From 59fc87f2dc9c998b70ad254f367c4e7335781f3a Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Wed, 30 Nov 2022 19:51:24 +0100 Subject: [PATCH 01/24] init --- example/blockchain/000106.ldb | Bin 0 -> 42912 bytes example/blockchain/000107.ldb | Bin 0 -> 935 bytes example/blockchain/000110.ldb | Bin 0 -> 1766 bytes example/blockchain/CURRENT | 1 + example/blockchain/CURRENT.bak | 1 + example/blockchain/LOCK | 0 example/blockchain/LOG | 493 ++++++++++++++++++++++++++++ example/blockchain/MANIFEST-000112 | Bin 0 -> 443 bytes example/libp2p/libp2p.key | 1 + example/trie/000105.ldb | Bin 0 -> 49685 bytes example/trie/000106.ldb | Bin 0 -> 2471 bytes example/trie/000109.ldb | Bin 0 -> 3059 bytes example/trie/CURRENT | 1 + example/trie/CURRENT.bak | 1 + example/trie/LOCK | 0 example/trie/LOG | 500 +++++++++++++++++++++++++++++ example/trie/MANIFEST-000111 | Bin 0 -> 434 bytes state/immutable-trie/hasher.go | 6 + state/immutable-trie/trie.go | 1 + state/immutable-trie/trie_test.go | 25 ++ 20 files changed, 1030 insertions(+) create mode 100644 example/blockchain/000106.ldb create mode 100644 example/blockchain/000107.ldb create mode 100644 example/blockchain/000110.ldb create mode 100644 example/blockchain/CURRENT create mode 100644 example/blockchain/CURRENT.bak create mode 100644 example/blockchain/LOCK create mode 100644 example/blockchain/LOG create mode 100644 example/blockchain/MANIFEST-000112 create mode 100755 example/libp2p/libp2p.key create mode 100644 example/trie/000105.ldb create mode 100644 example/trie/000106.ldb create mode 100644 example/trie/000109.ldb create mode 100644 example/trie/CURRENT create mode 100644 example/trie/CURRENT.bak create mode 100644 example/trie/LOCK create mode 100644 example/trie/LOG create mode 100644 example/trie/MANIFEST-000111 create mode 100644 state/immutable-trie/trie_test.go diff --git a/example/blockchain/000106.ldb b/example/blockchain/000106.ldb new file mode 100644 index 0000000000000000000000000000000000000000..f906e74fb98e73b89c408e66e8a14091b377b1ce GIT binary patch literal 42912 zcmchA2{hGT*Z)*O}t!u5__q)$I`|Pv#XMfH)(Ms)>3^mpgMn+na z%=2-NoHwm_FuOKADWQtf>RFp2wmO#Y(D?@0M3}_r`Bz$83?o@A=DMq&_P;V~Rk{)H zYi{agzJAsDls1{U*SdMl-OMc&pa~c-no-Ku;&A5}?h#(~rk?MPR#fQ+)w;8Mm19*p z>-{*3U&=XssM-p98K5bs#o<@HV%RVu&;EXfEoYnO)!USZ5Zn zKwgU@;5%2mEY_vl>yzp@xuNFwSQZ&>?OaJB(L5>k%$b6-U<^}KE0#HebvtA!r!6X< zB{^-yK^+(N{L6yMPAgkJ-{+Z>A1~uK4;Fx^W&&x6;O6sVc8dO-d}!+fH~BaG)#lOf zUG?g7MlNc4)zTGtGYMjtq$PaMIATLciDZqs8ku8 zcxHJ?YM07+KRexm`SAF%H&n6Y?Kw)`#+7Ft2@Tt8+vsW6>E-u%^U|_i$F%i^@gIA- z_sM527{nyqH`K|qVNIVps&aOkP12PWU7)BB6X~;5-{e$`7Rgjt7Q5v01@U|LWjW7^ zOE%@4*dg}5TRLrM0|ZhjwS~58eJ2YZH8pQ~t+sNVQFNza<{1fb+tme+9nU$am_i6k zRLh`&qn^pKGvya%CUr0)%6B+g?q%;>_p01|A6xRabhwxK5SY#o9Zd&JL$t*?==__U z_d8~vNiL7{n%Qmpy!lp@J9o~GZ0E`TDNw^A1E%(!qsdi1dG9Ul5#?N+j~rH{D@iN} ziC-sC((1k9$YQs}HkvS!3>YyyEusCjN4yus=-du;ZJHCXgFm(5P({#e@7NI2)0W$2 z3&IcRH7S?IV3Tj}rGtyPl&u?t7u#=K==m_fURmzt;>{bgv*MtO(L1bT4pxVB?tXca z%m3q*?D!*39&a+V)Epro6L<6WSy<#D2;6K7IRcuJw&T8Ti#WYR{?4`rJ?<_I z#ge40xoKO>d=($A1s?{R8s2#JbDy#-?c@M0Tdy0s_O4dPq@=D)kO|Ap+~)j5mNge1 z_vx4Do30YrwrN7^hP>zTZhI$n4AIf6TCyqNg+cqmNe`moI5Bx@b`$E~JE)Hr<^Iet z=2bn(zWhO7obw}W+xN}`tEa0T|858QJ^Ja`l{$cu4iS=H?5~NmIhYMJkq{?&0?C5Zq;Ab1p}=P;7p3+shsTQdt{;0 z=%PtsBTludr%6TgWGTOm++k9$b}<(Z-X_M#TfV!@wMxKPFo9oHO~c7giAqr2VJo?eE(f z#XdJuYSdcW^Cy>u%@KdL=Fqs8UZIU4KW*>Efr{3124`yH!5FDh1+S!1fuvD&YdAk& zzwdbaI;prb&tsXU&4+e~WsqsB@4eJGdxM+TP`#*jen${c)Sg(rQj!s~_C>dU=<{j` zXkd^@WS}=L*u8ju(#o5!R(oCb4rz;&=iI0Xlu#>EI^*VM6#?0dUK6csX-Sa(lJ_k* zEc@C@lOV~3VHQz7)h+k4WEAt%8{R={pNY;KQt>KeZ$QB};m6s_Zq7JAEm;3Czl77- z*AqO4EwsMA25zu5H4k!3V)(iI6^@oxNlL3{9cUZ$rgKq&$0d!3;yr1REAwS)L5$gJ z0`{D_cNb|XRz*lwTv5waJg<7=p_+ZPnYOz8wHIE?yHeNPhoQ6~=H=J)BE?sQOtd&q|%=h2l*|N2yJlxeMz0-1q%^4Yi%iQnO0O1wQ&_bVk^Aw@-16;q>DR znP%Rhjhb+)&z9$feo|j_Wjm95C-+G?hur#7eZ9xcJL5%4C*I`!c0H~b9z2kuHqe|s zD}L#orf#SG`k9NyEw9NPA|H{PJ~PmB_9h+e#Y#S*Ky?VI+QE|D`mb@l0@QM=c!oquMS^vxyk4%k{`78%!Z z7MTcE3_Uy{|3`33*nO_cL!LRURv6N1C+D`)Yv>)ri6-!h+3Nx=#~)OU@wBQoTGnXC zUYWaR&{W}kyT6`>y)zZz(5Q+NH*%S1-Flu1uxuR~p=cj9Su*8A z>#<13via&4TaAz0d8IMZxbE5waHNZx?P`nL7q7^MHm%8i>iNmL`i;csnIS*l6>H7k zv-slBQDHEdB_A1d()ZTfy#lXZUK_kn`qS|7Z-+l}s6XsJHhfZYl-k$KAjs0PV{jbO ztplUGriaM3*tTD_lr|i7prUQ7s6~XbjCgi^IJAKU9b2NA^KC1ylLao~U7WUZnJekb zAL_|Z>&}_#xK;gA!MV5+cQ{JMY%rBvQhN5?NRhTN!_(95B^|Q1^xLrF;hx*el+w!8 z_74?RJOFF7_ft8ywVkE1+=3&{d=nEX+Nc>(a)_7VDzUr5^Yw`Q(=sa8VU~nFwSnwR zh0fOaD8(n*tqu{{Zze2gP=58rg>zg&$YX}>JCkIwkIs zZ|0qA@Quu&lnVhf)lXS1U66P#Y^I6j`5EG3PTZz@X6V#?Pba%ip~CIzv1n<&xGFpEl=`yjR~9mR&FUco`(A zl<&*qf>X?u-b|M`t<2eXF5HFbwR+J{!8Ep%!aRwO0xWn+2f$BwgN0SMeX5IXcj3yp zp0^C@p6zH9tmry7^Jk=M&A|q^)VClThMz2eoPuZ7au#9Udxnk=k;|WSEGR*>EXgBJ2TzRKID-GY!YBUp zB>`{Jx^{gp^r&_Tw{~d_Gv%JZ#QGC@u&0^dTYAfz@#DPCfe~jF zoTpM@%P*@A{eD)s@t(T>CD%36AkAGuGooqsm#w3YYHr-$0i&r@#L~uhrCRgq-!IrZ zZGUy;$}_{A#@T#7xve~AM)+x6{grTtEKVfC;~YQ0IJ*3P^coM(QoUtM26x}uqQQ_{ z@h1D}#Hh@dvWC`pH-uFaI*na5RP1labC1p&N zD_6I)m93lfD5bee=8#&a>f`9uFsgr=mvF>cBy~{W1iKS&!T;*vw)T~k<~22b<>ZXl?=8PnFwRc2rXN9DE7VoH*GX$%?80Ex{F(F*n2aA^GD42&At*R;3vGTqh z&3>`f-L~Y8;XW-;)_TU^WUgLmDwgY!!&&fQTt|TI!qoG3c_(a74UCMOFF)eP%?%(< z@ z@vd$LGfcOQfNLbup`NjjbvW2}3|u^-r7iChQu)F5Nm9YHyC1jSSl(u7BzRm0u4=V1 zIG332BcvNYUGk5ZGc7{C`N!6W)x6acx~FEJ{+2Ok&fPT-M?GW7lsh@#pO`q-b<=^9 zUDIz~4ynB3{&;xG+(#PnwQ<8Lz@aaQPCBq=p5C~(kFKkPSiH=flQ`Mc$N9i{;p(;> zX0}|JwXlvQuNm~|%OPps#KWHqwk0_)R~a=q_s9b6YO}JvL3un6mhP$o9j#mj=W>SV zLzzVnim#en*<$-}Z2OBDnWKzbZYspQ&4^K0@^m!JW%h<9*Wb!5xjk2Ci}SOs(O*_Y zTQtau+}pqD@ybZwjYo!_HM$H*TFY3R8!NWx+Y2U%H&3n9uAO;pn63Llo(W}%ZTtLB z4LVS?@G}(kxx6s>qnEA(ICmLTPbyz2w?bs?wk=OaI$1lbE}Ly;GwnTC&=$PDaCuZ} zk=2F?Q|}!e^Yen#!^%M+cia*zTr##qDI9D8XRQ_n=ay@ZSGTBt@R?0VQkLlZ-g!NE zR@9BnM<*8vEE13YnsN(L`&w|v)quNt(RG25mqin}lieRx=^3~;@h)e1n9LK1*R6|( zQnse&Zcb%s#ItP{!3)|9B&)-0_$NyY`<8J-dsmrC$+(ElS;IVlLy}%b=~3WR4P!JP zFSQA)a*$kKc59dMG~Q>?JnxKbO$(b_TOPF!2G_pfI$@Nzc$3PQ=~*YUH!pLQG%6YI zBYP_*vcAH`E#2s`HFywrLejhY;s>2qRo*)9ban8a-P$vay1gz9ueX@A*1_C9ey_Z$ zJ_z?MKaV;@y`twFs9I99Yom`~_R)sIlJ%?7noDY?eyW?!(R~1(S~r06xb*Ojq{_ON z9}PXE>Mv?a>+$+<$#$xyj(cgl?EJx7{;-wWT)m#-Vs{vA#TU)rx<&Ad)wcEPZH=Oz zYco|H^J*fDd_j<|15Lb9Z+7uaZz^R?+g0G>Ej7k;l_O8$xhl_~E>-7>@L*U-C)XSP z+3rcDmBU(>y+}&hX};}b-Rb?znA(Ewc`Bz~ZOgX?FDmse>iLk@o$`EU`5%>Hi{|L@ z8?KwRdVl58{ZVO-%CB1I!3(;ke0=WgKf27jT9>6#GfXggins^s6iQZEK6^jTjF4@R@peU_{= zij?(uW0JaaC%d_3+fS2;rTeanJAV*_sZ{FQ;M)4V&-Q%U$e7fU#4ncny++kYR^^A} z*hr0SrOTbWA)f|d-^WfXv^uD`R`P&qbCdJg`(fKeW|SB&jrcwyAi6@n)(Y&XUY(6^ zMp_oVoL|ogwvH~hPd{R6bE?pC#)HkmqL?pwCLMT^U>$?fHqq_ zfq{kXM3NV#5KS;JnF#WM5!D2P{fHz#%q5y6V7V5N90UugB$f~oNdZ_)BpJsymGaW| z34%*cZ*JzHe+hvHpGM$0HvKIOUVIt>7&PQi#w!B8d=nBdOpiQK6as0(F`SD?4u&wI zq#pt`7>9Cni-z~CqHd6V}Jn~3o_&~>Q9)ed9$)WI#!KV?60ANIL z7%(K?@g-;>FgKA@0Ulu6Bw!UAA~_s{fy}eRn;r<#j!*?jzO9UeO@oE$Un4-CPs0yM zSY77wj)dW4KCbI|f*NR$`G{tS5A5qnHgu6>LkT1sawgf($Y0rza`pTC14<&)S2OrP zU=)l8Hh%(^>JoL;VKQk;LJ1Q25lIa&ppw|aNF+637L~*j7$T_!7F043NuG%0Xt1J^ z0!RgnNR9yqDv7~~L~<;+Qpp=g%t$21!73_Qg+ygUaycSy1e*&=dpZJ5xaFowE z0gJ=PBlRE?*v<*#ks1(@oC4Xj;TW1kB&R|?mBg?jA~_98sU!xB5lMY0r;=D+Mk0aQ~-EZ!rMGvEo8#42h;(h#0eNvzIIB#q!Tk@Q32ZkHpx#_&w*OyWw1j0;OAMtV zl2+hJB{8gzNLs@>+8!ilEm_5D1OB8vhY?(kJkb_HNP7Y>)&Vih#Sq2k?1vOn3=Z(x z!A=r?AOw(-TfFv=K!QFir2a)zbbur#`$7T+*b+%cNTVHzp({kv2~N_EL=tv`GG1rM zA%>3ObmWOHP(Td>!|I6S61YsY#9${PxfE_tNetH`lCDriC9%2_k#vI^Dv4EiiR3b9 zq>@;1nMk@rE0x6RJVeq1-cm`dCQBrjLkE!z_<_I(#4uOD54GY1tbRuxxe~Zo#AE6r z%mpI33Ite0O^mBSBt1clNctf#n1PqTYLKCi#42Xwk!wJiO8!8w5hCeDuv{XEF(-)R zS{O|wv8o=C^oEI45-Us+NgtR-C9#?_kz5DHR8j|_su0QbFqcYVMJ*z^0Txop8we;% zBz?h-N^V0cRz%VdmQYEo)=nfh!g3-RfI()&Iyb>u(;*2M`bi$?4}Qct{Yw5jPA;^S zmp1^m@Yy6_bsX}@%@EEaJ_#d>5y?P^A?@+A{O{BTu;JZ8V34f|9uNO}8Js*Z2=dmGnaj%S18^iil(Y zin7YNTRGn66F_yePzRz$cH22{v^ubaGgaGWvog?-W>sVsFqlzlt^;m zA(g}!jzlsN>WO6gOpN`8UnoZSy&(n z+Dro0Fh>BAy@NIIsS`RRAmK|A>>~VCP0+yktFxIv5M>ArLXrgFleXqy!8|B3`K)<~ zeu3OfE~qvQ2aRM54F_U{^dA@q<8)RLCLiVR0tO0zKPlGI_G5uPOd;)OYv8ojP$n5i z%u_)Gi%4PUHW(Aj3Dje8!4q8zLJK=Oy zKLSXC4Ng~WfL;qnpbE(9(+@*)p_r}C4&`7W5D2o^n#8t>I2e2j4;g%#bPgg>0L*0d z_8^Ak!xp09X`HfpfGjR9Yv`Mizz^7cZ^jA}u(qdfu(%7lZg945wqk`z zSVTN+BL^#QE?Xc;R#KmnD)YIiV!N@2xo zI84V0%jdz2jsRMJ)TD33U~EwBTRV_^AME=^0ILWu{DG z8uksRq9y@blO1J$on(vQBu+OZ*@)R2A6a7#^ z>S#JFC=pePb~uJh!|J{cM~bL0uP?d6kP8SR3{;w2Ugc71^x%0pF^uElAn(hQRPVDL8N zk`X3O2m`mFkcL^r{4m5CZfc&Va#+Ch$A7$>0~>(d`4pO&mu4#u6qu|`*jthQ z-N5MmyamRDAl}e<3`Wq_rJ;4)LCJyqz~G1~6A17rei}hDutysR2VlI9C}AdN{kV-X zhK3_{4pJ;wv2O2e-K(S5vFa4YPpW$RdGtkpuGK`>4R0Ytnb9rG{QWTyW*C|Y^M>Wh z=8;EWgi1(YSPBPVSPM}mK*N3_bI|(d@40@o-woK~nY7=+eU{#ZOY8RSK5>riRWmc> zKWQQ{UzjUnD^&!Aq`817f)W0xBG2|4#@%f?QZvqDQPG^OKTA?i2$q?AJEk#M!>ag4 z`!dDe}kO$DIgO(4rGmWQ`se`5b)JXhS8}ZvXTr-cIb#Z@Wh(x%r{xWaH%!Vx) zX(J{!=PgS3JzaW#me| zCx<7h{2anHJ40OK$WaB2fm+NbTI78vc3Pr=);`#(lX(LWzLj8<5HrAWbhqb{8Ou&R zNfyh}o_RYq)Mn_?48<1>QECM$$&ofuzsIEahp7-_78#gaB{DE28hCj{mKiS}fN`&A zcQhWIlN4vEMRV^D?2b8>!VJ~3!pztf7FL*p zdn_~I*rsHx)JH5ga5jIyS*=+sHIl3woR(T=ns*PoIJSfPyM5r$LJ#RrKTb$4i5Q>@ zS1@P32v<|VSrI0ugN4?QBy9x*$fEW!Ss^nR-2pcYUay{uNbxbpxLtR6DIVOw+2LgW_6UMFUH+%nSA@$m@{Y}O7 zNo5(@S<^E$R(vnldExh7K6T4I3zeTAuI#$=zjjQfzZ_Gp@^8n~GyT!(nJ-y6FHpaW zfsOr|=P3O5&Z*xb`dygGm_Vjt&P(bL&~n`*;t1S6cm7V4QW0vnx*<_*tI$gScmy}#JE z>>cm4ib4hLimY22*DR#(sd`H`Hx1OnmS|BRPqjenjiD@}1%_8pEh5rKy5w_K>F9M! zcX(L|+}*QZo+q_1G$B~pP2XyAg2O;9HWMux3#k@pJ=1_jHdypYwP+D4iN4(NB6#E? zg)>Ey!)w163tmupmusT5hFv+l%yZU2E%?lY1w!j@1f872PdpRG1AxcGGjW=dF%Om; zK7}{H^@D(e#u|ljrxvan6P_Qq=3T7hvN~7iiM#f$-^UTUG-iM@T)~lMB3xljmlV11 zs;wH+OoY>zjG=+a;Udg{qhDH&zcxFw;;h$&H?qRtUq0nj9uvyeXsbVZSEtcF?rygT zv;W6bgkd&cm^XK1P?{oFKOZ(_YV=Q~zTgU5tboKY^dFt%7{J(XlK+zr6B#kz(rtqH zhYh>3__MdakMw(|#8Z|d^Vshg^Jl#Hi0Z%dVT_A>r+>#*J;A@pZx^QcJNWO3t*|op z4?ay2Tg^l2Y5iK}NJ68Ah()VfvQv2Nlvo759(llOy z?+u@leUkspMva9TKr)ih+Acb8v2AIvj?P=Gm`vww^X6fE%b%(%b*8#q_xGJLB(+nd zL1_3Wj>Pqt>d9~85B{4PB*qh=iBZO4ss@&SK`qTku)LY7alZ4u@vE=$sr3hUY>ym% zZ+Yh6?8@tBraU@xX3@PgSMzHF)tEt?SguS432SITj&TptCHL`_XaryY1P%1CFnnO3 zr)Md|U=bq`(&Oczk!twWwWEf9gy&dMb>x|j7lGE`` zYgCqG59|^d(j_OP>A;}e2|l{IV02WfMe4K}wUs{v*IsyTzcJ#-DBY_Kv)tuQa@ zj4hLW{-$W47ORLBwb5i?{`jx`SGr#ZDJS>jhA3I1iUe)U_C)HwFor8Uq8a-dI($!FIhtZ+HYVTXGMAyIfXH9CuK{3(&VNi6<$pP}ti69?GHRO` z>tqH!^};|1El<b1eP!H?iDIG=M#bNjrm;Ooiads?JR?lw<(7}}BQ5H0 zqHl$mW5Z>VvQfbIg7tLc z-Oo=a!|WdxiO~ZMM3fjvh8;;r+HG1`7)cWndI_4}peY&Se)cm5M-A=(71^hb!r~JP zBFkMd_IkG;H8CJxYyD>#T`Cym7!BFqxaAdIpDHJSk!^*c&| zD`0AijEd5UwdFy#xUbARH|)ua@f%?8@d8WD#L^?uUg`)lWMJNaF9>oAC1D>zUYVLDp2 z)TyAPqv6!4V3;QD64j5wiB9f^%RlrLG}WePUyiO@np!6r+lt}a4<%hcJ#6f_ zoYy&J^%oQUxow^rB@Bj)@w4UbbHl#CR1&X`_qeQZP^#@#fQC$JahV8QB-b!H%fjJNJojrgE?eo z2Fr7>#R+bbXfRkl0IOm3m?HB8_^y`Qv7X1!pkSg;%Dj~2yFyxP+>Q#EOdmQ!XMX=y zliwr?lOv$c9y%W|%m~D3I*S1xR0*%H6uWufQ_sH1xIgp4*E=C9ueaqiDZJRN(w*re zyDEiipc1o5*XItWTA<{+VRTkv)EcTqYRX(!@y%0xW5ly{LTkU64=Z1jeWox=W4pl1 z`?4>7Tpy?fo5sa;45|jo?yIMrfpPYz8vk>zy^O}iwYC|;OrhEQK^T4Tw&Zz15-$c| zb!cj*7c^}wcpUsqgpSU5zcXZ8`ivD1bDzC+v6jpjyTe&~@bH0lI(@znBlo0@z@HH8 z{xB}TAHPyatOMZT9~cbV*!35V3hT?ia8&;ppLhG^muhW(`=uT)fFy^|(VIgebjyBC zb0j&W-^``Q67QSw{Sa?j7qq9<`OuZni=V&05V!=3$Ld!dIN8^X{-Z(h`JvQjoX-Q+a-;|69m! z;+vF77LrR`Qx6V^Qba>~of8%b(y6d!=RU{KBNE2unmR^RcQOZm+S>L?AmmHZPe;YM z_Zd6a4xEvL={jjoWzU!lWscH8?-$S=ge<@y)rp?(e zDyYlbI>Opjf_Z#kml%_-&y^>ALfkdB@ekT40*_JgNPlomZRwuH-~Y3H7C*y-G`ZG} z`XH1jyO<=!e#mJK+ews!CZY;l-Tgk13XCyCiJY6X-!(WG4>yX%Fc2mwF$P3N$#Vq+ zJRj56Q8ehA(~pXj2kjkAOJ?5LD!J>e?twLFTt`H%Oc~hofu!dfFOi=AG!Vp^_{#z1y#5VhCD5D?<1NP%Rv5|oim`It zfVRyf6MXPC&{9@+Z(X-8^xQY+b+<(Vv|cB2xxab5O|0IIOvit4MD}D%ia!7H5GZ5X ziPe(>Vw)GKhlu`pIl_uZ?#lg}DKgiDJR$0OoZV`(U3u&w-&CT+e(o9QA^eD?Haw%# z1>3|4dNixRc)(PPG+kYfhZ8ufZy%XpocF3CIOeKr1kWN@%Zf?60zVjbjUA|k51q8h zWWJCwYhhum?~`=KB+x_@+XF~OEs!Ljw-tqIz~u51WuGC-PCeJQOI`Es2VZ{PF7vy$ zMTd`hYcOEia0Q1FjhYhZ4A#WYL7qqSxvCj}(ZOlPm3up6jH}2E?>n|Lv^7m^Bf?&8 zUNBRLGm_hJYBS4e;lBPLH2F<%=s`r2^gDEfQ2KfrjqNZxE*&8ubDcH;HT_Wy&-qW+ z&*EadxPQQIyx6%01)e$9(bi+m4jdsVqD4kH)dH(mffvOZG3FN0g6rA-ZV#dUpY0w( zjPc|}IWI`Z|8ZEK%QoKrmD*u_45oilJFKWOU``KY;HXA^vkR)sUVOgw!4j`AI_!;J z6`x}j(&|d5=1rNY?7;d9fAyEB75^^}mVWzp2-Pziu)PDvC~DO+8!(a~oec!H8nSIp z-Kxt)32v$`1&w1g1=D3Y!Aq56*e*}mLwE3V)WIwAIwap?(bFxCP@ zFb#ym6oRlCUr%l3hU_c{wQV!nTO!N_hFM#PTl1PL?44066b7lIO}WN?9yli!6J?4% zQftJ3ANWoa4eSU3Iw!E;c;K8^LA0n1CSB4K>LUB0VP~Z#frpUo)gg3@G`Rx~BrM)G z$5C8yN~rC=DdWe@Zri{0;^S5^A<7t)YgB1$ZryLZlMc(5m{77$bqE_P(ed1 zjG@~t&-HJgczK2^ZL>A)d2A(s33R={wr9|uSJI0vTb7r3w|wPM(NOIz)wPS$1gl;- zEP8pa!jbo!*1i7075Po#D{qo?Cy|aPyb^4~Ng&Pd+=T+Lf_xMSY_aHMV6SVFUe9^; zFX2@}*iU9~AI6Sx0Abu8Z-w#o|H4~|p1-J&VZ${9-h5#JHvL7;6uq-X2Aj%hAXB{ zt$M+$KEQQw1#cz#H0>k$2rU-iU<5qSCkyJ}#R7f^eP=tVEksS+xPL}8uU+zu#xc30 zvfjVn6W#g2=f?S&4r8wRwRNqK+a z$BY_Ts+V{xq-F@+$&h$)$mrEBdGT}si>9t8g?YmZJ+}RYA0s%`z$|gfuNW&={7;rh zy%us*W;@9A@SKlhyQTWI&GCQF)fz#VCpny;Trz2~nE)5adlTh~92vJ*zH9lRCqu8V%X96BGOdvD4wc?D{Nys9 ze^Y~m43b2Pj4-MNx)afqdSmRQBC3VjsfnrM%z3|`&m8hKardG1%UUPe9Ix_ysQ$&) z()r5Z#(_P)o@h~9le_J6w zY^D#dJ$ffr{CIWF_&W+umsthP=T%YP5#)UiI;Do;Dp`&Stb-QK+7PZV{ zmp*Kx7R#2mAJ4whw3bnu`oDHjR=-?Sfy{3g)q_o7+p_2OY?HzETK8+3BSF8hZ26ai z`nPQ|S~O)Y|Al^I#A*m&^=y+t&cv%FL+{sVr)n@GPw42ip<)*CdQVjaIZj9BXDluc zYSKEU^!>uW86aUS1dwUaSU~JA@B=w1%6Okb0Ji0kT3EkQ5BW_a98L0^oU)7_JObN> z?nn2zU^_l37$I&L!*_Y#sVS*L!!AuKh_-#J>!B1dL8D}n|LrK-1@_t98r=Oq>^$7vroBQ(;|`|+z2lZ_E~7#@sUUL->igW(3a#y1=3`6 z|9Fo*g6bQ3lcN@v2ex{`m0tl)Q!=($w%-){C-33Bx48V+16Qu~m09KI#vS-LMdb78 zgR884C;hPfx@kk2&i~STObQAP|K&cKjuH1E@Mo7Db}yDSpJvZi7VH?FeywvP5zd(A zh|e+4YE2K!H%OKo^w#TySL4ZvzSYs4J{6k|axCJ0Igoyf=ywv~2oMuYulVIau-F-f z0_B3E=b{kZ0*QHGPHmuhjHHwQGF`+lObaCFT8ix)r$$=#ZJz(m{2a+;jDYaOZ6n4x zY2Cbj=y9mjoe`~{>hI3{JWvY~$PrF@H&p{Y%Hb@XE7(SHs>c5u=y9f?*Yy)r4fLdl zi$sk;y+3<>e>aMNMK0uBN-41Hofxl;e)TtfBZ zl74S8!J<&u{Rer$YWe-9-#4h(xeP>JCjD|Pxr~2BUeLSa9DDHMB(BGfycOxg0i{`k+b~EnBWV?X!T@}b;ZNLL zV?JHYv6D#1ZJ0z048kE=(2A=%cmL0Jb#8__UDB@+e_EoBA82C643;B=bZl2KoeXxh z35VZH$Sv72A~8$i^_xjAD_s^9#ePwFuTnmH!`Hm01DEs#r2F$advjN;m2zv**cI_V>sLVd>Eg>^&i)YtwztH=Grmn#>b=^Z! z*W{-x%)dZ!Pl6Dp7=U@bD8;`Zq7T@MwuE%d^(bCZ_Ty6mnY;@aZ?32)o7x zT>f|~jGonRM*sizR%3s8tDIZ^>aA{Jmo^?I*R~r7AIEb0er==P3R`FY!CN^Jt0?+H zS1^p)43}x-fo+MRlh#2zJ?HuKN${+rJ?!%Q(g@8BciWs3ZyjIx!%R9YFYn}liNcU2 zTAYxfT3}p%h@@Izj7X}5)UY=tb5(ksb4?a8{4o0?#`WFjA-9y4xi+Q8rEooDlR_xo(0&CeJ|y>ly>ay`5YtVReT zEK=FWcAe42r5N0vqvFH*AZx5D)iJB&)=XK!ceewEroag$?eMQgFE`!#`MbSg5-YcF;ZKk^9N5L1h!%}` zq>KN!Ao0s=iQlCvjHC!*e_RlDn^nJQ`v2Pn>HKy_LM+jGQ_}Li^S67O*Ud-?S{bi7Ebl0*rYc#V{SPjP?E4^T#}8^0=vh~bNTiP4 z!$aw|2THfhYtP~A(9>Rf&@+2FYwO{OMs;$VhySRY>s8p5lrzvK7SgOEuV+IphOEF^ znlE60A7$$4iH?vORXzRM#^mdhHjnxIO>OSbZHqk)z4jMe`MRt7Gw(n(tchtB^c+-# zv8drC%_y)#^63N_B(kp<8lN!)Ls)H+96p6AjY^}dQtMY0bF)7S&$u{n2R*}xXpt*N zM+8gp-~{apY)zwDU<=g1zHlO1T+g6dU|W45mG%XO$rCNady|vy#RC05fr|wglWCKg z^ko=+2h-@wu$u<|tvTdRk}7JDm*iak7sunM+EAC=10oX`2!nQ@;13Lh-80c|a{iO! z$t~FPV2eP0-tzmF560eMX9{F7#S>H8Z(6Yj?J#B?S@Cz7+JHJ2fq}w)xt^xP-!M?m z;)B6!U{9i-9v}$w1^wFRD8fu=Ts|$(aIkGb*YuqSOK&~CC>JY#JG9jzX=S(j#OYp+ zGQXTpzqt6j2$Qjhj7Y%{I_%g|1Ix&Q#KD->M5{nz>?IF2L|>8C*UOx>YnkdPapt|H zjHTzV-sGvd>b58?-RbVXSqDJ~Hxfk}o>N7zE%tDq+8=iH9-VS`SGnx58QEAPe~Rzv zMShu^K@YBIoSND8?wX(E98urzK?AigptFGDls(BScJ|#zCP`k&wgYTC22B*u>E93H zCrJZgBQB?jLJ&<}kt>WqL18vOIm82_NF|4>a|hJ%D;2Z1NNbcPj4#}*bZE(-)Hz*~ zCDR5O777>UH@^uSn6RuNdvSJ<;7NrcsI2LnqqDpTFHsON$Se8#~Ytn7y$zodsC@2?Er*v4ag@Bb7prH)-rU@Dn?I zEO4X93%mU zat=vF0Xss0yYC!y?4TO({<~XGM*ZcjCwu7VqPz8<^&SR{?s3oSyKMp6dj95b?>)Io zT3d&2?3Vt^drwBv)?x%(XzugW*v93mzN6I9J;b#=_f%O2VS8~qLCy39dh^LA!Jfm> zF%$)-tzaQ0xKiJaZnc}htw1*wMSF_TBjeFMKR*REQZ{1OpX|BVg>RI(&y+ZY?{v}a8!l`wN@(BmgKi6% z$W}Kk#4kWmX0Wxu7T@JCmKq%vVS^l%LU#$gq!SUVg~FA;yaFY!Z|G6_yOEg?9eR|A zo*N@iH<)r*UeuHk}M8wfP8j{#aE8%;^|lG;7eJZ$wGIBl;E+>=G0Q zG6q5uc{wPLwX5&2eUw&ucjI;Rq!~CzubsePA4sN6#mXs=LX8roGLE4`fHDn-&^KZL zA*|`^T#Q*azi-N;Jhxz7C;YOL+0c6d1V%F3%p?~;U?ecnjh;Az>j|Ux)-jCs2p;?7 zIVcmVoZRbWaEXHz^TD1*a%38#b1#1^`FT7 zMrVKBZ*;rjsaZO2Z-R-|*{}8zaf|=r5)@04PH7}iN$e(+W%R}$8V+JmI2>m(L^beg zYZ*zaQ4_b7IOv@g$NHV{1HSeFwEcb+@*cvuDl#jIp zUBma22LMyNS(YKnwG{Y=5b#NjT-XJ?B8*nqNE!Jd0zFr64;lGc`-lRApUZVO{Nw|r zLyOYo$X_0VL`9Wud1Z(*_}LzEqN1lew~}kh8ER|~>|P5{Bl)r0$lcqah>tOd?V)2Y zY9#V#FXZ!q6=Ry{V1a}bc*q{iupmD_X24;#2M6244^b>|7ia9xh9A6O$yh3CC~&Y4 zGTDY4tl|uTz%~@Pa}CnjWB+DPD0{3xR|S-^>$tX+i>?>ATm$FX5sZCA)t^mph+W4x zCOTLowGA%vDjVSo(luavh%|nLM?{+IM!2XES78@q3XmSHAx~@zV|KGQF}{+YZ?`i) z!9-qfEn!hHmDat?20_y8-esbLm2Mto*2yvW*gm47BAKPkG9K`4cN$H`(u91S$k&T} zgUL6Je6NsiHTk|I-%j$?An@Td@?Ar|$>e*Ee6NykHTm)q^N=N9P4d+z-v#9BO1{)i g;FOeh^|x{+Kj#MXDZK^dzx}iB4BDo$-lX>b0g8FWg#Z8m literal 0 HcmV?d00001 diff --git a/example/blockchain/000107.ldb b/example/blockchain/000107.ldb new file mode 100644 index 0000000000000000000000000000000000000000..8f041675bcc7735ec2e5271065a83cc7c1014689 GIT binary patch literal 935 zcmbO$@gbB!lR1fX-Q#(u_FnRif4HUp*#R%d!^>@j^9+3a&-gu_@;XJgkMTV-0|*>C zaDY*RIU(Or&cN_uP>Hx2_s#mWJ%>{z{#u*zWNcH3O4gWVQqK5-nSoKC;Sj4{N4rk{ za{npCD_i6ve3sqXkYu1@sBc)FQ=k5B?T)2l|K~G4WMJ?- zoH`5%RmZ`+9>&j{I(3SSAemmqUqJR@1|9}Y#+14M1{TIIoIX5^j2et}D}bE0k~(z^ zj4X`LfHa8zn^#AGLGuZ7M$;w+h7X*2JU>1w|_m0O_t!~|#zU|Bv zsmnsH(o?!hgg-2F`s;9IvU|eYW>D&v~?$6peSm{ zFnK}P3wd$rGoj1=H@iNYbl^u`w8sPKnK^3@Fed45eVn{S5uqSTk%46=qpQ(BMg|Ca z$H-vO(Ad))z`)SZlHB_6Lc@YOZbpU_t%l2Jru<`iHm#%AHi>^nu1IYFjVCVu`a}H=tQyd$^cc6P?*g)nmYAt#awp2cM z&T(Lx`RaDjXNHYl=!%-6%@%^poeF!(FwN-&nsafL0Fw#>uR?xCVsQrJ56v%iGE6*d z>>Qtrgct;RfQ;85 zMmLc01jOh9CYPeRX0mD7abK;L^#hIf)WO{WI|AG8Z%c=Va7iIKc*&TD4wW{VW^T9X2tL5PlH;yP;d9 H)crO9s!%|T literal 0 HcmV?d00001 diff --git a/example/blockchain/000110.ldb b/example/blockchain/000110.ldb new file mode 100644 index 0000000000000000000000000000000000000000..9414ccb2555f5759fecdf1a9cb48545a4b83eb7c GIT binary patch literal 1766 zcma)-3rtg29LCSTy`{aSEti+P1X`%rLR%D=kf{?;UI7f-bc%|TmsF9$bRvS@)C$Uc z0Hrw53@lEJgP{`v1?Pq=lTFzJMck$kRL0OPN>soh;LhzfH8HNcIXCBbPQLTy-sHRA zJuDttjO6Sj2fg#zgr&o)GIu|0w0m-QSfe|$`od1%VB4TVH%@Vu0R#kMuC~@zkg+R1 zn7_8S*3Uy8eKGOJ_?{6?jy4lX7nRpdmx$M=d~*?G1Oi{w#!(g4FB08JtM~U_BOJ_G za-EmsJ(zE7>kPLPXhT1W9*NR`EdffQs<2BM`T))%c%%~>I)ft-_BeKH3*wZ}UkB{egJiFuhH5LJEp@Ks4ezsZ{2uMh(1b@O!BVCV%GK{Vrv4g$s3Awce zjcH9CUCvi*!d%LBy>B~I6*>{zWr)xkPbGbpkybNG>n9g|pFh9IAwZO{<8W0!C-iI| zd5*MK8s8aocW~)geDvw|uz}Ln$C~AleJ%&q)wM#BZ{zLc2FY{5G6^D@A$9g7pufjG zKtbAVCEMc=(&i@@+;Z0%X-hzb))M?q{X5Dzgq+~`hEVi9)-H;rt*%rZS`jw#d;QuJ z>ai}f%9uWGKYFEsJ99&ArRq(eS;k3<_2P)4P}yP%dA3k2-6VnR;wd_Yz(!k!ZwUFa zocFfvYkcdPM80)x|AU6Wf`S;Or{1ZunRxWwizb+3DWu0fV(dddViVwjjhZYNBmeA= zrAKD?y( z*-NBCai%(PgBrXEj%|s#-m>6|JqeC?iMcYux~YuLT+v{iJ)<*Mf>$r^0 zTn%C!!aAKJTPosdHfAKHt_L5vQV3KTkIR$#*&xb*!Ignh3{x1;W3XbN1OtzOVhq4Q z5iY9r^aO4p8!`a3f|96Cm5CKFw?)9A5``n;v(?w&DG82fn2ShagSFM1G46!v&qHCE>EyYPG1j<% Vzgy_Voc`}?$rJ5v>Bflbe*tUYRy6 L1·0 S·3KiB Q·107 +07:44:40.894836 table@build created L1@16 N·75 S·3KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xdd;..\x87Dw,v19" +07:44:40.894908 version@stat F·[0 1] S·3KiB[0B 3KiB] Sc·[0.00 0.00] +07:44:40.897612 table@compaction committed F-3 S-318B Ke·0 D·28 T·6.361942ms +07:44:40.897743 table@remove removed @10 +07:44:40.897809 table@remove removed @5 +07:44:40.897868 table@remove removed @2 +07:44:46.230801 db@close closing +07:44:46.230990 db@close done T·179.078µs +=============== Nov 29, 2022 (CET) =============== +07:45:07.132700 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:45:07.132848 version@stat F·[0 1] S·3KiB[0B 3KiB] Sc·[0.00 0.00] +07:45:07.132882 db@open opening +07:45:07.132963 journal@recovery F·1 +07:45:07.134880 journal@recovery recovering @14 +07:45:07.138258 memdb@flush created L0@17 N·35 S·1KiB "b1K..\x1f\xd6q,v115":"r\xd1\xc2..H#h,v142" +07:45:07.138574 version@stat F·[1 1] S·4KiB[1KiB 3KiB] Sc·[0.25 0.00] +07:45:07.150201 db@janitor F·5 G·1 +07:45:07.150219 db@janitor removing table-13 +07:45:07.150272 db@open done T·17.379812ms +=============== Nov 29, 2022 (CET) =============== +07:45:22.714330 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:45:22.714469 version@stat F·[1 1] S·4KiB[1KiB 3KiB] Sc·[0.25 0.00] +07:45:22.714495 db@open opening +07:45:22.714562 journal@recovery F·1 +07:45:22.716495 journal@recovery recovering @18 +07:45:22.716939 version@stat F·[1 1] S·4KiB[1KiB 3KiB] Sc·[0.25 0.00] +07:45:22.729254 db@janitor F·4 G·0 +07:45:22.729300 db@open done T·14.787096ms +07:45:27.631654 db@close closing +07:45:27.631778 db@close done T·122.12µs +=============== Nov 29, 2022 (CET) =============== +07:47:50.195416 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:47:50.195551 version@stat F·[1 1] S·4KiB[1KiB 3KiB] Sc·[0.25 0.00] +07:47:50.195571 db@open opening +07:47:50.195625 journal@recovery F·1 +07:47:50.195761 journal@recovery recovering @20 +07:47:50.198242 memdb@flush created L0@22 N·28 S·942B "b\x06\xb5..\xf2҄,v151":"r\x87c..9?k,v164" +07:47:50.199098 version@stat F·[2 1] S·5KiB[2KiB 3KiB] Sc·[0.50 0.00] +07:47:50.212673 db@janitor F·5 G·0 +07:47:50.212730 db@open done T·17.148314ms +07:47:54.508347 db@close closing +07:47:54.508555 db@close done T·197.943µs +=============== Nov 29, 2022 (CET) =============== +07:58:29.865734 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:58:29.865902 version@stat F·[2 1] S·5KiB[2KiB 3KiB] Sc·[0.50 0.00] +07:58:29.865925 db@open opening +07:58:29.865998 journal@recovery F·1 +07:58:29.866162 journal@recovery recovering @23 +07:58:29.869386 memdb@flush created L0@25 N·28 S·938B "b4\xdd..\xa8\xfa[,v187":"r\xced..9ܕ,v200" +07:58:29.870371 version@stat F·[3 1] S·6KiB[2KiB 3KiB] Sc·[0.75 0.00] +07:58:29.882379 db@janitor F·6 G·0 +07:58:29.882415 db@open done T·16.477753ms +07:58:34.095856 db@close closing +07:58:34.096035 db@close done T·166.305µs +=============== Nov 29, 2022 (CET) =============== +07:59:00.168427 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:59:00.168581 version@stat F·[3 1] S·6KiB[2KiB 3KiB] Sc·[0.75 0.00] +07:59:00.168611 db@open opening +07:59:00.168689 journal@recovery F·1 +07:59:00.170441 journal@recovery recovering @26 +07:59:00.175443 memdb@flush created L0@28 N·28 S·941B "b6r..\xd5\xf1G,v209":"r\xa5\xd6..\x9d\x15\x87,v222" +07:59:00.176340 version@stat F·[4 1] S·7KiB[3KiB 3KiB] Sc·[1.00 0.00] +07:59:00.189416 db@janitor F·7 G·0 +07:59:00.189462 db@open done T·20.838718ms +07:59:00.189544 table@compaction L0·4 -> L1·1 S·7KiB Q·230 +07:59:00.193367 table@build created L1@31 N·160 S·7KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xdd;..\x87Dw,v19" +07:59:00.193437 version@stat F·[0 1] S·7KiB[0B 7KiB] Sc·[0.00 0.00] +07:59:00.196163 table@compaction committed F-4 S+638B Ke·0 D·34 T·6.585113ms +07:59:00.196303 table@remove removed @25 +07:59:00.196360 table@remove removed @22 +07:59:00.196413 table@remove removed @17 +07:59:00.196466 table@remove removed @16 +07:59:06.057455 db@close closing +07:59:06.057605 db@close done T·145.115µs +=============== Nov 29, 2022 (CET) =============== +08:32:21.921182 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:32:21.921422 version@stat F·[0 1] S·7KiB[0B 7KiB] Sc·[0.00 0.00] +08:32:21.921459 db@open opening +08:32:21.921554 journal@recovery F·1 +08:32:21.921764 journal@recovery recovering @29 +08:32:21.924936 memdb@flush created L0@32 N·35 S·1KiB "b\n\x1f..\xda6H,v259":"rP\xf4..I7u,v244" +08:32:21.925138 version@stat F·[1 1] S·8KiB[1KiB 7KiB] Sc·[0.25 0.00] +08:32:21.936959 db@janitor F·5 G·1 +08:32:21.936982 db@janitor removing table-28 +08:32:21.937051 db@open done T·15.577369ms +08:32:25.249429 db@close closing +08:32:25.249611 db@close done T·182.906µs +=============== Nov 29, 2022 (CET) =============== +08:33:22.413828 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:33:22.413979 version@stat F·[1 1] S·8KiB[1KiB 7KiB] Sc·[0.25 0.00] +08:33:22.414005 db@open opening +08:33:22.414069 journal@recovery F·1 +08:33:22.415690 journal@recovery recovering @33 +08:33:22.418834 memdb@flush created L0@35 N·21 S·715B "b\x80\xdb..Wa\xf0,v281":"r\xa3\xe2..\x1b\x8c\x18,v273" +08:33:22.419091 version@stat F·[2 1] S·9KiB[1KiB 7KiB] Sc·[0.50 0.00] +08:33:22.431309 db@janitor F·5 G·0 +08:33:22.431343 db@open done T·17.326534ms +08:33:32.547907 db@close closing +08:33:32.548105 db@close done T·189.939µs +=============== Nov 29, 2022 (CET) =============== +08:33:58.629600 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:33:58.629730 version@stat F·[2 1] S·9KiB[1KiB 7KiB] Sc·[0.50 0.00] +08:33:58.629750 db@open opening +08:33:58.629811 journal@recovery F·1 +08:33:58.629965 journal@recovery recovering @36 +08:33:58.633112 memdb@flush created L0@38 N·70 S·2KiB "b\f\xcd..\x1axP,v338":"r\xf7C..`\xf2\r,v323" +08:33:58.633353 version@stat F·[3 1] S·11KiB[3KiB 7KiB] Sc·[0.75 0.00] +08:33:58.644620 db@janitor F·6 G·0 +08:33:58.644647 db@open done T·14.887263ms +08:34:05.061197 db@close closing +08:34:05.061379 db@close done T·179.951µs +=============== Nov 29, 2022 (CET) =============== +08:34:23.230635 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:34:23.230880 version@stat F·[3 1] S·11KiB[3KiB 7KiB] Sc·[0.75 0.00] +08:34:23.230919 db@open opening +08:34:23.231031 journal@recovery F·1 +08:34:23.232932 journal@recovery recovering @39 +08:34:23.236435 memdb@flush created L0@41 N·42 S·1KiB "b\"_..{\xbc\x9f,v374":"r\xda\xc2..\x9d\xcc{,v394" +08:34:23.236705 version@stat F·[4 1] S·12KiB[5KiB 7KiB] Sc·[1.00 0.00] +08:34:23.249129 db@janitor F·7 G·0 +08:34:23.249173 db@open done T·18.236734ms +08:34:23.249233 table@compaction L0·4 -> L1·1 S·12KiB Q·402 +08:34:23.252938 table@build created L1@44 N·280 S·15KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xf7C..`\xf2\r,v323" +08:34:23.253013 version@stat F·[0 1] S·15KiB[0B 15KiB] Sc·[0.00 0.00] +08:34:23.255717 table@compaction committed F-4 S+2KiB Ke·0 D·48 T·6.455994ms +08:34:23.255853 table@remove removed @38 +08:34:23.255919 table@remove removed @35 +08:34:23.255975 table@remove removed @32 +08:34:23.256028 table@remove removed @31 +08:34:27.565320 db@close closing +08:34:27.565551 db@close done T·224.865µs +=============== Nov 29, 2022 (CET) =============== +08:34:43.148588 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:34:43.148764 version@stat F·[0 1] S·15KiB[0B 15KiB] Sc·[0.00 0.00] +08:34:43.148792 db@open opening +08:34:43.148866 journal@recovery F·1 +08:34:43.150802 journal@recovery recovering @42 +08:34:43.154093 memdb@flush created L0@45 N·28 S·841B "b3\x9a..8Ռ,v424":"r\xf6\xbe..\xc4\xdd\x13,v423" +08:34:43.154389 version@stat F·[1 1] S·15KiB[841B 15KiB] Sc·[0.25 0.00] +08:34:43.166735 db@janitor F·5 G·1 +08:34:43.166826 db@janitor removing table-41 +08:34:43.167006 db@open done T·18.196688ms +08:34:57.710814 db@close closing +08:34:57.711005 db@close done T·189.017µs +=============== Nov 29, 2022 (CET) =============== +08:35:00.573886 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:35:00.574055 version@stat F·[1 1] S·15KiB[841B 15KiB] Sc·[0.25 0.00] +08:35:00.574078 db@open opening +08:35:00.574152 journal@recovery F·1 +08:35:00.574305 journal@recovery recovering @46 +08:35:00.577496 memdb@flush created L0@48 N·98 S·3KiB "b\x03\x02..NU\x1e,v481":"r\xfd@..mn~,v473" +08:35:00.578480 version@stat F·[2 1] S·19KiB[4KiB 15KiB] Sc·[0.50 0.00] +08:35:00.590290 db@janitor F·5 G·0 +08:35:00.590328 db@open done T·16.238516ms +08:35:04.919068 db@close closing +08:35:04.919268 db@close done T·193.896µs +=============== Nov 29, 2022 (CET) =============== +08:48:48.753017 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:48:48.753236 version@stat F·[2 1] S·19KiB[4KiB 15KiB] Sc·[0.50 0.00] +08:48:48.753275 db@open opening +08:48:48.753391 journal@recovery F·1 +08:48:48.753604 journal@recovery recovering @49 +08:48:48.760290 memdb@flush created L0@51 N·28 S·935B "b\x151..\x0eZ\x95,v538":"r\x8b\xc8..\xa9Oa,v551" +08:48:48.760860 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:48:48.772603 db@janitor F·6 G·0 +08:48:48.772633 db@open done T·19.344141ms +=============== Nov 29, 2022 (CET) =============== +08:49:09.996093 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:49:09.996267 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:49:09.996294 db@open opening +08:49:09.996370 journal@recovery F·1 +08:49:09.999213 journal@recovery recovering @52 +08:49:10.001170 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:49:10.013078 db@janitor F·6 G·0 +08:49:10.013125 db@open done T·16.816337ms +=============== Nov 29, 2022 (CET) =============== +08:49:41.632675 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:49:41.632917 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:49:41.632956 db@open opening +08:49:41.633061 journal@recovery F·1 +08:49:41.633296 journal@recovery recovering @54 +08:49:41.633995 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:49:41.645625 db@janitor F·6 G·0 +08:49:41.645661 db@open done T·12.691685ms +=============== Nov 29, 2022 (CET) =============== +08:50:15.131176 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:50:15.131371 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:50:15.131405 db@open opening +08:50:15.131516 journal@recovery F·1 +08:50:15.133436 journal@recovery recovering @56 +08:50:15.133867 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:50:15.146041 db@janitor F·6 G·0 +08:50:15.146067 db@open done T·14.650479ms +=============== Nov 29, 2022 (CET) =============== +08:51:00.753198 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:51:00.753444 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:51:00.753482 db@open opening +08:51:00.753581 journal@recovery F·1 +08:51:00.755534 journal@recovery recovering @58 +08:51:00.756021 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:51:00.768622 db@janitor F·6 G·0 +08:51:00.768668 db@open done T·15.172194ms +=============== Nov 29, 2022 (CET) =============== +08:55:34.186825 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:55:34.186969 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:55:34.186993 db@open opening +08:55:34.187065 journal@recovery F·1 +08:55:34.188499 journal@recovery recovering @60 +08:55:34.188853 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +08:55:34.200271 db@janitor F·6 G·0 +08:55:34.200319 db@open done T·13.315296ms +08:55:40.541081 db@close closing +08:55:40.541198 db@close done T·115.097µs +=============== Nov 29, 2022 (CET) =============== +09:00:23.232522 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +09:00:23.232738 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] +09:00:23.232775 db@open opening +09:00:23.232881 journal@recovery F·1 +09:00:23.233121 journal@recovery recovering @62 +09:00:23.239506 memdb@flush created L0@64 N·42 S·1KiB "b\fw..F\rH,v560":"r\xe1\b..φ\x81,v601" +09:00:23.239888 version@stat F·[4 1] S·21KiB[6KiB 15KiB] Sc·[1.00 0.00] +09:00:23.258743 db@janitor F·7 G·0 +09:00:23.258777 db@open done T·25.986546ms +09:00:23.258858 table@compaction L0·4 -> L1·1 S·21KiB Q·602 +09:00:23.263767 table@build created L1@67 N·420 S·25KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xfd@..mn~,v473" +09:00:23.263835 version@stat F·[0 1] S·25KiB[0B 25KiB] Sc·[0.00 0.00] +09:00:23.266631 table@compaction committed F-4 S+3KiB Ke·0 D·56 T·7.729411ms +09:00:23.266745 table@remove removed @51 +09:00:23.266791 table@remove removed @48 +09:00:23.266848 table@remove removed @45 +09:00:23.266916 table@remove removed @44 +09:00:29.773577 db@close closing +09:00:29.773708 db@close done T·129.384µs +=============== Nov 29, 2022 (CET) =============== +09:16:50.070492 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +09:16:50.070634 version@stat F·[0 1] S·25KiB[0B 25KiB] Sc·[0.00 0.00] +09:16:50.070652 db@open opening +09:16:50.070705 journal@recovery F·1 +09:16:50.070841 journal@recovery recovering @65 +09:16:50.075175 memdb@flush created L0@68 N·42 S·1KiB "b&\xed..\xa6\"\xdf,v638":"r\xfa1..\x1d\xdbV,v609" +09:16:50.077279 version@stat F·[1 1] S·26KiB[1KiB 25KiB] Sc·[0.25 0.00] +09:16:50.088902 db@janitor F·5 G·1 +09:16:50.088931 db@janitor removing table-64 +09:16:50.088985 db@open done T·18.324666ms +09:16:55.700304 db@close closing +09:16:55.700473 db@close done T·166.625µs +=============== Nov 29, 2022 (CET) =============== +09:49:45.778230 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +09:49:45.778380 version@stat F·[1 1] S·26KiB[1KiB 25KiB] Sc·[0.25 0.00] +09:49:45.778406 db@open opening +09:49:45.778473 journal@recovery F·1 +09:49:45.780071 journal@recovery recovering @69 +09:49:45.783199 memdb@flush created L0@71 N·35 S·1KiB "b\r}..\x89˟,v653":"r\xccd..\xf8\xa1\xcc,v680" +09:49:45.783427 version@stat F·[2 1] S·27KiB[2KiB 25KiB] Sc·[0.50 0.00] +09:49:45.794888 db@janitor F·5 G·0 +09:49:45.794922 db@open done T·16.503924ms +09:49:51.233600 db@close closing +09:49:51.233757 db@close done T·154.973µs +=============== Nov 29, 2022 (CET) =============== +11:13:42.269914 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:13:42.270349 version@stat F·[2 1] S·27KiB[2KiB 25KiB] Sc·[0.50 0.00] +11:13:42.270393 db@open opening +11:13:42.270490 journal@recovery F·1 +11:13:42.276857 journal@recovery recovering @72 +11:13:42.280289 memdb@flush created L0@74 N·35 S·969B "b\xae\x1f..\xb5ġ,v689":"r\xf3\xe6..y\xaf?,v688" +11:13:42.282579 version@stat F·[3 1] S·28KiB[3KiB 25KiB] Sc·[0.75 0.00] +11:13:42.294299 db@janitor F·6 G·0 +11:13:42.294327 db@open done T·23.920764ms +11:13:47.686648 db@close closing +11:13:47.686807 db@close done T·153.982µs +=============== Nov 29, 2022 (CET) =============== +11:14:23.708457 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:14:23.708700 version@stat F·[3 1] S·28KiB[3KiB 25KiB] Sc·[0.75 0.00] +11:14:23.708737 db@open opening +11:14:23.708841 journal@recovery F·1 +11:14:23.709060 journal@recovery recovering @75 +11:14:23.714721 memdb@flush created L0@77 N·35 S·970B "bN\xc9..>F\x92,v732":"rw\xe9..\xf3\f\x03,v745" +11:14:23.715043 version@stat F·[4 1] S·29KiB[4KiB 25KiB] Sc·[1.00 0.00] +11:14:23.728772 db@janitor F·7 G·0 +11:14:23.728822 db@open done T·20.069401ms +11:14:23.728884 table@compaction L0·4 -> L1·1 S·29KiB Q·753 +11:14:23.735044 table@build created L1@80 N·525 S·31KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xfd@..mn~,v473" +11:14:23.735133 version@stat F·[0 1] S·31KiB[0B 31KiB] Sc·[0.00 0.00] +11:14:23.737955 table@compaction committed F-4 S+1KiB Ke·0 D·42 T·9.032055ms +11:14:23.738119 table@remove removed @74 +11:14:23.738186 table@remove removed @71 +11:14:23.738242 table@remove removed @68 +11:14:23.738308 table@remove removed @67 +11:14:27.464043 db@close closing +11:14:27.464269 db@close done T·212.523µs +=============== Nov 29, 2022 (CET) =============== +11:14:35.688207 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:14:35.688457 version@stat F·[0 1] S·31KiB[0B 31KiB] Sc·[0.00 0.00] +11:14:35.688502 db@open opening +11:14:35.688622 journal@recovery F·1 +11:14:35.688899 journal@recovery recovering @78 +11:14:35.692321 memdb@flush created L0@81 N·21 S·722B "b9\xd6..\xb6^^,v768":"r\xfd\\..g\xe4c,v760" +11:14:35.693031 version@stat F·[1 1] S·31KiB[722B 31KiB] Sc·[0.25 0.00] +11:14:35.704631 db@janitor F·5 G·1 +11:14:35.704652 db@janitor removing table-77 +11:14:35.704703 db@open done T·16.184328ms +11:14:42.384623 db@close closing +11:14:42.384771 db@close done T·144.254µs +=============== Nov 29, 2022 (CET) =============== +11:14:54.469611 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:14:54.469818 version@stat F·[1 1] S·31KiB[722B 31KiB] Sc·[0.25 0.00] +11:14:54.469853 db@open opening +11:14:54.469949 journal@recovery F·1 +11:14:54.470176 journal@recovery recovering @82 +11:14:54.473554 memdb@flush created L0@84 N·42 S·1KiB "b6[..\xb6\x9f\x1d,v776":"r\xfd\xdf..^En,v803" +11:14:54.474587 version@stat F·[2 1] S·33KiB[2KiB 31KiB] Sc·[0.50 0.00] +11:14:54.486408 db@janitor F·5 G·0 +11:14:54.486453 db@open done T·16.586048ms +11:15:00.256970 db@close closing +11:15:00.257105 db@close done T·126.6µs +=============== Nov 29, 2022 (CET) =============== +11:33:07.397127 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:33:07.397388 version@stat F·[2 1] S·33KiB[2KiB 31KiB] Sc·[0.50 0.00] +11:33:07.397443 db@open opening +11:33:07.397588 journal@recovery F·1 +11:33:07.397842 journal@recovery recovering @85 +11:33:07.401262 memdb@flush created L0@87 N·35 S·1KiB "b6\x9e..\xdd\xc39,v833":"rʅ..X>\xf1,v853" +11:33:07.402433 version@stat F·[3 1] S·34KiB[3KiB 31KiB] Sc·[0.75 0.00] +11:33:07.414163 db@janitor F·6 G·0 +11:33:07.414200 db@open done T·16.734306ms +11:33:11.229931 db@close closing +11:33:11.230090 db@close done T·155.734µs +=============== Nov 29, 2022 (CET) =============== +11:36:41.243838 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:36:41.244052 version@stat F·[3 1] S·34KiB[3KiB 31KiB] Sc·[0.75 0.00] +11:36:41.244088 db@open opening +11:36:41.244203 journal@recovery F·1 +11:36:41.244432 journal@recovery recovering @88 +11:36:41.250160 memdb@flush created L0@90 N·21 S·783B "bW\xaa..\xdc\xc6\xca,v862":"r\xfb\xe0..\xea\x98\xf7,v875" +11:36:41.250506 version@stat F·[4 1] S·35KiB[4KiB 31KiB] Sc·[1.00 0.00] +11:36:41.265206 db@janitor F·7 G·0 +11:36:41.265254 db@open done T·21.151145ms +11:36:41.265298 table@compaction L0·4 -> L1·1 S·35KiB Q·876 +11:36:41.270981 table@build created L1@93 N·610 S·36KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xfd\xdf..^En,v803" +11:36:41.271038 version@stat F·[0 1] S·36KiB[0B 36KiB] Sc·[0.00 0.00] +11:36:41.273693 table@compaction committed F-4 S+1KiB Ke·0 D·34 T·8.358963ms +11:36:41.273807 table@remove removed @87 +11:36:41.273851 table@remove removed @84 +11:36:41.273891 table@remove removed @81 +11:36:41.273937 table@remove removed @80 +11:36:48.973721 db@close closing +11:36:48.973958 db@close done T·231.689µs +=============== Nov 29, 2022 (CET) =============== +11:40:21.464610 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:40:21.464775 version@stat F·[0 1] S·36KiB[0B 36KiB] Sc·[0.00 0.00] +11:40:21.464800 db@open opening +11:40:21.464868 journal@recovery F·1 +11:40:21.465026 journal@recovery recovering @91 +11:40:21.468182 memdb@flush created L0@94 N·49 S·1KiB "b)S..]$I,v898":"r\xd8\xf6..\x889\xd5,v883" +11:40:21.468837 version@stat F·[1 1] S·37KiB[1KiB 36KiB] Sc·[0.25 0.00] +11:40:21.480440 db@janitor F·5 G·1 +11:40:21.480465 db@janitor removing table-90 +11:40:21.480535 db@open done T·15.725154ms +11:40:26.940207 db@close closing +11:40:26.940344 db@close done T·134.875µs +=============== Nov 29, 2022 (CET) =============== +11:40:37.994469 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:40:37.994607 version@stat F·[1 1] S·37KiB[1KiB 36KiB] Sc·[0.25 0.00] +11:40:37.994631 db@open opening +11:40:37.994690 journal@recovery F·1 +11:40:37.996408 journal@recovery recovering @95 +11:40:37.999645 memdb@flush created L0@97 N·35 S·1KiB "bY\xae..\xf8\xac\x80,v941":"r\xf9\x12..i`\xfe,v961" +11:40:37.999919 version@stat F·[2 1] S·39KiB[2KiB 36KiB] Sc·[0.50 0.00] +11:40:38.011149 db@janitor F·5 G·0 +11:40:38.011179 db@open done T·16.53782ms +11:40:40.724628 db@close closing +11:40:40.725031 db@close done T·395.979µs +=============== Nov 29, 2022 (CET) =============== +11:40:58.995205 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:40:58.995419 version@stat F·[2 1] S·39KiB[2KiB 36KiB] Sc·[0.50 0.00] +11:40:58.995455 db@open opening +11:40:58.995575 journal@recovery F·1 +11:40:58.995802 journal@recovery recovering @98 +11:40:58.999127 memdb@flush created L0@100 N·14 S·621B "b\x8d\x81..<)4,v970":"r\xa8\x02.. \x13\x94,v969" +11:40:59.002275 version@stat F·[3 1] S·39KiB[3KiB 36KiB] Sc·[0.75 0.00] +11:40:59.013689 db@janitor F·6 G·0 +11:40:59.013718 db@open done T·18.250579ms +11:41:01.461842 db@close closing +11:41:01.462008 db@close done T·163.238µs +=============== Nov 29, 2022 (CET) =============== +11:41:17.816270 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:41:17.816441 version@stat F·[3 1] S·39KiB[3KiB 36KiB] Sc·[0.75 0.00] +11:41:17.816465 db@open opening +11:41:17.816550 journal@recovery F·1 +11:41:17.816850 journal@recovery recovering @101 +11:41:17.819872 memdb@flush created L0@103 N·14 S·637B "b\x17\xb5..\xda\xc3r,v978":"r,\x11..:{\xa1,v991" +11:41:17.820824 version@stat F·[4 1] S·40KiB[4KiB 36KiB] Sc·[1.00 0.00] +11:41:17.836802 db@janitor F·7 G·0 +11:41:17.836848 db@open done T·20.371822ms +11:41:17.836943 table@compaction L0·4 -> L1·1 S·40KiB Q·992 +11:41:17.842303 table@build created L1@106 N·690 S·41KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xfd\xdf..^En,v803" +11:41:17.842369 version@stat F·[0 1] S·41KiB[0B 41KiB] Sc·[0.00 0.00] +11:41:17.845108 table@compaction committed F-4 S+1KiB Ke·0 D·32 T·8.128852ms +11:41:17.845238 table@remove removed @100 +11:41:17.845298 table@remove removed @97 +11:41:17.845353 table@remove removed @94 +11:41:17.845418 table@remove removed @93 +11:41:22.549878 db@close closing +11:41:22.550053 db@close done T·173.237µs +=============== Nov 29, 2022 (CET) =============== +11:42:36.829762 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:42:36.829956 version@stat F·[0 1] S·41KiB[0B 41KiB] Sc·[0.00 0.00] +11:42:36.829994 db@open opening +11:42:36.830083 journal@recovery F·1 +11:42:36.830298 journal@recovery recovering @104 +11:42:36.833414 memdb@flush created L0@107 N·28 S·935B "b\x05\xae..d-\x8e,v1007":"r\xb4\x94..\x83\xe5S,v1020" +11:42:36.834362 version@stat F·[1 1] S·42KiB[935B 41KiB] Sc·[0.25 0.00] +11:42:36.846382 db@janitor F·5 G·1 +11:42:36.846404 db@janitor removing table-103 +11:42:36.846487 db@open done T·16.480647ms +11:42:44.520686 db@close closing +11:42:44.520928 db@close done T·237.238µs +=============== Nov 29, 2022 (CET) =============== +11:44:14.711696 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:44:14.711839 version@stat F·[1 1] S·42KiB[935B 41KiB] Sc·[0.25 0.00] +11:44:14.711863 db@open opening +11:44:14.711925 journal@recovery F·1 +11:44:14.713393 journal@recovery recovering @108 +11:44:14.716658 memdb@flush created L0@110 N·49 S·1KiB "b\x17\x91..\x8fp\x93,v1036":"r\xfe\x98..i\xe4\x93,v1028" +11:44:14.716902 version@stat F·[2 1] S·44KiB[2KiB 41KiB] Sc·[0.50 0.00] +11:44:14.728348 db@janitor F·5 G·0 +11:44:14.728382 db@open done T·16.509186ms +11:44:18.275814 db@close closing +11:44:18.275997 db@close done T·180.432µs diff --git a/example/blockchain/MANIFEST-000112 b/example/blockchain/MANIFEST-000112 new file mode 100644 index 0000000000000000000000000000000000000000..6fc7d0502ca547c967b8c9ad176e550812f999a3 GIT binary patch literal 443 zcmbPHq4jJFBO{|!PHI_dPD+xVQ)NkNd1i5{bAE0?Vo_pAei2hXb0N!m4ps)uqMt&y z?@oU@?Mo$t#gqA5!rOk`RCAG5`737FsndNZGvOcOL1qRJU}wmC#;chmK2d6SY{b`u z{O-?NMSj2fn%A@=?O40MgRn)19BY5UWJVqquyW0!e={<2%eT50xb5q?Xvlug<62@i zw^+_MzG!3Pb?li>CNr`?RMODk?B(p5Nv!K0&pWmEl6U;WE&b09csU+kZY!K;;NySB z@9~t^DY|`(?;#%4EZQ=K&u72Qy@qw0SI9^gEc{SC+5Ya#gIChof3GoK(fl-+@eed8 z7_%0fXVOe!ShZ}v)H973ZKjTuz^W57Dh4UtG&f9)pdKRMvI4FRD{P(`3 nxWK%VyHxzr9!@hqSbV#8VY$S`;Lu&MC!WrVbIoH^hL{Whbp)-% literal 0 HcmV?d00001 diff --git a/example/libp2p/libp2p.key b/example/libp2p/libp2p.key new file mode 100755 index 0000000000..378daa63d7 --- /dev/null +++ b/example/libp2p/libp2p.key @@ -0,0 +1 @@ +08021220cb153983432524188e92d30c36a9bcef01aad506f8cbc5ec9fa8c97e6949f641 \ No newline at end of file diff --git a/example/trie/000105.ldb b/example/trie/000105.ldb new file mode 100644 index 0000000000000000000000000000000000000000..618df53fcc65d5a7441d99b34677927ac3e11e46 GIT binary patch literal 49685 zcmeIb2|ShUx<9_|#WK%Rkwg(Plra^VWyq8UL&^{(B(sc*ij~YFQCfryNybn@gP}4; zDitNs#3E!|{qLpT-QN4`b8h?hI{o)P=d91OKIMI%mS;V~bzj%_`hLIHGr<&$m?uV` z$<*@GjVF9ncO-f*CE4k--WOzAcb$(**z;4rXXzd=kHG+J%CtKkzKCTku5L~z4i6aZ zob<3&Nx3*In3&{3btGeV*EhdUd-r$YL;|%kSD$$hbzIIQGIBqmsAB;u{s@>Jk=ALG z2%HZ4mOhCSA?dL9tjcf_zhv-f+)P#?NAcE6y*aP#bZ5_LE2uZ;`GGz>9*CM592igI zO;^ttlCvIF5%b8^x`mL&Y;~?Io#mefsgGU+YUc{JN{9KOItO<;ahd(PJaKCFeOlk3nIl~rk#j_ zxkbjdN2i`iJo!33@hMPXrO&ydtgNPP*Bi4}$7TZWRq9M@;kk%=hu5rF^>|Ot_mkT1 z6Y8dqS?Tt#y5Le+2kbVM57?Ip5g&BwfbehYloNu3N?tZn)eT}Q%pQh`ZVQ-wMs0mM z>o`0pY)jz==Epw8?6r*U&$k)(@5j~!MdGrtnA)epZZ|QCpp-W`@bPVpm8V5M7-gIs z`$oS`M@Vz!7fs_x;z8xQ+%*Klj!JSehBui&o&33dHw#A(XWq-(d18BO3}hq*Tg;!S z%tt-EQTGgY64+pH=Y=HwzTIYEJJPBW;vtq&V0Dl`JUIHh>8XMau|r(;kIlx}aLLpR z#1Tm#B^lR+rSa^^#5iXmwmSx{13aal+Q)+O4n#Uz63e}?)*e3m;t6l zGI#fUnMwb-6Q72@B}ARG`*wngfLrLd(7Apz+GqA|0Pz)nL}jtf;Wzv>zUr}V_?EC% zVpIE3fx!xf$gylOZUJJ#u`6~gQL7)-*?shuF#JxQRNkt@(r(y%!lA#|s>@gr-lyji zrUnCAi>_65q~3EMZE78!Uvai;1z=oHin{9}2myOZF2mN=o|RQ+;~Y#P^W#N!R_v+}&i{){gBR-<6mRQA4@j=W6&7&{kJ|5XMvN2|a5G*m%1(55vRC0s zZTq})^`)fj40wJzYijy?HA>H`HZfeFbw3%wE!?e1&^SvUJ#|;V*x!&I4}WtPmXYm3 z9q1p#Fo#in;vvurbV_z;Jy_xGQb&WEWYwtJ1egIv=(`XZf54{M=WF}K>VyD;mlgK+ zoAzz|jNkk*?&8p_#HqfoEA)uL;cN!!Pi}kG&mxuL?a$?6cc`!cIKK{Km1P^U+T>tsd8UAId+UpGs6X9xGB&T}KiO z*{42MW?ISV zch5X9F>|Ar%_A0Ea-ukkGRKFWEj)TUp+~eaSi4TeP|4wz>a$D3TF-_X_H|=6zJL3k z4)~wmKO@utFP3Z{&u4z6QjA=myXj1Lv(t&LldH$pyq>=9=hROh-xj6AJm5Oaps{5=K z9+FSLGQ$(OYdcsU&F>F=!+xiCVD zXS}C27uNZ6Q!Ot$XK9}Rt--#ieVa`G=oEowLL zh)uPP_`WraX-fh9MSU+;ex(w9B}W?l9$@d!kU@W*ac<{_k3_Rn*DcatWTgnZqYB=&?;(rP{Me+$Xl|IV>YbVCJ#Na=f2pb1klSC=OeZC2JSFy} z*6wRGFPNkLCStr5qlxl#$>BLr>ePA_4 z1W%YABPwUOXqNjlU(XyXC1>tdo=7^=WMF$i+P}3oeihw4dn~{`7zBr?M zDDYvcMqp9GYZrW&2M*|P{kYdXWN{d0e=%liFek!4s1sw!h!G%{QJ*OzaGV9wLK26E zyu419&e(XhumwtgPNhEl<;7XfS61$1R&WX6QdsuW6W*C_$*O)us8-oJD|X(?W>+oAsQRdQt~}(FX(y_)N0za~cDuL$06-+TzS++$swmKqS)%ql8<)4P_{vkIJ$}IC z{HN=&nT+MlbvO3cXV6->ozt%= z5yZ(+A33;!?$dWR&P!{Gwt5Cte+BN+^F&(kVe9<4qH>OVanhN{y?5$D7x`O-j}EO7FfXNKAHvrgjSg$|HH?j!+cJQ0! z)mbcYd;N(GTU&Z3scM{+F7JE#NXf~bDA|R?_UnA?a11@SM*8;p3BiF8s%*Arwg>KB ztT%LYa$GzrhJSoi)yWtFPx_iWbuaiNXt<0^-3!)h$MFQ&hlw}6i5`*;{lMky4a8w- zO`v@J4eD1qZ*7d$TuVSpfX$+zm#H-%|io(X4O9 zy(>y}TEoG#o^+~wlN?V(M}urj#T|2M2_7HzN_KfY#=WZq|NQ8DKt`X z!O`0()T=i>TJ`a1)|+wK+!%%tZmb?RCF2kS zId2sq)LtkWXFGsf`F&g}6ewYF=hgFJ9Vk;9wDOwqPLXSO=(Zi_y<}xLcbnll^M>&& zdHZ%%CN;kxen=|K6dk0a`y|VFui)0$aqvjSPCSx{Z&SvT(Y$xsam027i%))KcwClJX$D4f-GFR_Ry^-;>wYrj6D-{;7ZKxte10`kZYk zzV{A}4VS`Q9KTxlGxR){jUi{}seYQ;#uLxnStH?`b4u4SMjSXKtsaTMNS$Lww}ckEl*BpPxgf! zob`^A+sWYnp*%f5*KxCBXoi#_@63_=DwMJel_-Eoj7W$&kDtT4cMPdF!-c%>2L|2m zzMsu^Y#r;{9gZb*%rjY^XDY}%SW})KHT~tJ$$(4pP5g0z^~6Z!)*UH+?|H@=TIw`4 z_grXU1PPRyJ`h!mk!z{pmQ+jHNpKTwl#!Oo-!W$M_N)P^!-m;G?FMT;L14?xm&`$& zhIrx<>a9OY>bJGjfvBo0v=%?R^NeJ1@RZM|wo%myEB40`u4W;wqP)eGnGfbqPjLW! z@nCf>KgC9gmKc+XcDd(l6XQps%uhe6F0EJVM1z|YRS!Zc1;LP14AB2#g^H)9`t=Qmja zun9(D2%I9S=*2iJ2}C3b{A=os316%&)?ej`e=Pn)o7>ju?I~G_OM_MX@A%`dJOqA# zI~i3yz>gDy$A?QMtX{1h8Zpx{l#u0DD{d!m4-pvYHjj;zlMWDxI^if$l1?m2f^uWb;DlP;o-upN%n1{ zp)|MGSC}xs$kK%s+!od3SbeR%**Tm2q(VqfuVoH%=SS<^A4=N}(3MI*0ng$2m%>l5 zfZqbf?>@yjvHz;|K4Doi<}E4=7p#td&MDY@=@f=1R{dCr@dFsw|3$#~U_2n{EF~*N z;Bp`qVAQ{p;wWhuVl7_G|HS@r{`b!{iOf(HHE6_uB+^dUGJ|JaW8x*ibfhRvk6DQt zR89?lW_$j+t7?KMHCuMCbbfRl++`_sDl-+t0-e{T?~*-v$0j#$1x`^Vue5)|C7O!s zM+2_M%ieiVq53fh&;kqy5kf|85iXdcaseSO7@mYz4IE(Q+I;&=Q%jxeMt+5TQmR3Q z{-+;2_7FdEo=$l)kidfE(|M#X|C@4?+}-}-RHUS3$UtB+X}OJE`f(MZgH%`7w0G=) z-hs?@C&j{0mdd;@Bm*C#gT&=qMYz`Gm?R4qduglrX| zTMMY<3Dz5B*fTR$_>MBmn?v1p$2TeBP8@HWj1$Otc~_-cSx3m43T#}wpb#gNLE^>B z(%C`5&G7UiJ3B}?`po0B(qPIhBK%B> z-yNQ|=d|E)^BOvcDUplml8fn5me|ntD5k>?DV{u4Lwf8N^Xcdz<;;Z(TQ7V#mmqXQ z3OkdT*hV|}5Dz~RZanZ)F=Ay{QEs-vFxK129m`(+#_EAOiXYuRL^Yb2&4oJ00vyiK2 zN)ZJzSd5SjOCY^8z`$-?FNU>&%}w$S)7jNLS>;>ZM!f4hD{=9w%7sb~vz(JrC7w;- z3pJP6le(W}r>;y@Da&ztA(bTEja4Ta=lWkxo|mSSec}!_KJ2X**_y9vml{2m-|?Jw zPBY`BEZ_42&%pLAT(7}C%+GF|IX|C%EB%T`ZhCX#Au_ECja6|G3W6Y)AV?)2Evr!Z z<}ikV{FTb-E52xRrmPX&?9FQ{r&G_RdpizoHqY(!eJb(IVvo&zj(+eV|0@-tI8y0m zh%%eb-dOBhu!FUNl;7j^O)O;`H0>GmlX)DLkXAv?VuBlA7E`XW&$my5=MFp@wU5A0 z$=B(JOW)Z`Ez9y+^~0;h;JS^JXpd;$=#A~E3ch0J$>urxs_ic=-*)v5?yP3 zE%+9as7GyNz$eTeo{4ere@(dMrNKbj1fpvTTz@|El-g!6Erhv0u|;P68eu6gSZ5fX zmS5&h?b4&7U`!X;Ya$PKLBZ;OG~nQ$aOFo(#Xu>*;DTO>yKk>dr&`>${I z?TMQ6Z1cZFFir$2FlLa>E@o`MWd%lOY~i`oB;(~y%Jkuf>Mb!1dpA-$yZ&I&_iaj4 z@uk^c0@;cUxOBP{Q|`?t@{+vFz;3u`9~7F5xkN*r1R|4ho~Qy507!sI#<*+O;)&C$ zg*So@9p;KL{JJqzbe*eLaQVhvPgar}YsK@sIUDcLuO}H_y&2~;n4_X|SZ_3y>U7je z^E&VKwnl3s*~?}RfcJid@Oz+0TNLt~*&pHgKpqV>*a+ael%5_4)+#nL>CwSgqk`6KS>+WaXka&5dTnmVrE+}`|2&Ik?Ydp!@T}DvhF}avElam z8%b~6gzd^eItBzMkI|ERY2Wmc$LLwc=m|?GRsDScHBr-F54Z9spY7NfJrbF>tt6me zSYQN1LY(;U#2d*~5`&|{GEY|=p>?Q>4Nw(eqBD-3G05@_4QeR0P*uN(ClYucgn);2m(&!n*|IPIhKJZmVvOfxhT+NW5vsG(O3o+5f;KWcF`3ZdejHR5j+sV-#}u?l$11^ z=?~Hu-PhqV!Acl%Q1ush`zzg{$HKT>@wig%fVsjMcg949*K7yQtG63H4glC#eerRH zgN33&l)!`1KTvWWnCu{kgn$ME0w;8_6mr9M1nKy{A~*bV;C2^Q6=X~(QX}#O?ZscppN2z^$;wr%3Nj&$TAX!auV_}19Ik;;7 zSuFU^8KeIo9w3;%C`@AsLJ(LaA-H=$S3EfMDxNrm=fByO`L%=?Z(L(vpx59v^r-Eva$quIjJ;FVom@6d=tv>J^y2alvBF*T? zJ(_bP2Ta0(EeYce8u3Jvizg;9&WCq>pYi?pJ;H2H!Bwr5<9 zR-s)u+I1=ASboI=-CF7F7x=I9t9Mn{SjCWosV)O`h>pL!Tpat1dJ|8xK7&kNraTv zNrusC$MJKXB-&>=j+}?xb9Q!XxyM z;GhMI-}Dww#u(e6ZNaG#zUl4M?z?G|Y>(8)eP?pvz4COwiZ%;mw6I|HSn7}9`>EF7 zp=(>A!P1(~J)ExfF<~`V9+UB#`PVhoA~i?OfpGv#m(qa2wMFscVQT~Sfn&#@3 z(}xQB6U#+glcJbqN^LwfrN?io$Q+ia11djzrtWz4<7hMih>+az#Cr#tCa=DwPS%P& zA*XfloXMA4&Kou+v3|IwqyFfujQw^Pi5Bfx41@Y3ouaKR|8F%Zo3?k2E_ zJdE!C{&qFjsMl~=Zs4};rmVxSn$5TG-P83*1L*P5)1^>gyPOV(RwFIuk#I2`2C{ga z&B;dF4nuN91Yh$GznsTU7vL_z7IfO%=>ZIVW+)XPpz9DPX%bP?1o)x1ZXW#H6*5kW zD`Olm(D!b8Z;@~s!`)JA zjMi}tqLa32ZBV^7aB;V9w%e_ty?$=&94VCcS{K%+Z?J&hg<#)h>Dx3)x4o@KK%uSh zv1EfW@00Z&Ja6BCNU&#?jAu;1GX|oV-7!hbBX~wWxTo*ApbcjQHM$QQudWVb9yQFh zRJeCIM&XLm$?ff?XI?szXR+F|6hX;##-FvtzW$PgPC?QaxM-N@cdj_(**_GOQa2~& z5dP`)S27h@ZP&f$CvP>)UQt{J*8FPxqe^Fr#Q6uH`KKh#u*8W=P^VZqJT5nMxOhpucMBj3;3huYxJRRn7O?vuvJEOS&vHEOs+L z<;E6w^`9lXnxO=IzzN=~@U=)ya`q$6w!3z(Ox6;!U(nISr)-KZmZ`alIYGRX zVxiHiMyXRNFQWbU!k)aX^DGhl%@%8%UWwu|;y(zFJR1tF@=T7bwijI73qH6g0vdSs z^WHKg_OVV_=gui?TX}Pwqc5X4ZyP4wG0Hk)*lI-re~s3u!|=DhmPqIbU@6IelvpA# zDQMKY`LbGVQC#pgIfl>oLtYp@TKuhm2mrkE%up%`uo5!G0;!>kfy`n?wF1HLCaNOR zNSIM|Vbw%>vs>f1a(l|TNWlB-8%u-Y?(O$dx0 zGNi-d=Xs*klR!Xf0pl(*gC~ZyM`x6p8gyDG5bZm@epz5@3gPmQ)nTLE-ALs6#HJ2$ zd8hj7C?&s_r$X{#C!QZTE%mgb?)+XBfr;u_rY}VsibY)EH?exANNw##C1;R*#pLPR zxELPtJHk+T4XftC`pkt7)sTfwIel@LW1UG=cjly?e}87+F=zknC@F$lfEFkd?;^?e^m93O--NzN5V&%#NcI7V8Z8eN*oX z0$ni3eCBAvcxdN)GKr~Q*n>f>DJ1w-DP>gwwt3!}Xvlyl-fKyo5} z6C)5wNn1jj1+7H?LmBb^Y&L+ZV<}i}9u;Hno=1oDM00EAU)&3-s@f{C)3#FNg7E%E zy-jyjfa0%AZz(+GC4e)LPZ;rYc@{<6du7MgeaKCX?J(*1$h&rPO2cU2=@8ZlMLuir z#VL{H2$P?`r`LHQ*1)?HhX!iD7mnuPZ4)2&MaWXM#5Xme64-{n&G}k@!P`0Gv<*%1PDoJ=Le$tG2|MWzibUPGz8}Z+qi1S zrt>tJ=(Rd`c84AqeeIGq(qal&xq6Ih9J)(EkVvpLPmC%J1V>b9>QynG{@HZY;2m>P zi5q?3<>m!mdHE21##P1Sm6z?D2NMEZi$=%d9`c9;hBw6?O?9IuI3rrFU>gRPZma8u zP%b*?!t$R2`7CNKg8$H5Sc@ioJoSSTbx_-HQb;*jF!J{1cdfa3fHP)Q6o#Mk*`q7{)(gUr&4+tcv0RTU?l`vl5@8$rO5apksMFPEMmpy>zc22AENf| zC~Pj3z4%p`ZSuw?mwmoU3l`JmW>x{tv+UK4Ak-TCs0woT_xWxj-8W8|-X>l+!A)@qOc(9&=@uI36a0CRN*-vhuN^PL9 zTD!1^#+j@o-2`Nd%v?5w-wJjcjpK2AdB|pS!g=ot1eQCSfE^Z>lF&#Mcl}X^+m^QB z-Ye(t-Vb9v@SfiL1kC|;w<^ZdUfJYqb+tv&Cb^LcZVrtpHxn~KVNiqU#jTd}kFKvV zE4|2QnX!vmmSaKk8?Y_9pTr~C?CMSckWLW)JZ*_`-H=>yc+vh&sH$NKi76YJaTK98 ziX`?Rjar#Fl1B3&4PJdu6o?DzMa+^S0#Wsm&>nIGby5VzIXDnd14ia_*lJKhF^tJ= zv|rjNw;;;N3UqKM2co#PA`c<`{UH#4$l^eUSGuQre!Ki@aKHOO;PA)Ga{Oxh-jAL? z&Fvf$!jQ6B6VU6~gr+Y=c&v(O^$<}HF1(;9d;so(ghu1XQRiV{Wkls?+Faxl3>+sI2+q?1A>#aknrz+|DmF)i`)-uJai@H+Mwb4?wL9!5 z>Aq478qeX9{3Obb^~n^Swotk=n|u6=N_bXbV&3O(4ay&LnXl(vGlUH}fss6{UfvsB zf(z3&wVn&&cXxW0G<;yYd49y>P=>kMn#2W7_pbVL#zvqVYEz*y{a>eO_@5&qa^^MJ z;P%mxy@zQ+;@lcGxz9!nToz_ezqA=wpG+i<-2|FHu{zkSTuMjxKQXuXYyL-g6*IvM zW%mPmz&Q+t!<~U1F8(N@9g7D;;Fm)dSJ?NLD>T}d?Af_h{|UB^v^ioz#w}c!!^P;T z!5A=rxui476!Z4rdJZ6D9YcVQYF@p24Nb?VG3#=Y?ZYVB2?kME#_1Na6rCz9Y z$!;Qt`^%}>-sZSr7!oFSpeqhbcE=;^TIQrv4P|{o^Ik-DG{?`8FJ2bYDQ~@*DU#Yic z?j=-|EYRFnEf6y_ArX)sYcL4@L0J9oHR}6)J{|w1QJ?e0-JPwiRe)|o)PQd4bj{?) zQ%9`JKApA?wPb$%$({~e{gvh-B>#&g)i1)!pD=>$!XEdD`O?;?)ReDKsCG^A=xnp% zu;19~%#bI>!r#a5C$s{IABRP`DNq$L@m~d?M1xjHH%=7Lz8uIU1sk5vuris=Ecue( zrBgZG8YcYtZ2233;d8>|Yo4oIGN^&<-=2PQ2nY*-qVnb7A;Gf*KMrm&As~Z`;BGaW z@OAZFJ@O^r^p+dn>g;k92x;uhTj+*F_Z{NK<^oPo&PCew-+)q+zhn1)$CBDn#%N10 zQO&6s;)+b#U+Y;7-2E@m3Z`%5FSkrN%5n8VdN+^RYtH4kY%qaEN!dZeVkph#ZePlZ z_8&Z*Te)!rXHQIKz!P;73#s*oi?0Sq6Jj5(w4yD!Y+txKqeGWHWd`_abHQZ+L5_n$ z1co0rO`cvZ(WRzpbL~Z12|DBb*EkKQpEG$WkL`)rL4E3`j5i}lh9zeT-OqBE3+0q0 zLQ29Dd*xRR8qz{ua_xnkY1ZG@DI{~bg*hckA8O$!jb*P+gHawuwO=HOmWE5MvOBu_ z-pKlN@lOj(J6T?rS4r&O#yjQUaK?0y6}>*$3jhWl!*FYKq1)uDN~G>wL?W2OGVp zUJA%5b&gDKtO}q$2IyhIr8H%0&&P2;% zOiwc{YBZ27&n1}LnxT9g!D~n&BZFXSqL;rKH8<4S;E71`){kzWj{VitE<^eSt~Xxz zQ&Iwi0FK@ps-!Msrl~ zUr|r!jm%NG&JmnZg(7%q7ytnPRK;HT<~dAyHEG{y5}Z-YIv}OTokEemF9Gr+Kd1fh z97drKZQy^B zed2GSZNngZf%PW=Xro3y^DDs#ERIrI1is(&X{wfS=HNnGMmK5djh#;GDV~IpEf?K# zsI%DaD+8e){Q}ClN6F`wg$}bE5X>@ozaa^3s3&Vl-fu2JdHUbYEhfZY+4j}8)CT9s zoIC326|Q$@I~~((-vrSU3KADz(?>G|S(ehWUP6tHo-$#EGM56of0jIy7Cj2}fk^4k z7ZIh*hWk-&N_@Cm(x(?%o?$PKh}I7VZFaU9dO3r$i6jYG=6gQBRRX4d<<>~!s{g|U z|JslctwR!XMnNjz%&(jdg&Z&66hs{5b^>?QX()@Mh&D$F;h=DaI@CvnQRLD*1&c#Hxkq^qE$5b$fbAdpQd za{!>*3n6mzi8PHUIxFJC{!JAd3dhEhqvpmvAKuil-t-{g(`7%f2jD_%*+}h3faUiP zf0oZ~+wlyRRIwb++Nh<3LQX+&yuj?w)doI*$Qly%k;%7kdAA5C4<4`ytIbt!>W4^E z9mL?M3o$AuG4%pM)c1Q4dujRacRkABYhZB&k&TH~#|#syaVuwpBRRh(gL!EDsa|06 z57#7e0{ve$#{_zkPNEmL@Ru9Ju3Sznvn>bBlrDKIZjTe8&CbdhQlFinK16wtV%@nu zYrj_6Pf}{U#bZaZ9KXmue#(hH#l+^-YC)~L5`Y&=@rI4*poKm;JXpOS2CzMrBAj1k zJ}aucQ-7cMwXQht{Y(CHrP1GLjCN`FIjjU@i$h&V|C8KFkg(tqYSuqJqzB&02pJGK z`D>9v;6J|>sXsY14F1Ne%s+E~v-qglGmFAvl({k3{F5jIQ#@%b#r4V>!693U>y;U5 zWEVIAFzirrg;FN6Uq;g=aFkWUd2B7w>`u7Mk>Yc08_P5KrsA>-j_Uikr_O%>b?Jl- zkO4p-bd#d2?n{CEmIb{xLp}Ro?ynMTBnKAv36dK0h$v<5kF^H!O&z!iw9HJ~}? z7A^wHj1J@i`ec&MlGyZah&BrzFC@bZhay4feX?)FgQ;Mnp6uO+({ENq0{UU9ffMbM z16zUqf^ljTu)_sSnEkNV`t$8D6n71#6aRbKVd{wll;sRCfK(jYt0?zt?L^Ahz^hcQ zS7E|?F~#z%!2zx{$|o%@D9g#}e@Z)5wXvu#->1mYgUxW_6A-2N&+{yW2J)Ny=aDp! ze-jLX@;KcMF(H)`Vz(){Uve!|qdIkEv(`)gAd!WRoyTkDFPDSEKp_O4dZa1GzfX>f zoY#nKA}#|b9&)-+0yCfq(>v;E_iSA}Q5fOU3xzM5%OM~Ql_Q|2lAsDhPvMOTA|_T; z);B=Lv>f#rIYNedi-E8w)%Ysy^(&@y>mTc^VjgV?T$=$31Qo)ko7RJBm^z2bksN-H zV~4*vEj1n=E=P?vNewT<5>Q%rD3KT`!y1;sP?ot}qqk#$*}d}p{u2>d8@4>?)BVz_ z*Je~Z7uU4v{g+x$2FUoITPGd_qTpY+vk)GxdZi#^=OL~j72jyCGR2d<-;CBZyOkB! z6iUW0edt;>ywC`^M4<5$X1W;3fkZm`;_+v8k#v@cBN={`4&xc@0G-V&`6?L;IRa7r zN%}g%5(HeqrHmMS1_vQ)#$ekz;=$EtR}H_|Nv~X2rC2Cy_-0UMi=+FXCLdR8>GRaS`vfCB=_b0Xk4S1tw zaFA?~B|p;j2{qxA+(4VzKucJ{{Hu`$+QEh!$RSpg+GFUCQouw#?RtaYL*M_20kkvXVuGs1O0(c3(Zv{<1%0@~T2H9WyP2wnI zzx$tTUH+pnoyeknS?toy5Y!XE@v9i40Gxlk(58Y*(C9iNybb{8FToDNyk!wFSOyI~ zOiWOu3K0C`hWs%N9xcIGJY`E6HjS2Gz>*#@*%O@n3tot#*e{;4Whm+4K_R?A!TrA+ z6f$jECNBl3I!DDXQ2U?U+DMD@r5O4k=7)kyKX0PNE+T@B{+EXi<@LC@BZN*-Mohrt z*9BQhb7mRt5{%drP$-_dT5`4lOlLe0rv}=+<_8n$ZMIMD6FqhAkZ*(a4#4~Kq;&lG zJZ=dyw<%}qcd21u3#XN|>Regc5tD)8J#n2cB<5BL%SSFG(18xXahQ&@b5S(41k+}e zyZqukKu-}td7`9Ez!q8{P--k7wr9Z4hpqj?2(}+qXH%=erhLT!c%H$0piG0>gcBgPsC7HAPj_LrQ`^BA}Ytm zi?ES2myl&6Z4!j!2q>RdU4%`@I;icwXG}33N>W@&y+?L!qj-g zY(l{0niDFl^mjH$8r$h%&3av!8digzh#3xG7>L}8UKbpS)gD<6*SgSku(U0a)^(P= zysz(|{l05P^~Qp+<&f}vjvGJ+Pcn6~}hScbakV^+HTt1kStoCrmAqLg0A zcDJrYx4l~!{_2{lB%ydlDelAf%Fcn6?sgHYK46T2GUQe#!*;@N(@`vwLg3$Fs;HSGOf64Oodpk)J)Q&y*S2LZK|xJKp%^dp`g#dC7>+F;Msp4`98ua z8aTjt^1-%=DNEsa!R&Y>k;*BNP=;*@+jNNSp+~EQhJw@%i-^-7f_CY!5X5K>sJx{* zXm$Z?2InRyMJ;9c7;QYw=yj!MqISIp17_N4H@Ox*`{m3GMo~^ zhMqfQGwo1YtD$HL@_yYAD4gz(*_q?tv4N-&m@y&LB%Nh)v^ut*1~P`02c4x^-->%z zlM;$N5&!9%wU%T%|x3b2?J^5>(gkTf>;P6wqJP_hRK& zD$!SRq|xsI_WleR^yeApc7FJ{9IERK0qW@vA9FfF86xM$6RZ5aDbrs@=7IP;Ne4Mp z4Z@oU*aO(WVM}-x7Y6F-E#cppF=8Vw3_LCj6oxd)RTn%4=XjD>P=pZr2gjLC)WNB3ltQ`j>4}+5hj50 z&tz%|WCsdrzXV@AR80yoOH}6=sQ;{#-6>fa5d{n^?u4S`FYbhzwL}3fJ)34s0^)C# z^EhGx!&A?S${v({)R_L_6F0EJVM1z|YRS!Zc1; zLP14AB2#g^H)9`t=Qmja_F5dUZ6`cjrE4vIR)h2|!iZ_zK4Y$ZbVdT_HSV&U2ALc6 zsAVQWJP=t;a-uxGNdDAv^v#?7*#M~-o-yRanPnJeg5s_$gL9||p3t&}O>iWg zf9S8f*)cRj%8+;F$bA(`3`A*qz*acWjY#1~FU2rYV8jHMXF?%fBZ^MIjO9-9LtqQg z3QBe)2}7S0DnV!yiAlfQcw?Q6Z29N%rdL&|0W>Xk?k70;g(KEhbUfM#ZMGqWOk!EA zpinmD@Bv#6((f{5+p}xyWLft8clyV6VP72@{d9MK?YCO)qB%8Ly#ud8kLTye2Rw4g zH*fCVGzG5ws{5CR!bi@>MdsrIQG>DIZg4Blr!#9;@Y#l=1A>q;xit61!4Q_Ubb-hr z2qGzqz=w-%vbk9Q^VLQ4162%skMQ01C5v=EjW+o47_j@!;=ux()@>UIk;;D>_Rwd& zFUYj+IvXr2UbTtg0SczxIxX^E*bNy(v&+OfRW%0rIJygrzQSl+Emhf&w-R0oQ4|EOAUtXW2<7~GouKkJA z^I-$8`uZ^pf0i#Mhvfz~#rOJ(WL@|`pu{kgs_HKr=Y}T@bptuI3D6uBx6*Tu!Kpie}nEC ziBl1lAn^zmr%It9w%h04^iLJqKg88;@hBOfIg}GY?0y*D9O`LiG4+*}9eBY`8eS+Q z5LE((Lx;HV?TF!x@Ov*uix^e^MTUStlne%1&Zu zfwZGb8j%1}5*gO`h}|ylRvTx}rV5!U7pmQ3nJ?zBe%*H9t6KIQQu{?&(1}ZOP$R|t z7M}V)lLlLwFp}Ddzk`*I?hGzvWCvnmCa7FoDzv#!4hCc{tSJ}E7+p%g)AnFZ4vX9K zYVnuuK7LWfAGf;Yn0c<_H{U7mNubVeY`MZB z_?7oXlJniQGw}BzuK{Gq!r`XXuL#vDTW7`2d)e%YkBYBYJ#&()k8ft7Vx6`wxcKuD zEcQ|0Y&nDv)Z*i{T+XRxh;e(s1S>M1>_;8Qyh7?s+O<7gJ!dDL2?iZYPTlgEv?trh0ZX=}=)#skz5;W} zzahr!n9)GE6@vqdL*17owOST?LQfQ#0=U7{7vrw}0^J*hWe6IPi$fxE6u8O102V;} zxQjw^ftwKdIav;Dkt3L)s#cI`ctDV{JS<9Lj-JI5;NKGvhBiVQ7hO`E@%%U2vfOK| zS=cZ6@c?G0P&)g8kqE8PGZr1f2V)$-4j{s%-iw;;A;Jks7dlvN9RkW&1Mp$#ll620 zO;GcDNAN@x6&zN6NDWOr0|Ax30TT2nz?ed}N@%>kB!4^9qzF777fe98FoWxut-%<2 zil-iOPCaNhRSq}!cHm?C$F{>y-;RG2;?h=)aQIeTxs%^NB}@t4SY~U)3ynEb_xWFT zI&T`|Vf0cX1Mi$9wXQmw>Uk$o6$eLBFTNmRrJUgtL{Fd04!J$t;QH(x8>l;x?Q_c?rfIkvSJZk4 zIr*#}!H4G4HU4vz@16dw77Rr7|dP}e+b;{x-s?Lv09J?-_f7oUf_t}pv zvWj5AzNN_2QteEVG927WggLhdhLzL<|N3{+m$vc5Gk5t1%D2;5_`Tu_Rr^X@hF+|g z1J{XT2h*tl)jq0d{w#j|d4Ap_(gCS9X%=$zOevzvK?{Ts%P*SeUMVhcXKx00S^KEENDPFG;TcoUDVajp#0H?*x}}bYSop( ze3>2!(OPc34Y=eHbF85`gni5m3`FGby7 z7SJc9EY==q-2JTHxX2QR6JK6a>}$5)!8G9t~fIk+6iQ!MCUw72L`}(>APf4-m%FIT!B+m$t&&O zaEYek`q6;v@v?UwRH%Lof*}D#?7@pLF;gaXL#n&gdUcIzmh6VLoW@Dp2G%nZ4rZC= zTQ=k0NM9A4ty}}RvA-&4Wc2!1A?Gba#QPhlJo%8kZY|3Zo|-}%JKx&tT7Au<%MFlP=p}hjd!jmT;1Lj6fKWGXA2o5>e>XLBU)p&UVF3Vd zK9u?1k3dbSO2Gh|=T16)$~Rp6kw*S<+z|CMj2IQ_K?LAORg1Z}0>eNpkORJd{|>Ok zj1>jE7%^&;bQ-kNs}egly<7?R-Nr7uVndHw!wF)eQqZQ!8S$NK&srWy{~W;V{CS={ zNeA%s8~IE0`gk$))W+<`=#uSwfGPnwjuXzhy+#}lXkCF3!=Y4%aDaS zH`YyAya(rh+{)cAuxapY;=Z%1vrT@*5*fiNlBzWPf2#0J(RWfT6AIz`C44i%>kQS2 z7(@6Dg6|mkCc<|+e7}Wn4!Cr~DXADBQ~F3b^*fd!?>qJ;HT)0%)ob4z{;aU~j^6(d DB@HtD literal 0 HcmV?d00001 diff --git a/example/trie/000106.ldb b/example/trie/000106.ldb new file mode 100644 index 0000000000000000000000000000000000000000..e28d6dc70ea168403851285f3233cd417d81c9c2 GIT binary patch literal 2471 zcmeH|Ycy1A7{~X!4dc=*lFL!bxSb}FYbcb;2<1qkMlt0Y{`)L`>@0u? zoiNa1^}29W0<#+-p!>nPeKW&+g>x=#e~IaQk)!zPaBv8QglhsgqQyjO;(06i)#}s` zTD?s5Lxkev#w1Kg_Wj%tHrLzDxs$psNYS-zOLKUZy zY$;dfR-A$C=jCsYCfqbaQ%zS!cp8k;tZ(POl&o<4v%Y$-8f7pnAPS zHzt227tNTNilmls25B*=}IGEP6(>^St4-sk?*@h(3^7263P_<_89GWZrlWS~P{$4ivZt=IFFVsdW~Of=T2_CF*(d9qQL zQ_9Tx9a5FohtdHRcIMG?=rIeQS4Y|Gj4P-pL81OoncdP$7avhM)qHbR>~V@6p9g=7 zyF3`PAO3dG?1cvzq(B6UEMbk&5amX(idrFk5{{34k>RId;BIT|%UAGJz_#B72bV>U zP{;jH{E*MN0Iyw&K|`&pB1muDr~BDVmOx`TTOHOQ;gh;~8a?XD(?*e+SI{3$&9O_(4oyD7 zxE*HiQ^iukXVn_#Q=yAgNE{+K(E~*>AWTP!;V2jk*7SILvOhhcNsgMmeVC*&$bzb* z5B61VtzJDR zrx2Lf$9IG5+@P3SiH6C$72vd&fVk+- zi@m%VTzal0Gd_Qz=iJt&V78Oz!k_CiY=EUiz;@@w@ zjLxUnwLt`tIROivtq5J0f+R3E!OV;(Y+fhTE+(wJLa>Fe0qJUp&S_c6Tvc+0W0kQ5)asU7T literal 0 HcmV?d00001 diff --git a/example/trie/000109.ldb b/example/trie/000109.ldb new file mode 100644 index 0000000000000000000000000000000000000000..913f33ecd46f8120c7db2872ed00705da0664569 GIT binary patch literal 3059 zcmd5;do+}57k{5Im~kDK5-BE>NiMloL>EL-G+jhYh+Jw)435hfg|jHoEA?l^pX@uJoH)P`B2i_M$Wzn?B^ z03N!x-+5MI87)t(LEMa*St>d5R{ukxhGD1*-*#bxY54aSNY~iHb68RTNCXIiARY-S zAwgM?W)H$3_?mj5p1yfn<@F7miXHv_nI9X=i39HwRqTdl9Q-u^10kF_=T}qHbYieOt!@>))ZgGd-7PASl>&1Dvwoc@oCz0C0(*7EW)r0 zbu4s1DSF2w1}_6B!v;ZC#O=z_Bn6* z1E)x4MNg8siTR^#y<``4zw_FuvWrO!`WB-QPs3{V+MWS8Lh8}mk{`-1D`J(9-Av&A&IRaB*CvV+joOOR8O>rU!Phm{9my2)YmBm_`kFT8rS?e1`&!w)4jr+ab~tY{D7s-OyZ1n{%$Cjbe&t-9S6%SPa_iNFHzu& z1=0{+F1$#nEfSJ|H1UpMNkT~QyY_0DBYY3*Q^%6T9?yHUu6_OVAeZukZ2);C(M~bu ztadcG6=rZK;2U;LL^U-;PIrA+vMa4jlx;hzBmV41YES|p3*b)uwBw!CQ0uMA8lozJtW6Ham zuR7@(?sOU4nwVx8m|Gg8wKejI)C^H}Wfw@6Bxk{Z^x|^Gva92;q~?go=I6~UC8C=2 z&>rtwD9O3PvAL=xK=NuuT5F*M7)wng2+o#2nGKL2PBA0GNm*%cCt9KXtnEB5YIEn0 zhc&cIMyjAFURB62Mc?QSPaJF&hc5nPNkk$+s$xdyOr03Ur*nJMdCjaFE(GN`a>}A( z%#Ci%lk%P&_^%k)aJx8kSzyS2PqrUbGa&jvDsEClrdQ;wu>#tz_Bh51A3`q)vq%^u zf;{+8YU!FOV_bC5jG9@v(9BIX)w*53&(0(Y#1hK_n`kdopQFP@5g=)3|D8P3MH_ z$z1_1D+}b5=}tCT9N~3LxLSDqXo2YTqoGXP^v`t;@8MG4IT+8%)5$+>HT~(9-$~5u zg|keC|H6uyXO*Ix18?N%IBFS#LIiIRQ8kEwX5wlkXsxcJLRO-@mwyO7Ck10073C$j zYGSKg8$EE%&vGOiiv^tp|Io#8}>;H%nWB*Hd z|4JXc87Ba30$ew2kAIyxRWd`S^A2^!?4~LhO1Z`rFuB6JYTuymqE~1GD!*=Ec`%5e z{Zd;HsM`)Alm4z3foBf_;A3uCUdzHoO_2C){cLi1guSFzeI`bpWP@83!|n?O4w;{B zUM>*7-P$1h54QDmLC9ud5MN&+BRp9iX3`XG@d;Z#V=u>hu!;pviX?m4Hd}YC={XJV z)oWEx*QC_HA(Ws8DEBZ{mw4)#GRb|vBe{g zp3NRoI*w8M7yzQehW6c$>T^afMZ)?Y8E}{a9%FXJzZpk6l?freG3ttAR>%avBF8~S4g8-zw03O70)Wq)Uv;t5T`CvotHs^)*n<{vAuDCPv zprpR+k4>WqagBz*G8*v8QL^PIC<-?X&GDqf1Y!(tmfE}q0d5y~vc4D+MB}1jTOtY; zX1l3=Cb6;mwAJW}c{RwX$KVR$I!B1I?99gVmB{v$AP0-^649`1 zOhiL;+`m&fLOE&RHHaly}(RM1YyDLpLTmo)W4HIkT-y>)Ct zuW0{`EnQVa9owNm%5VJ;#hnA?3SPWK=r+>-A@s1Bkz$lGpW^}l6EV!EZCVA139<6Q zA{wlM*y0cxIV&S=c1OHJoUev~zok~dJQDgOK|w4_VLku%|6WJuDM{+2J+J=+b@^3h literal 0 HcmV?d00001 diff --git a/example/trie/CURRENT b/example/trie/CURRENT new file mode 100644 index 0000000000..0e6632492f --- /dev/null +++ b/example/trie/CURRENT @@ -0,0 +1 @@ +MANIFEST-000111 diff --git a/example/trie/CURRENT.bak b/example/trie/CURRENT.bak new file mode 100644 index 0000000000..db6fa61f96 --- /dev/null +++ b/example/trie/CURRENT.bak @@ -0,0 +1 @@ +MANIFEST-000108 diff --git a/example/trie/LOCK b/example/trie/LOCK new file mode 100644 index 0000000000..e69de29bb2 diff --git a/example/trie/LOG b/example/trie/LOG new file mode 100644 index 0000000000..fb5a0d16be --- /dev/null +++ b/example/trie/LOG @@ -0,0 +1,500 @@ +=============== Nov 27, 2022 (CET) =============== +22:51:55.530536 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +22:51:55.540057 db@open opening +22:51:55.540920 version@stat F·[] S·0B[] Sc·[] +22:51:55.544104 db@janitor F·2 G·0 +22:51:55.544173 db@open done T·4.060863ms +22:52:00.992848 db@close closing +22:52:00.992938 db@close done T·89.158µs +=============== Nov 27, 2022 (CET) =============== +22:52:03.862949 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +22:52:03.863165 version@stat F·[] S·0B[] Sc·[] +22:52:03.863205 db@open opening +22:52:03.863277 journal@recovery F·1 +22:52:03.863501 journal@recovery recovering @1 +22:52:03.874407 memdb@flush created L0@2 N·20 S·1KiB "\x15\xbf\xd1..\x03\xca\xce,v7":"\xf5b\xab..\x92\xdel,v13" +22:52:03.874737 version@stat F·[1] S·1KiB[1KiB] Sc·[0.25] +22:52:03.886343 db@janitor F·3 G·0 +22:52:03.886391 db@open done T·23.168312ms +22:52:07.281589 db@close closing +22:52:07.281687 db@close done T·93.376µs +=============== Nov 27, 2022 (CET) =============== +22:58:06.424207 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +22:58:06.424515 version@stat F·[1] S·1KiB[1KiB] Sc·[0.25] +22:58:06.424542 db@open opening +22:58:06.424607 journal@recovery F·1 +22:58:06.424725 journal@recovery recovering @3 +22:58:06.429476 memdb@flush created L0@5 N·12 S·950B "\x11\xb7\xce..:`W,v29":"\xe6\xd3\x19..\x8e\xc8e,v26" +22:58:06.429756 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] +22:58:06.441675 db@janitor F·4 G·0 +22:58:06.441722 db@open done T·17.162407ms +=============== Nov 27, 2022 (CET) =============== +22:59:37.874956 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +22:59:37.875149 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] +22:59:37.875170 db@open opening +22:59:37.875229 journal@recovery F·1 +22:59:37.875821 journal@recovery recovering @6 +22:59:37.878628 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] +22:59:37.897993 db@janitor F·4 G·0 +22:59:37.898042 db@open done T·22.855551ms +22:59:39.680719 db@close closing +22:59:39.680833 db@close done T·104.407µs +=============== Nov 29, 2022 (CET) =============== +07:42:20.161946 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:42:20.162409 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] +07:42:20.162427 db@open opening +07:42:20.162471 journal@recovery F·1 +07:42:20.162587 journal@recovery recovering @8 +07:42:20.165989 memdb@flush created L0@10 N·4 S·629B "\xe4\x0e\xc1..\xc8mH,v38":"\xf3w\xb1..\xc2\"\xf9,v35" +07:42:20.166650 version@stat F·[3] S·2KiB[2KiB] Sc·[0.75] +07:42:20.178614 db@janitor F·5 G·0 +07:42:20.178656 db@open done T·16.21591ms +07:42:25.529683 db@close closing +07:42:25.529789 db@close done T·99.909µs +=============== Nov 29, 2022 (CET) =============== +07:44:40.846342 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:44:40.846517 version@stat F·[3] S·2KiB[2KiB] Sc·[0.75] +07:44:40.846541 db@open opening +07:44:40.846595 journal@recovery F·1 +07:44:40.846734 journal@recovery recovering @11 +07:44:40.857884 memdb@flush created L0@13 N·38 S·2KiB "\a\x91\x06..\x1dS\xb5,v54":"\xef|\xb7..\xb4G#,v65" +07:44:40.858198 version@stat F·[4] S·5KiB[5KiB] Sc·[1.00] +07:44:40.870117 db@janitor F·6 G·0 +07:44:40.870180 db@open done T·23.619927ms +07:44:40.870311 table@compaction L0·4 -> L1·0 S·5KiB Q·78 +07:44:40.877022 table@build created L1@16 N·37 S·3KiB "\a\x91\x06..\x1dS\xb5,v54":"\xf5b\xab..\x92\xdel,v15" +07:44:40.877096 version@stat F·[0 1] S·3KiB[0B 3KiB] Sc·[0.00 0.00] +07:44:40.882327 table@compaction committed F-3 S-1KiB Ke·0 D·37 T·11.965483ms +07:44:40.882453 table@remove removed @10 +07:44:40.882576 table@remove removed @5 +07:44:40.882625 table@remove removed @2 +07:44:46.231241 db@close closing +07:44:46.231338 db@close done T·94.729µs +=============== Nov 29, 2022 (CET) =============== +07:45:07.114170 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:45:07.114410 version@stat F·[0 1] S·3KiB[0B 3KiB] Sc·[0.00 0.00] +07:45:07.114441 db@open opening +07:45:07.114520 journal@recovery F·1 +07:45:07.114704 journal@recovery recovering @14 +07:45:07.119754 memdb@flush created L0@17 N·34 S·2KiB "\x04\x96\xec..\xd8\x05\x83,v96":"\xf4I9..\x85\xddS,v79" +07:45:07.120520 version@stat F·[1 1] S·6KiB[2KiB 3KiB] Sc·[0.25 0.00] +07:45:07.132479 db@janitor F·5 G·1 +07:45:07.132503 db@janitor removing table-13 +07:45:07.132570 db@open done T·18.113518ms +=============== Nov 29, 2022 (CET) =============== +07:45:22.693483 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:45:22.693706 version@stat F·[1 1] S·6KiB[2KiB 3KiB] Sc·[0.25 0.00] +07:45:22.693734 db@open opening +07:45:22.693804 journal@recovery F·1 +07:45:22.693988 journal@recovery recovering @18 +07:45:22.694779 version@stat F·[1 1] S·6KiB[2KiB 3KiB] Sc·[0.25 0.00] +07:45:22.714155 db@janitor F·4 G·0 +07:45:22.714210 db@open done T·20.447382ms +07:45:27.631977 db@close closing +07:45:27.632069 db@close done T·90.832µs +=============== Nov 29, 2022 (CET) =============== +07:47:50.174053 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:47:50.174223 version@stat F·[1 1] S·6KiB[2KiB 3KiB] Sc·[0.25 0.00] +07:47:50.174238 db@open opening +07:47:50.174278 journal@recovery F·1 +07:47:50.174389 journal@recovery recovering @20 +07:47:50.185166 memdb@flush created L0@22 N·26 S·2KiB "\x0eN6..W0\xb2,v139":"\xd7-G..j\xae\xbf,v116" +07:47:50.185429 version@stat F·[2 1] S·8KiB[4KiB 3KiB] Sc·[0.50 0.00] +07:47:50.195283 db@janitor F·5 G·0 +07:47:50.195315 db@open done T·21.065239ms +07:47:54.508803 db@close closing +07:47:54.508920 db@close done T·103.886µs +=============== Nov 29, 2022 (CET) =============== +07:58:29.841898 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:58:29.842096 version@stat F·[2 1] S·8KiB[4KiB 3KiB] Sc·[0.50 0.00] +07:58:29.842116 db@open opening +07:58:29.842173 journal@recovery F·1 +07:58:29.842308 journal@recovery recovering @23 +07:58:29.853930 memdb@flush created L0@25 N·24 S·2KiB "\x19՟..\x99\xcd\v,v146":"\xf1Ot..\xf6Y\xe6,v148" +07:58:29.854233 version@stat F·[3 1] S·10KiB[7KiB 3KiB] Sc·[0.75 0.00] +07:58:29.865580 db@janitor F·6 G·0 +07:58:29.865617 db@open done T·23.487832ms +07:58:34.096259 db@close closing +07:58:34.096433 db@close done T·167.317µs +=============== Nov 29, 2022 (CET) =============== +07:59:00.141319 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +07:59:00.141465 version@stat F·[3 1] S·10KiB[7KiB 3KiB] Sc·[0.75 0.00] +07:59:00.141480 db@open opening +07:59:00.141523 journal@recovery F·1 +07:59:00.141633 journal@recovery recovering @26 +07:59:00.151793 memdb@flush created L0@28 N·22 S·1KiB "\x01\xd0Q..\x98\x828,v173":"\xec\x194..\x9b{\x1a,v171" +07:59:00.153147 version@stat F·[4 1] S·12KiB[8KiB 3KiB] Sc·[1.00 0.00] +07:59:00.168235 db@janitor F·7 G·0 +07:59:00.168286 db@open done T·26.784089ms +07:59:00.168346 table@compaction L0·4 -> L1·1 S·12KiB Q·188 +07:59:00.172773 table@build created L1@31 N·90 S·11KiB "\x01\xd0Q..\x98\x828,v173":"\xf5b\xab..\x92\xdel,v15" +07:59:00.172851 version@stat F·[0 1] S·11KiB[0B 11KiB] Sc·[0.00 0.00] +07:59:00.180777 table@compaction committed F-4 S-1KiB Ke·0 D·53 T·12.38572ms +07:59:00.180928 table@remove removed @25 +07:59:00.181070 table@remove removed @22 +07:59:00.181123 table@remove removed @17 +07:59:00.181165 table@remove removed @16 +07:59:06.057858 db@close closing +07:59:06.057942 db@close done T·77.697µs +=============== Nov 29, 2022 (CET) =============== +08:32:21.897521 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:32:21.897867 version@stat F·[0 1] S·11KiB[0B 11KiB] Sc·[0.00 0.00] +08:32:21.897899 db@open opening +08:32:21.897989 journal@recovery F·1 +08:32:21.898161 journal@recovery recovering @29 +08:32:21.908918 memdb@flush created L0@32 N·28 S·2KiB "!\xf5x..\xb0\x8a\x1d,v199":"\xeddY..\xa7K\xf1,v211" +08:32:21.909215 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:32:21.920833 db@janitor F·5 G·1 +08:32:21.920861 db@janitor removing table-28 +08:32:21.920979 db@open done T·23.06199ms +08:32:25.249911 db@close closing +08:32:25.250025 db@close done T·107.073µs +=============== Nov 29, 2022 (CET) =============== +08:33:22.392995 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:33:22.393256 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:33:22.393287 db@open opening +08:33:22.393370 journal@recovery F·1 +08:33:22.393569 journal@recovery recovering @33 +08:33:22.394360 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:33:22.413653 db@janitor F·4 G·0 +08:33:22.413698 db@open done T·20.383494ms +08:33:32.548471 db@close closing +08:33:32.548590 db@close done T·111.782µs +=============== Nov 29, 2022 (CET) =============== +08:33:58.605960 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:33:58.606120 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:33:58.606139 db@open opening +08:33:58.606192 journal@recovery F·1 +08:33:58.606754 journal@recovery recovering @35 +08:33:58.610119 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:33:58.629444 db@janitor F·4 G·0 +08:33:58.629493 db@open done T·23.332548ms +08:34:05.061623 db@close closing +08:34:05.061732 db@close done T·106.08µs +=============== Nov 29, 2022 (CET) =============== +08:34:23.209590 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:34:23.209903 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:34:23.209941 db@open opening +08:34:23.210041 journal@recovery F·1 +08:34:23.210286 journal@recovery recovering @37 +08:34:23.211278 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:34:23.230407 db@janitor F·4 G·0 +08:34:23.230472 db@open done T·20.495394ms +08:34:27.565814 db@close closing +08:34:27.565900 db@close done T·83.288µs +=============== Nov 29, 2022 (CET) =============== +08:34:43.133530 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:34:43.133734 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:34:43.133759 db@open opening +08:34:43.133819 journal@recovery F·1 +08:34:43.133958 journal@recovery recovering @39 +08:34:43.134549 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:34:43.148403 db@janitor F·4 G·0 +08:34:43.148459 db@open done T·14.671595ms +08:34:57.711302 db@close closing +08:34:57.711394 db@close done T·88.056µs +=============== Nov 29, 2022 (CET) =============== +08:35:00.550364 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:35:00.550567 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] +08:35:00.550587 db@open opening +08:35:00.550648 journal@recovery F·1 +08:35:00.550796 journal@recovery recovering @41 +08:35:00.562138 memdb@flush created L0@43 N·82 S·6KiB "\x00J\f..s\xb3U,v252":"\xfc4N..tYH,v231" +08:35:00.562424 version@stat F·[2 1] S·20KiB[9KiB 11KiB] Sc·[0.50 0.00] +08:35:00.573709 db@janitor F·5 G·0 +08:35:00.573759 db@open done T·23.156604ms +08:35:04.919517 db@close closing +08:35:04.919636 db@close done T·117.151µs +=============== Nov 29, 2022 (CET) =============== +08:48:48.728406 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:48:48.728657 version@stat F·[2 1] S·20KiB[9KiB 11KiB] Sc·[0.50 0.00] +08:48:48.728688 db@open opening +08:48:48.728776 journal@recovery F·1 +08:48:48.729592 journal@recovery recovering @44 +08:48:48.740938 memdb@flush created L0@46 N·22 S·2KiB "\x1b|\xf7..\xf72\x1e,v304":"\xfa\xaa\xa2..\xc5\xd1T,v302" +08:48:48.741248 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:48:48.752807 db@janitor F·6 G·0 +08:48:48.752856 db@open done T·24.148648ms +=============== Nov 29, 2022 (CET) =============== +08:49:09.982477 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:49:09.982660 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:49:09.982675 db@open opening +08:49:09.982721 journal@recovery F·1 +08:49:09.982862 journal@recovery recovering @47 +08:49:09.983075 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:49:09.995835 db@janitor F·6 G·0 +08:49:09.995908 db@open done T·13.215727ms +=============== Nov 29, 2022 (CET) =============== +08:49:41.609148 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:49:41.609395 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:49:41.609424 db@open opening +08:49:41.609504 journal@recovery F·1 +08:49:41.609683 journal@recovery recovering @49 +08:49:41.610363 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:49:41.632444 db@janitor F·6 G·0 +08:49:41.632506 db@open done T·23.061488ms +=============== Nov 29, 2022 (CET) =============== +08:50:15.106485 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:50:15.106773 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:50:15.106810 db@open opening +08:50:15.106920 journal@recovery F·1 +08:50:15.107130 journal@recovery recovering @51 +08:50:15.108048 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:50:15.130945 db@janitor F·6 G·0 +08:50:15.131021 db@open done T·24.178157ms +=============== Nov 29, 2022 (CET) =============== +08:51:00.732037 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:51:00.732202 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:51:00.732221 db@open opening +08:51:00.732272 journal@recovery F·1 +08:51:00.732405 journal@recovery recovering @53 +08:51:00.733144 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:51:00.752894 db@janitor F·6 G·0 +08:51:00.752969 db@open done T·20.715027ms +=============== Nov 29, 2022 (CET) =============== +08:55:34.166530 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:55:34.166721 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:55:34.166736 db@open opening +08:55:34.166782 journal@recovery F·1 +08:55:34.166899 journal@recovery recovering @55 +08:55:34.167067 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:55:34.186644 db@janitor F·6 G·0 +08:55:34.186697 db@open done T·19.929993ms +08:55:40.541442 db@close closing +08:55:40.541541 db@close done T·97.153µs +=============== Nov 29, 2022 (CET) =============== +08:59:41.463385 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +08:59:41.463562 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] +08:59:41.463582 db@open opening +08:59:41.463631 journal@recovery F·1 +08:59:41.463771 journal@recovery recovering @57 +08:59:41.475567 memdb@flush created L0@59 N·36 S·2KiB "\x14<\xae..[l\x14,v335":"\xe7\x80\x1c.._\x8ee,v324" +08:59:41.475793 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] +08:59:41.486893 db@janitor F·7 G·0 +08:59:41.486950 db@open done T·23.352547ms +08:59:41.487049 table@compaction L0·4 -> L1·1 S·25KiB Q·360 +=============== Nov 29, 2022 (CET) =============== +09:00:03.139305 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +09:00:03.139562 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] +09:00:03.139593 db@open opening +09:00:03.139699 journal@recovery F·1 +09:00:03.139849 journal@recovery recovering @60 +09:00:03.140532 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] +09:00:03.162388 db@janitor F·7 G·0 +09:00:03.162467 db@open done T·22.823367ms +09:00:03.162504 table@compaction L0·4 -> L1·1 S·25KiB Q·360 +=============== Nov 29, 2022 (CET) =============== +09:00:23.207116 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +09:00:23.207323 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] +09:00:23.207344 db@open opening +09:00:23.207406 journal@recovery F·1 +09:00:23.208021 journal@recovery recovering @62 +09:00:23.209251 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] +09:00:23.232273 db@janitor F·7 G·0 +09:00:23.232327 db@open done T·24.967579ms +09:00:23.232422 table@compaction L0·4 -> L1·1 S·25KiB Q·360 +09:00:23.245153 table@build created L1@66 N·174 S·26KiB "\x00J\f..s\xb3U,v252":"\xfc4N..tYH,v234" +09:00:23.245831 version@stat F·[0 1] S·26KiB[0B 26KiB] Sc·[0.00 0.00] +09:00:23.250034 table@compaction committed F-4 S+808B Ke·0 D·84 T·17.562381ms +09:00:23.250162 table@remove removed @59 +09:00:23.250201 table@remove removed @46 +09:00:23.250341 table@remove removed @43 +09:00:23.250373 table@remove removed @32 +09:00:23.250401 table@remove removed @31 +09:00:29.773978 db@close closing +09:00:29.774050 db@close done T·71.345µs +=============== Nov 29, 2022 (CET) =============== +09:16:50.047996 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +09:16:50.048182 version@stat F·[0 1] S·26KiB[0B 26KiB] Sc·[0.00 0.00] +09:16:50.048201 db@open opening +09:16:50.048243 journal@recovery F·1 +09:16:50.048721 journal@recovery recovering @64 +09:16:50.058769 memdb@flush created L0@67 N·34 S·2KiB "\x14C\x8d..R\\\xb4,v388":"\xe5\x9b\x7f..\xdbP4,v361" +09:16:50.059036 version@stat F·[1 1] S·28KiB[2KiB 26KiB] Sc·[0.25 0.00] +09:16:50.070318 db@janitor F·4 G·0 +09:16:50.070364 db@open done T·22.140208ms +09:16:55.700780 db@close closing +09:16:55.700875 db@close done T·92.324µs +=============== Nov 29, 2022 (CET) =============== +09:49:45.754492 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +09:49:45.754768 version@stat F·[1 1] S·28KiB[2KiB 26KiB] Sc·[0.25 0.00] +09:49:45.754810 db@open opening +09:49:45.754923 journal@recovery F·1 +09:49:45.755181 journal@recovery recovering @68 +09:49:45.765477 memdb@flush created L0@70 N·30 S·2KiB "\f\xe7\x9c..ë\x11,v400":"\xe76\x83..\a\xe5\xca,v415" +09:49:45.766390 version@stat F·[2 1] S·31KiB[5KiB 26KiB] Sc·[0.50 0.00] +09:49:45.778057 db@janitor F·5 G·0 +09:49:45.778102 db@open done T·23.271137ms +09:49:51.233998 db@close closing +09:49:51.234125 db@close done T·123.003µs +=============== Nov 29, 2022 (CET) =============== +11:13:42.253930 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:13:42.254615 version@stat F·[2 1] S·31KiB[5KiB 26KiB] Sc·[0.50 0.00] +11:13:42.254646 db@open opening +11:13:42.254705 journal@recovery F·1 +11:13:42.254874 journal@recovery recovering @71 +11:13:42.257910 memdb@flush created L0@73 N·1 S·492B "=\xe4\x1a..\xf1\xda.,v427":"=\xe4\x1a..\xf1\xda.,v427" +11:13:42.258137 version@stat F·[3 1] S·31KiB[5KiB 26KiB] Sc·[0.75 0.00] +11:13:42.269683 db@janitor F·6 G·0 +11:13:42.269749 db@open done T·15.07535ms +11:13:47.687039 db@close closing +11:13:47.687172 db@close done T·124.195µs +=============== Nov 29, 2022 (CET) =============== +11:14:23.692113 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:14:23.692343 version@stat F·[3 1] S·31KiB[5KiB 26KiB] Sc·[0.75 0.00] +11:14:23.692363 db@open opening +11:14:23.692417 journal@recovery F·1 +11:14:23.692552 journal@recovery recovering @74 +11:14:23.696111 memdb@flush created L0@76 N·1 S·492B "=\xe4\x1a..\xf1\xda.,v429":"=\xe4\x1a..\xf1\xda.,v429" +11:14:23.696625 version@stat F·[4 1] S·32KiB[6KiB 26KiB] Sc·[1.00 0.00] +11:14:23.708232 db@janitor F·7 G·0 +11:14:23.708297 db@open done T·15.902515ms +11:14:23.708332 table@compaction L0·4 -> L1·1 S·32KiB Q·430 +11:14:23.712124 table@build created L1@79 N·206 S·32KiB "\x00J\f..s\xb3U,v252":"\xfc4N..tYH,v234" +11:14:23.712183 version@stat F·[0 1] S·32KiB[0B 32KiB] Sc·[0.00 0.00] +11:14:23.719919 table@compaction committed F-4 S+23B Ke·0 D·34 T·11.548244ms +11:14:23.720077 table@remove removed @73 +11:14:23.720244 table@remove removed @70 +11:14:23.720321 table@remove removed @67 +11:14:23.720409 table@remove removed @66 +11:14:27.464580 db@close closing +11:14:27.464687 db@close done T·103.987µs +=============== Nov 29, 2022 (CET) =============== +11:14:35.665718 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:14:35.665944 version@stat F·[0 1] S·32KiB[0B 32KiB] Sc·[0.00 0.00] +11:14:35.665968 db@open opening +11:14:35.666029 journal@recovery F·1 +11:14:35.666189 journal@recovery recovering @77 +11:14:35.676084 memdb@flush created L0@80 N·1 S·492B "=\xe4\x1a..\xf1\xda.,v431":"=\xe4\x1a..\xf1\xda.,v431" +11:14:35.676293 version@stat F·[1 1] S·32KiB[492B 32KiB] Sc·[0.25 0.00] +11:14:35.687856 db@janitor F·5 G·1 +11:14:35.687893 db@janitor removing table-76 +11:14:35.688006 db@open done T·22.021528ms +11:14:42.385051 db@close closing +11:14:42.385137 db@close done T·90.101µs +=============== Nov 29, 2022 (CET) =============== +11:14:54.445849 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:14:54.446024 version@stat F·[1 1] S·32KiB[492B 32KiB] Sc·[0.25 0.00] +11:14:54.446045 db@open opening +11:14:54.446090 journal@recovery F·1 +11:14:54.446244 journal@recovery recovering @81 +11:14:54.457542 memdb@flush created L0@83 N·34 S·2KiB "\x06s\xd7..C̝,v466":"\xfe\x15\xd5..\xfa\xc2{,v456" +11:14:54.457920 version@stat F·[2 1] S·35KiB[3KiB 32KiB] Sc·[0.50 0.00] +11:14:54.469380 db@janitor F·5 G·0 +11:14:54.469436 db@open done T·23.37376ms +11:15:00.257359 db@close closing +11:15:00.257460 db@close done T·99.068µs +=============== Nov 29, 2022 (CET) =============== +11:33:07.370281 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:33:07.370471 version@stat F·[2 1] S·35KiB[3KiB 32KiB] Sc·[0.50 0.00] +11:33:07.370492 db@open opening +11:33:07.370543 journal@recovery F·1 +11:33:07.370670 journal@recovery recovering @84 +11:33:07.384761 memdb@flush created L0@86 N·28 S·2KiB " ;\x8c..\xb3.\xd3,v473":"\xde+\x92..\xdaM\xcb,v468" +11:33:07.385064 version@stat F·[3 1] S·37KiB[5KiB 32KiB] Sc·[0.75 0.00] +11:33:07.396822 db@janitor F·6 G·0 +11:33:07.396898 db@open done T·26.389813ms +11:33:11.230303 db@close closing +11:33:11.230404 db@close done T·91.523µs +=============== Nov 29, 2022 (CET) =============== +11:36:41.218234 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:36:41.218450 version@stat F·[3 1] S·37KiB[5KiB 32KiB] Sc·[0.75 0.00] +11:36:41.218476 db@open opening +11:36:41.218536 journal@recovery F·1 +11:36:41.218692 journal@recovery recovering @87 +11:36:41.230324 memdb@flush created L0@89 N·18 S·1KiB "\f\xce\xda..~\xde\x19,v512":"\xc1\xd5v..\xa9_\xd0,v511" +11:36:41.230703 version@stat F·[4 1] S·39KiB[7KiB 32KiB] Sc·[1.00 0.00] +11:36:41.243562 db@janitor F·7 G·0 +11:36:41.243625 db@open done T·25.13154ms +11:36:41.243698 table@compaction L0·4 -> L1·1 S·39KiB Q·515 +11:36:41.250854 table@build created L1@92 N·246 S·39KiB "\x00J\f..s\xb3U,v252":"\xfe\x15\xd5..\xfa\xc2{,v459" +11:36:41.250991 version@stat F·[0 1] S·39KiB[0B 39KiB] Sc·[0.00 0.00] +11:36:41.256213 table@compaction committed F-4 S+715B Ke·0 D·41 T·12.468741ms +11:36:41.256440 table@remove removed @86 +11:36:41.256493 table@remove removed @83 +11:36:41.256537 table@remove removed @80 +11:36:41.256589 table@remove removed @79 +11:36:48.974288 db@close closing +11:36:48.974425 db@close done T·131.418µs +=============== Nov 29, 2022 (CET) =============== +11:40:21.440991 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:40:21.441249 version@stat F·[0 1] S·39KiB[0B 39KiB] Sc·[0.00 0.00] +11:40:21.441278 db@open opening +11:40:21.441343 journal@recovery F·1 +11:40:21.442025 journal@recovery recovering @90 +11:40:21.452456 memdb@flush created L0@93 N·40 S·3KiB "\x00K^..}\x06+,v526":"\xfb[&..\xfa\xb8\x1f,v530" +11:40:21.452713 version@stat F·[1 1] S·43KiB[3KiB 39KiB] Sc·[0.25 0.00] +11:40:21.464385 db@janitor F·5 G·1 +11:40:21.464408 db@janitor removing table-89 +11:40:21.464471 db@open done T·23.181562ms +11:40:26.940578 db@close closing +11:40:26.940732 db@close done T·135.786µs +=============== Nov 29, 2022 (CET) =============== +11:40:37.971310 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:40:37.971565 version@stat F·[1 1] S·43KiB[3KiB 39KiB] Sc·[0.25 0.00] +11:40:37.971599 db@open opening +11:40:37.971680 journal@recovery F·1 +11:40:37.971865 journal@recovery recovering @94 +11:40:37.982092 memdb@flush created L0@96 N·30 S·2KiB "\x18\x8bK..\xf2-\x81,v568":"\uf612..\x7fm\xfc,v559" +11:40:37.982590 version@stat F·[2 1] S·45KiB[5KiB 39KiB] Sc·[0.50 0.00] +11:40:37.994292 db@janitor F·5 G·0 +11:40:37.994342 db@open done T·22.71424ms +11:40:40.725398 db@close closing +11:40:40.725522 db@close done T·121.53µs +=============== Nov 29, 2022 (CET) =============== +11:40:58.970497 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:40:58.970667 version@stat F·[2 1] S·45KiB[5KiB 39KiB] Sc·[0.50 0.00] +11:40:58.970683 db@open opening +11:40:58.970727 journal@recovery F·1 +11:40:58.971191 journal@recovery recovering @97 +11:40:58.983036 memdb@flush created L0@99 N·10 S·941B "\r\x17-..I\xe2s,v591":"\xe4d\x8b..\x05\"\xa1,v589" +11:40:58.983304 version@stat F·[3 1] S·46KiB[6KiB 39KiB] Sc·[0.75 0.00] +11:40:58.994970 db@janitor F·6 G·0 +11:40:58.995027 db@open done T·24.327832ms +11:41:01.462301 db@close closing +11:41:01.462420 db@close done T·115.288µs +=============== Nov 29, 2022 (CET) =============== +11:41:17.790982 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:41:17.791219 version@stat F·[3 1] S·46KiB[6KiB 39KiB] Sc·[0.75 0.00] +11:41:17.791251 db@open opening +11:41:17.791343 journal@recovery F·1 +11:41:17.791644 journal@recovery recovering @100 +11:41:17.804109 memdb@flush created L0@102 N·12 S·1KiB "_Ex..6D\t,v602":"\xb9\xe3\xdf..f\x93\xcb,v605" +11:41:17.804456 version@stat F·[4 1] S·47KiB[7KiB 39KiB] Sc·[1.00 0.00] +11:41:17.816095 db@janitor F·7 G·0 +11:41:17.816136 db@open done T·24.869396ms +11:41:17.816209 table@compaction L0·4 -> L1·1 S·47KiB Q·611 +11:41:17.823577 table@build created L1@105 N·292 S·48KiB "\x00J\f..s\xb3U,v252":"\xfe\x15\xd5..\xfa\xc2{,v459" +11:41:17.823700 version@stat F·[0 1] S·48KiB[0B 48KiB] Sc·[0.00 0.00] +11:41:17.828209 table@compaction committed F-4 S+906B Ke·0 D·46 T·11.951541ms +11:41:17.828425 table@remove removed @99 +11:41:17.828489 table@remove removed @96 +11:41:17.828549 table@remove removed @93 +11:41:17.828617 table@remove removed @92 +11:41:22.550350 db@close closing +11:41:22.550475 db@close done T·107.904µs +=============== Nov 29, 2022 (CET) =============== +11:42:36.806480 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:42:36.806778 version@stat F·[0 1] S·48KiB[0B 48KiB] Sc·[0.00 0.00] +11:42:36.806826 db@open opening +11:42:36.806907 journal@recovery F·1 +11:42:36.807096 journal@recovery recovering @103 +11:42:36.817410 memdb@flush created L0@106 N·24 S·2KiB "\x01*\xa2.. \xbcv,v635":"\xc0{\x17..\x04\x14\x7f,v618" +11:42:36.817692 version@stat F·[1 1] S·50KiB[2KiB 48KiB] Sc·[0.25 0.00] +11:42:36.829507 db@janitor F·5 G·1 +11:42:36.829533 db@janitor removing table-102 +11:42:36.829608 db@open done T·22.768559ms +11:42:44.521220 db@close closing +11:42:44.521341 db@close done T·118.173µs +=============== Nov 29, 2022 (CET) =============== +11:44:14.688221 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed +11:44:14.688424 version@stat F·[1 1] S·50KiB[2KiB 48KiB] Sc·[0.25 0.00] +11:44:14.688449 db@open opening +11:44:14.688517 journal@recovery F·1 +11:44:14.688700 journal@recovery recovering @107 +11:44:14.698549 memdb@flush created L0@109 N·40 S·2KiB "$TM..\xbf\xf6q,v640":"\xf7\x90\xf8..\xa5\xf4!,v668" +11:44:14.699389 version@stat F·[2 1] S·53KiB[5KiB 48KiB] Sc·[0.50 0.00] +11:44:14.711523 db@janitor F·5 G·0 +11:44:14.711564 db@open done T·23.09984ms +11:44:18.276344 db@close closing +11:44:18.276475 db@close done T·127.732µs diff --git a/example/trie/MANIFEST-000111 b/example/trie/MANIFEST-000111 new file mode 100644 index 0000000000000000000000000000000000000000..ba6e48d698d65e3509c8653ef7d0a9ea3a78b702 GIT binary patch literal 434 zcmZoo{N%oxk&#g?`Sng zr(JwYk0}ZJPqlum#@i9UByd&K$%cn|%N2g@kY^NPVgLblhTPBM8Y&^azCR|mtgDj9 zv)?IcB3atH^t$dzuAWm1m^Mw>|E-X*0is&t`-C3}{u8z**tEr(PL^@8XWX2Syv5^@ ztD?Xx`%O!~C^F8Wv9Vdpg*6zp7Ci}DDxW*&I0K{pSGS8kGi>xiSJV`3wh(0QRM=C- zSPgaUfok#cG+Xzzp(~zb&zf-4`ovV_hlY~oZxs3hi&a=e>KU`3u4T-e+QO{C;KdUd z^?Ji)sh#_@Z_k~Yj%Y~LmB^ogN#ArpXk*;TLK Date: Mon, 12 Dec 2022 12:14:37 +0100 Subject: [PATCH 02/24] Remove example --- example/blockchain/000106.ldb | Bin 42912 -> 0 bytes example/blockchain/000107.ldb | Bin 935 -> 0 bytes example/blockchain/000110.ldb | Bin 1766 -> 0 bytes example/blockchain/CURRENT | 1 - example/blockchain/CURRENT.bak | 1 - example/blockchain/LOCK | 0 example/blockchain/LOG | 493 ---------------------------- example/blockchain/MANIFEST-000112 | Bin 443 -> 0 bytes example/libp2p/libp2p.key | 1 - example/trie/000105.ldb | Bin 49685 -> 0 bytes example/trie/000106.ldb | Bin 2471 -> 0 bytes example/trie/000109.ldb | Bin 3059 -> 0 bytes example/trie/CURRENT | 1 - example/trie/CURRENT.bak | 1 - example/trie/LOCK | 0 example/trie/LOG | 500 ----------------------------- example/trie/MANIFEST-000111 | Bin 434 -> 0 bytes 17 files changed, 998 deletions(-) delete mode 100644 example/blockchain/000106.ldb delete mode 100644 example/blockchain/000107.ldb delete mode 100644 example/blockchain/000110.ldb delete mode 100644 example/blockchain/CURRENT delete mode 100644 example/blockchain/CURRENT.bak delete mode 100644 example/blockchain/LOCK delete mode 100644 example/blockchain/LOG delete mode 100644 example/blockchain/MANIFEST-000112 delete mode 100755 example/libp2p/libp2p.key delete mode 100644 example/trie/000105.ldb delete mode 100644 example/trie/000106.ldb delete mode 100644 example/trie/000109.ldb delete mode 100644 example/trie/CURRENT delete mode 100644 example/trie/CURRENT.bak delete mode 100644 example/trie/LOCK delete mode 100644 example/trie/LOG delete mode 100644 example/trie/MANIFEST-000111 diff --git a/example/blockchain/000106.ldb b/example/blockchain/000106.ldb deleted file mode 100644 index f906e74fb98e73b89c408e66e8a14091b377b1ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42912 zcmchA2{hGT*Z)*O}t!u5__q)$I`|Pv#XMfH)(Ms)>3^mpgMn+na z%=2-NoHwm_FuOKADWQtf>RFp2wmO#Y(D?@0M3}_r`Bz$83?o@A=DMq&_P;V~Rk{)H zYi{agzJAsDls1{U*SdMl-OMc&pa~c-no-Ku;&A5}?h#(~rk?MPR#fQ+)w;8Mm19*p z>-{*3U&=XssM-p98K5bs#o<@HV%RVu&;EXfEoYnO)!USZ5Zn zKwgU@;5%2mEY_vl>yzp@xuNFwSQZ&>?OaJB(L5>k%$b6-U<^}KE0#HebvtA!r!6X< zB{^-yK^+(N{L6yMPAgkJ-{+Z>A1~uK4;Fx^W&&x6;O6sVc8dO-d}!+fH~BaG)#lOf zUG?g7MlNc4)zTGtGYMjtq$PaMIATLciDZqs8ku8 zcxHJ?YM07+KRexm`SAF%H&n6Y?Kw)`#+7Ft2@Tt8+vsW6>E-u%^U|_i$F%i^@gIA- z_sM527{nyqH`K|qVNIVps&aOkP12PWU7)BB6X~;5-{e$`7Rgjt7Q5v01@U|LWjW7^ zOE%@4*dg}5TRLrM0|ZhjwS~58eJ2YZH8pQ~t+sNVQFNza<{1fb+tme+9nU$am_i6k zRLh`&qn^pKGvya%CUr0)%6B+g?q%;>_p01|A6xRabhwxK5SY#o9Zd&JL$t*?==__U z_d8~vNiL7{n%Qmpy!lp@J9o~GZ0E`TDNw^A1E%(!qsdi1dG9Ul5#?N+j~rH{D@iN} ziC-sC((1k9$YQs}HkvS!3>YyyEusCjN4yus=-du;ZJHCXgFm(5P({#e@7NI2)0W$2 z3&IcRH7S?IV3Tj}rGtyPl&u?t7u#=K==m_fURmzt;>{bgv*MtO(L1bT4pxVB?tXca z%m3q*?D!*39&a+V)Epro6L<6WSy<#D2;6K7IRcuJw&T8Ti#WYR{?4`rJ?<_I z#ge40xoKO>d=($A1s?{R8s2#JbDy#-?c@M0Tdy0s_O4dPq@=D)kO|Ap+~)j5mNge1 z_vx4Do30YrwrN7^hP>zTZhI$n4AIf6TCyqNg+cqmNe`moI5Bx@b`$E~JE)Hr<^Iet z=2bn(zWhO7obw}W+xN}`tEa0T|858QJ^Ja`l{$cu4iS=H?5~NmIhYMJkq{?&0?C5Zq;Ab1p}=P;7p3+shsTQdt{;0 z=%PtsBTludr%6TgWGTOm++k9$b}<(Z-X_M#TfV!@wMxKPFo9oHO~c7giAqr2VJo?eE(f z#XdJuYSdcW^Cy>u%@KdL=Fqs8UZIU4KW*>Efr{3124`yH!5FDh1+S!1fuvD&YdAk& zzwdbaI;prb&tsXU&4+e~WsqsB@4eJGdxM+TP`#*jen${c)Sg(rQj!s~_C>dU=<{j` zXkd^@WS}=L*u8ju(#o5!R(oCb4rz;&=iI0Xlu#>EI^*VM6#?0dUK6csX-Sa(lJ_k* zEc@C@lOV~3VHQz7)h+k4WEAt%8{R={pNY;KQt>KeZ$QB};m6s_Zq7JAEm;3Czl77- z*AqO4EwsMA25zu5H4k!3V)(iI6^@oxNlL3{9cUZ$rgKq&$0d!3;yr1REAwS)L5$gJ z0`{D_cNb|XRz*lwTv5waJg<7=p_+ZPnYOz8wHIE?yHeNPhoQ6~=H=J)BE?sQOtd&q|%=h2l*|N2yJlxeMz0-1q%^4Yi%iQnO0O1wQ&_bVk^Aw@-16;q>DR znP%Rhjhb+)&z9$feo|j_Wjm95C-+G?hur#7eZ9xcJL5%4C*I`!c0H~b9z2kuHqe|s zD}L#orf#SG`k9NyEw9NPA|H{PJ~PmB_9h+e#Y#S*Ky?VI+QE|D`mb@l0@QM=c!oquMS^vxyk4%k{`78%!Z z7MTcE3_Uy{|3`33*nO_cL!LRURv6N1C+D`)Yv>)ri6-!h+3Nx=#~)OU@wBQoTGnXC zUYWaR&{W}kyT6`>y)zZz(5Q+NH*%S1-Flu1uxuR~p=cj9Su*8A z>#<13via&4TaAz0d8IMZxbE5waHNZx?P`nL7q7^MHm%8i>iNmL`i;csnIS*l6>H7k zv-slBQDHEdB_A1d()ZTfy#lXZUK_kn`qS|7Z-+l}s6XsJHhfZYl-k$KAjs0PV{jbO ztplUGriaM3*tTD_lr|i7prUQ7s6~XbjCgi^IJAKU9b2NA^KC1ylLao~U7WUZnJekb zAL_|Z>&}_#xK;gA!MV5+cQ{JMY%rBvQhN5?NRhTN!_(95B^|Q1^xLrF;hx*el+w!8 z_74?RJOFF7_ft8ywVkE1+=3&{d=nEX+Nc>(a)_7VDzUr5^Yw`Q(=sa8VU~nFwSnwR zh0fOaD8(n*tqu{{Zze2gP=58rg>zg&$YX}>JCkIwkIs zZ|0qA@Quu&lnVhf)lXS1U66P#Y^I6j`5EG3PTZz@X6V#?Pba%ip~CIzv1n<&xGFpEl=`yjR~9mR&FUco`(A zl<&*qf>X?u-b|M`t<2eXF5HFbwR+J{!8Ep%!aRwO0xWn+2f$BwgN0SMeX5IXcj3yp zp0^C@p6zH9tmry7^Jk=M&A|q^)VClThMz2eoPuZ7au#9Udxnk=k;|WSEGR*>EXgBJ2TzRKID-GY!YBUp zB>`{Jx^{gp^r&_Tw{~d_Gv%JZ#QGC@u&0^dTYAfz@#DPCfe~jF zoTpM@%P*@A{eD)s@t(T>CD%36AkAGuGooqsm#w3YYHr-$0i&r@#L~uhrCRgq-!IrZ zZGUy;$}_{A#@T#7xve~AM)+x6{grTtEKVfC;~YQ0IJ*3P^coM(QoUtM26x}uqQQ_{ z@h1D}#Hh@dvWC`pH-uFaI*na5RP1labC1p&N zD_6I)m93lfD5bee=8#&a>f`9uFsgr=mvF>cBy~{W1iKS&!T;*vw)T~k<~22b<>ZXl?=8PnFwRc2rXN9DE7VoH*GX$%?80Ex{F(F*n2aA^GD42&At*R;3vGTqh z&3>`f-L~Y8;XW-;)_TU^WUgLmDwgY!!&&fQTt|TI!qoG3c_(a74UCMOFF)eP%?%(< z@ z@vd$LGfcOQfNLbup`NjjbvW2}3|u^-r7iChQu)F5Nm9YHyC1jSSl(u7BzRm0u4=V1 zIG332BcvNYUGk5ZGc7{C`N!6W)x6acx~FEJ{+2Ok&fPT-M?GW7lsh@#pO`q-b<=^9 zUDIz~4ynB3{&;xG+(#PnwQ<8Lz@aaQPCBq=p5C~(kFKkPSiH=flQ`Mc$N9i{;p(;> zX0}|JwXlvQuNm~|%OPps#KWHqwk0_)R~a=q_s9b6YO}JvL3un6mhP$o9j#mj=W>SV zLzzVnim#en*<$-}Z2OBDnWKzbZYspQ&4^K0@^m!JW%h<9*Wb!5xjk2Ci}SOs(O*_Y zTQtau+}pqD@ybZwjYo!_HM$H*TFY3R8!NWx+Y2U%H&3n9uAO;pn63Llo(W}%ZTtLB z4LVS?@G}(kxx6s>qnEA(ICmLTPbyz2w?bs?wk=OaI$1lbE}Ly;GwnTC&=$PDaCuZ} zk=2F?Q|}!e^Yen#!^%M+cia*zTr##qDI9D8XRQ_n=ay@ZSGTBt@R?0VQkLlZ-g!NE zR@9BnM<*8vEE13YnsN(L`&w|v)quNt(RG25mqin}lieRx=^3~;@h)e1n9LK1*R6|( zQnse&Zcb%s#ItP{!3)|9B&)-0_$NyY`<8J-dsmrC$+(ElS;IVlLy}%b=~3WR4P!JP zFSQA)a*$kKc59dMG~Q>?JnxKbO$(b_TOPF!2G_pfI$@Nzc$3PQ=~*YUH!pLQG%6YI zBYP_*vcAH`E#2s`HFywrLejhY;s>2qRo*)9ban8a-P$vay1gz9ueX@A*1_C9ey_Z$ zJ_z?MKaV;@y`twFs9I99Yom`~_R)sIlJ%?7noDY?eyW?!(R~1(S~r06xb*Ojq{_ON z9}PXE>Mv?a>+$+<$#$xyj(cgl?EJx7{;-wWT)m#-Vs{vA#TU)rx<&Ad)wcEPZH=Oz zYco|H^J*fDd_j<|15Lb9Z+7uaZz^R?+g0G>Ej7k;l_O8$xhl_~E>-7>@L*U-C)XSP z+3rcDmBU(>y+}&hX};}b-Rb?znA(Ewc`Bz~ZOgX?FDmse>iLk@o$`EU`5%>Hi{|L@ z8?KwRdVl58{ZVO-%CB1I!3(;ke0=WgKf27jT9>6#GfXggins^s6iQZEK6^jTjF4@R@peU_{= zij?(uW0JaaC%d_3+fS2;rTeanJAV*_sZ{FQ;M)4V&-Q%U$e7fU#4ncny++kYR^^A} z*hr0SrOTbWA)f|d-^WfXv^uD`R`P&qbCdJg`(fKeW|SB&jrcwyAi6@n)(Y&XUY(6^ zMp_oVoL|ogwvH~hPd{R6bE?pC#)HkmqL?pwCLMT^U>$?fHqq_ zfq{kXM3NV#5KS;JnF#WM5!D2P{fHz#%q5y6V7V5N90UugB$f~oNdZ_)BpJsymGaW| z34%*cZ*JzHe+hvHpGM$0HvKIOUVIt>7&PQi#w!B8d=nBdOpiQK6as0(F`SD?4u&wI zq#pt`7>9Cni-z~CqHd6V}Jn~3o_&~>Q9)ed9$)WI#!KV?60ANIL z7%(K?@g-;>FgKA@0Ulu6Bw!UAA~_s{fy}eRn;r<#j!*?jzO9UeO@oE$Un4-CPs0yM zSY77wj)dW4KCbI|f*NR$`G{tS5A5qnHgu6>LkT1sawgf($Y0rza`pTC14<&)S2OrP zU=)l8Hh%(^>JoL;VKQk;LJ1Q25lIa&ppw|aNF+637L~*j7$T_!7F043NuG%0Xt1J^ z0!RgnNR9yqDv7~~L~<;+Qpp=g%t$21!73_Qg+ygUaycSy1e*&=dpZJ5xaFowE z0gJ=PBlRE?*v<*#ks1(@oC4Xj;TW1kB&R|?mBg?jA~_98sU!xB5lMY0r;=D+Mk0aQ~-EZ!rMGvEo8#42h;(h#0eNvzIIB#q!Tk@Q32ZkHpx#_&w*OyWw1j0;OAMtV zl2+hJB{8gzNLs@>+8!ilEm_5D1OB8vhY?(kJkb_HNP7Y>)&Vih#Sq2k?1vOn3=Z(x z!A=r?AOw(-TfFv=K!QFir2a)zbbur#`$7T+*b+%cNTVHzp({kv2~N_EL=tv`GG1rM zA%>3ObmWOHP(Td>!|I6S61YsY#9${PxfE_tNetH`lCDriC9%2_k#vI^Dv4EiiR3b9 zq>@;1nMk@rE0x6RJVeq1-cm`dCQBrjLkE!z_<_I(#4uOD54GY1tbRuxxe~Zo#AE6r z%mpI33Ite0O^mBSBt1clNctf#n1PqTYLKCi#42Xwk!wJiO8!8w5hCeDuv{XEF(-)R zS{O|wv8o=C^oEI45-Us+NgtR-C9#?_kz5DHR8j|_su0QbFqcYVMJ*z^0Txop8we;% zBz?h-N^V0cRz%VdmQYEo)=nfh!g3-RfI()&Iyb>u(;*2M`bi$?4}Qct{Yw5jPA;^S zmp1^m@Yy6_bsX}@%@EEaJ_#d>5y?P^A?@+A{O{BTu;JZ8V34f|9uNO}8Js*Z2=dmGnaj%S18^iil(Y zin7YNTRGn66F_yePzRz$cH22{v^ubaGgaGWvog?-W>sVsFqlzlt^;m zA(g}!jzlsN>WO6gOpN`8UnoZSy&(n z+Dro0Fh>BAy@NIIsS`RRAmK|A>>~VCP0+yktFxIv5M>ArLXrgFleXqy!8|B3`K)<~ zeu3OfE~qvQ2aRM54F_U{^dA@q<8)RLCLiVR0tO0zKPlGI_G5uPOd;)OYv8ojP$n5i z%u_)Gi%4PUHW(Aj3Dje8!4q8zLJK=Oy zKLSXC4Ng~WfL;qnpbE(9(+@*)p_r}C4&`7W5D2o^n#8t>I2e2j4;g%#bPgg>0L*0d z_8^Ak!xp09X`HfpfGjR9Yv`Mizz^7cZ^jA}u(qdfu(%7lZg945wqk`z zSVTN+BL^#QE?Xc;R#KmnD)YIiV!N@2xo zI84V0%jdz2jsRMJ)TD33U~EwBTRV_^AME=^0ILWu{DG z8uksRq9y@blO1J$on(vQBu+OZ*@)R2A6a7#^ z>S#JFC=pePb~uJh!|J{cM~bL0uP?d6kP8SR3{;w2Ugc71^x%0pF^uElAn(hQRPVDL8N zk`X3O2m`mFkcL^r{4m5CZfc&Va#+Ch$A7$>0~>(d`4pO&mu4#u6qu|`*jthQ z-N5MmyamRDAl}e<3`Wq_rJ;4)LCJyqz~G1~6A17rei}hDutysR2VlI9C}AdN{kV-X zhK3_{4pJ;wv2O2e-K(S5vFa4YPpW$RdGtkpuGK`>4R0Ytnb9rG{QWTyW*C|Y^M>Wh z=8;EWgi1(YSPBPVSPM}mK*N3_bI|(d@40@o-woK~nY7=+eU{#ZOY8RSK5>riRWmc> zKWQQ{UzjUnD^&!Aq`817f)W0xBG2|4#@%f?QZvqDQPG^OKTA?i2$q?AJEk#M!>ag4 z`!dDe}kO$DIgO(4rGmWQ`se`5b)JXhS8}ZvXTr-cIb#Z@Wh(x%r{xWaH%!Vx) zX(J{!=PgS3JzaW#me| zCx<7h{2anHJ40OK$WaB2fm+NbTI78vc3Pr=);`#(lX(LWzLj8<5HrAWbhqb{8Ou&R zNfyh}o_RYq)Mn_?48<1>QECM$$&ofuzsIEahp7-_78#gaB{DE28hCj{mKiS}fN`&A zcQhWIlN4vEMRV^D?2b8>!VJ~3!pztf7FL*p zdn_~I*rsHx)JH5ga5jIyS*=+sHIl3woR(T=ns*PoIJSfPyM5r$LJ#RrKTb$4i5Q>@ zS1@P32v<|VSrI0ugN4?QBy9x*$fEW!Ss^nR-2pcYUay{uNbxbpxLtR6DIVOw+2LgW_6UMFUH+%nSA@$m@{Y}O7 zNo5(@S<^E$R(vnldExh7K6T4I3zeTAuI#$=zjjQfzZ_Gp@^8n~GyT!(nJ-y6FHpaW zfsOr|=P3O5&Z*xb`dygGm_Vjt&P(bL&~n`*;t1S6cm7V4QW0vnx*<_*tI$gScmy}#JE z>>cm4ib4hLimY22*DR#(sd`H`Hx1OnmS|BRPqjenjiD@}1%_8pEh5rKy5w_K>F9M! zcX(L|+}*QZo+q_1G$B~pP2XyAg2O;9HWMux3#k@pJ=1_jHdypYwP+D4iN4(NB6#E? zg)>Ey!)w163tmupmusT5hFv+l%yZU2E%?lY1w!j@1f872PdpRG1AxcGGjW=dF%Om; zK7}{H^@D(e#u|ljrxvan6P_Qq=3T7hvN~7iiM#f$-^UTUG-iM@T)~lMB3xljmlV11 zs;wH+OoY>zjG=+a;Udg{qhDH&zcxFw;;h$&H?qRtUq0nj9uvyeXsbVZSEtcF?rygT zv;W6bgkd&cm^XK1P?{oFKOZ(_YV=Q~zTgU5tboKY^dFt%7{J(XlK+zr6B#kz(rtqH zhYh>3__MdakMw(|#8Z|d^Vshg^Jl#Hi0Z%dVT_A>r+>#*J;A@pZx^QcJNWO3t*|op z4?ay2Tg^l2Y5iK}NJ68Ah()VfvQv2Nlvo759(llOy z?+u@leUkspMva9TKr)ih+Acb8v2AIvj?P=Gm`vww^X6fE%b%(%b*8#q_xGJLB(+nd zL1_3Wj>Pqt>d9~85B{4PB*qh=iBZO4ss@&SK`qTku)LY7alZ4u@vE=$sr3hUY>ym% zZ+Yh6?8@tBraU@xX3@PgSMzHF)tEt?SguS432SITj&TptCHL`_XaryY1P%1CFnnO3 zr)Md|U=bq`(&Oczk!twWwWEf9gy&dMb>x|j7lGE`` zYgCqG59|^d(j_OP>A;}e2|l{IV02WfMe4K}wUs{v*IsyTzcJ#-DBY_Kv)tuQa@ zj4hLW{-$W47ORLBwb5i?{`jx`SGr#ZDJS>jhA3I1iUe)U_C)HwFor8Uq8a-dI($!FIhtZ+HYVTXGMAyIfXH9CuK{3(&VNi6<$pP}ti69?GHRO` z>tqH!^};|1El<b1eP!H?iDIG=M#bNjrm;Ooiads?JR?lw<(7}}BQ5H0 zqHl$mW5Z>VvQfbIg7tLc z-Oo=a!|WdxiO~ZMM3fjvh8;;r+HG1`7)cWndI_4}peY&Se)cm5M-A=(71^hb!r~JP zBFkMd_IkG;H8CJxYyD>#T`Cym7!BFqxaAdIpDHJSk!^*c&| zD`0AijEd5UwdFy#xUbARH|)ua@f%?8@d8WD#L^?uUg`)lWMJNaF9>oAC1D>zUYVLDp2 z)TyAPqv6!4V3;QD64j5wiB9f^%RlrLG}WePUyiO@np!6r+lt}a4<%hcJ#6f_ zoYy&J^%oQUxow^rB@Bj)@w4UbbHl#CR1&X`_qeQZP^#@#fQC$JahV8QB-b!H%fjJNJojrgE?eo z2Fr7>#R+bbXfRkl0IOm3m?HB8_^y`Qv7X1!pkSg;%Dj~2yFyxP+>Q#EOdmQ!XMX=y zliwr?lOv$c9y%W|%m~D3I*S1xR0*%H6uWufQ_sH1xIgp4*E=C9ueaqiDZJRN(w*re zyDEiipc1o5*XItWTA<{+VRTkv)EcTqYRX(!@y%0xW5ly{LTkU64=Z1jeWox=W4pl1 z`?4>7Tpy?fo5sa;45|jo?yIMrfpPYz8vk>zy^O}iwYC|;OrhEQK^T4Tw&Zz15-$c| zb!cj*7c^}wcpUsqgpSU5zcXZ8`ivD1bDzC+v6jpjyTe&~@bH0lI(@znBlo0@z@HH8 z{xB}TAHPyatOMZT9~cbV*!35V3hT?ia8&;ppLhG^muhW(`=uT)fFy^|(VIgebjyBC zb0j&W-^``Q67QSw{Sa?j7qq9<`OuZni=V&05V!=3$Ld!dIN8^X{-Z(h`JvQjoX-Q+a-;|69m! z;+vF77LrR`Qx6V^Qba>~of8%b(y6d!=RU{KBNE2unmR^RcQOZm+S>L?AmmHZPe;YM z_Zd6a4xEvL={jjoWzU!lWscH8?-$S=ge<@y)rp?(e zDyYlbI>Opjf_Z#kml%_-&y^>ALfkdB@ekT40*_JgNPlomZRwuH-~Y3H7C*y-G`ZG} z`XH1jyO<=!e#mJK+ews!CZY;l-Tgk13XCyCiJY6X-!(WG4>yX%Fc2mwF$P3N$#Vq+ zJRj56Q8ehA(~pXj2kjkAOJ?5LD!J>e?twLFTt`H%Oc~hofu!dfFOi=AG!Vp^_{#z1y#5VhCD5D?<1NP%Rv5|oim`It zfVRyf6MXPC&{9@+Z(X-8^xQY+b+<(Vv|cB2xxab5O|0IIOvit4MD}D%ia!7H5GZ5X ziPe(>Vw)GKhlu`pIl_uZ?#lg}DKgiDJR$0OoZV`(U3u&w-&CT+e(o9QA^eD?Haw%# z1>3|4dNixRc)(PPG+kYfhZ8ufZy%XpocF3CIOeKr1kWN@%Zf?60zVjbjUA|k51q8h zWWJCwYhhum?~`=KB+x_@+XF~OEs!Ljw-tqIz~u51WuGC-PCeJQOI`Es2VZ{PF7vy$ zMTd`hYcOEia0Q1FjhYhZ4A#WYL7qqSxvCj}(ZOlPm3up6jH}2E?>n|Lv^7m^Bf?&8 zUNBRLGm_hJYBS4e;lBPLH2F<%=s`r2^gDEfQ2KfrjqNZxE*&8ubDcH;HT_Wy&-qW+ z&*EadxPQQIyx6%01)e$9(bi+m4jdsVqD4kH)dH(mffvOZG3FN0g6rA-ZV#dUpY0w( zjPc|}IWI`Z|8ZEK%QoKrmD*u_45oilJFKWOU``KY;HXA^vkR)sUVOgw!4j`AI_!;J z6`x}j(&|d5=1rNY?7;d9fAyEB75^^}mVWzp2-Pziu)PDvC~DO+8!(a~oec!H8nSIp z-Kxt)32v$`1&w1g1=D3Y!Aq56*e*}mLwE3V)WIwAIwap?(bFxCP@ zFb#ym6oRlCUr%l3hU_c{wQV!nTO!N_hFM#PTl1PL?44066b7lIO}WN?9yli!6J?4% zQftJ3ANWoa4eSU3Iw!E;c;K8^LA0n1CSB4K>LUB0VP~Z#frpUo)gg3@G`Rx~BrM)G z$5C8yN~rC=DdWe@Zri{0;^S5^A<7t)YgB1$ZryLZlMc(5m{77$bqE_P(ed1 zjG@~t&-HJgczK2^ZL>A)d2A(s33R={wr9|uSJI0vTb7r3w|wPM(NOIz)wPS$1gl;- zEP8pa!jbo!*1i7075Po#D{qo?Cy|aPyb^4~Ng&Pd+=T+Lf_xMSY_aHMV6SVFUe9^; zFX2@}*iU9~AI6Sx0Abu8Z-w#o|H4~|p1-J&VZ${9-h5#JHvL7;6uq-X2Aj%hAXB{ zt$M+$KEQQw1#cz#H0>k$2rU-iU<5qSCkyJ}#R7f^eP=tVEksS+xPL}8uU+zu#xc30 zvfjVn6W#g2=f?S&4r8wRwRNqK+a z$BY_Ts+V{xq-F@+$&h$)$mrEBdGT}si>9t8g?YmZJ+}RYA0s%`z$|gfuNW&={7;rh zy%us*W;@9A@SKlhyQTWI&GCQF)fz#VCpny;Trz2~nE)5adlTh~92vJ*zH9lRCqu8V%X96BGOdvD4wc?D{Nys9 ze^Y~m43b2Pj4-MNx)afqdSmRQBC3VjsfnrM%z3|`&m8hKardG1%UUPe9Ix_ysQ$&) z()r5Z#(_P)o@h~9le_J6w zY^D#dJ$ffr{CIWF_&W+umsthP=T%YP5#)UiI;Do;Dp`&Stb-QK+7PZV{ zmp*Kx7R#2mAJ4whw3bnu`oDHjR=-?Sfy{3g)q_o7+p_2OY?HzETK8+3BSF8hZ26ai z`nPQ|S~O)Y|Al^I#A*m&^=y+t&cv%FL+{sVr)n@GPw42ip<)*CdQVjaIZj9BXDluc zYSKEU^!>uW86aUS1dwUaSU~JA@B=w1%6Okb0Ji0kT3EkQ5BW_a98L0^oU)7_JObN> z?nn2zU^_l37$I&L!*_Y#sVS*L!!AuKh_-#J>!B1dL8D}n|LrK-1@_t98r=Oq>^$7vroBQ(;|`|+z2lZ_E~7#@sUUL->igW(3a#y1=3`6 z|9Fo*g6bQ3lcN@v2ex{`m0tl)Q!=($w%-){C-33Bx48V+16Qu~m09KI#vS-LMdb78 zgR884C;hPfx@kk2&i~STObQAP|K&cKjuH1E@Mo7Db}yDSpJvZi7VH?FeywvP5zd(A zh|e+4YE2K!H%OKo^w#TySL4ZvzSYs4J{6k|axCJ0Igoyf=ywv~2oMuYulVIau-F-f z0_B3E=b{kZ0*QHGPHmuhjHHwQGF`+lObaCFT8ix)r$$=#ZJz(m{2a+;jDYaOZ6n4x zY2Cbj=y9mjoe`~{>hI3{JWvY~$PrF@H&p{Y%Hb@XE7(SHs>c5u=y9f?*Yy)r4fLdl zi$sk;y+3<>e>aMNMK0uBN-41Hofxl;e)TtfBZ zl74S8!J<&u{Rer$YWe-9-#4h(xeP>JCjD|Pxr~2BUeLSa9DDHMB(BGfycOxg0i{`k+b~EnBWV?X!T@}b;ZNLL zV?JHYv6D#1ZJ0z048kE=(2A=%cmL0Jb#8__UDB@+e_EoBA82C643;B=bZl2KoeXxh z35VZH$Sv72A~8$i^_xjAD_s^9#ePwFuTnmH!`Hm01DEs#r2F$advjN;m2zv**cI_V>sLVd>Eg>^&i)YtwztH=Grmn#>b=^Z! z*W{-x%)dZ!Pl6Dp7=U@bD8;`Zq7T@MwuE%d^(bCZ_Ty6mnY;@aZ?32)o7x zT>f|~jGonRM*sizR%3s8tDIZ^>aA{Jmo^?I*R~r7AIEb0er==P3R`FY!CN^Jt0?+H zS1^p)43}x-fo+MRlh#2zJ?HuKN${+rJ?!%Q(g@8BciWs3ZyjIx!%R9YFYn}liNcU2 zTAYxfT3}p%h@@Izj7X}5)UY=tb5(ksb4?a8{4o0?#`WFjA-9y4xi+Q8rEooDlR_xo(0&CeJ|y>ly>ay`5YtVReT zEK=FWcAe42r5N0vqvFH*AZx5D)iJB&)=XK!ceewEroag$?eMQgFE`!#`MbSg5-YcF;ZKk^9N5L1h!%}` zq>KN!Ao0s=iQlCvjHC!*e_RlDn^nJQ`v2Pn>HKy_LM+jGQ_}Li^S67O*Ud-?S{bi7Ebl0*rYc#V{SPjP?E4^T#}8^0=vh~bNTiP4 z!$aw|2THfhYtP~A(9>Rf&@+2FYwO{OMs;$VhySRY>s8p5lrzvK7SgOEuV+IphOEF^ znlE60A7$$4iH?vORXzRM#^mdhHjnxIO>OSbZHqk)z4jMe`MRt7Gw(n(tchtB^c+-# zv8drC%_y)#^63N_B(kp<8lN!)Ls)H+96p6AjY^}dQtMY0bF)7S&$u{n2R*}xXpt*N zM+8gp-~{apY)zwDU<=g1zHlO1T+g6dU|W45mG%XO$rCNady|vy#RC05fr|wglWCKg z^ko=+2h-@wu$u<|tvTdRk}7JDm*iak7sunM+EAC=10oX`2!nQ@;13Lh-80c|a{iO! z$t~FPV2eP0-tzmF560eMX9{F7#S>H8Z(6Yj?J#B?S@Cz7+JHJ2fq}w)xt^xP-!M?m z;)B6!U{9i-9v}$w1^wFRD8fu=Ts|$(aIkGb*YuqSOK&~CC>JY#JG9jzX=S(j#OYp+ zGQXTpzqt6j2$Qjhj7Y%{I_%g|1Ix&Q#KD->M5{nz>?IF2L|>8C*UOx>YnkdPapt|H zjHTzV-sGvd>b58?-RbVXSqDJ~Hxfk}o>N7zE%tDq+8=iH9-VS`SGnx58QEAPe~Rzv zMShu^K@YBIoSND8?wX(E98urzK?AigptFGDls(BScJ|#zCP`k&wgYTC22B*u>E93H zCrJZgBQB?jLJ&<}kt>WqL18vOIm82_NF|4>a|hJ%D;2Z1NNbcPj4#}*bZE(-)Hz*~ zCDR5O777>UH@^uSn6RuNdvSJ<;7NrcsI2LnqqDpTFHsON$Se8#~Ytn7y$zodsC@2?Er*v4ag@Bb7prH)-rU@Dn?I zEO4X93%mU zat=vF0Xss0yYC!y?4TO({<~XGM*ZcjCwu7VqPz8<^&SR{?s3oSyKMp6dj95b?>)Io zT3d&2?3Vt^drwBv)?x%(XzugW*v93mzN6I9J;b#=_f%O2VS8~qLCy39dh^LA!Jfm> zF%$)-tzaQ0xKiJaZnc}htw1*wMSF_TBjeFMKR*REQZ{1OpX|BVg>RI(&y+ZY?{v}a8!l`wN@(BmgKi6% z$W}Kk#4kWmX0Wxu7T@JCmKq%vVS^l%LU#$gq!SUVg~FA;yaFY!Z|G6_yOEg?9eR|A zo*N@iH<)r*UeuHk}M8wfP8j{#aE8%;^|lG;7eJZ$wGIBl;E+>=G0Q zG6q5uc{wPLwX5&2eUw&ucjI;Rq!~CzubsePA4sN6#mXs=LX8roGLE4`fHDn-&^KZL zA*|`^T#Q*azi-N;Jhxz7C;YOL+0c6d1V%F3%p?~;U?ecnjh;Az>j|Ux)-jCs2p;?7 zIVcmVoZRbWaEXHz^TD1*a%38#b1#1^`FT7 zMrVKBZ*;rjsaZO2Z-R-|*{}8zaf|=r5)@04PH7}iN$e(+W%R}$8V+JmI2>m(L^beg zYZ*zaQ4_b7IOv@g$NHV{1HSeFwEcb+@*cvuDl#jIp zUBma22LMyNS(YKnwG{Y=5b#NjT-XJ?B8*nqNE!Jd0zFr64;lGc`-lRApUZVO{Nw|r zLyOYo$X_0VL`9Wud1Z(*_}LzEqN1lew~}kh8ER|~>|P5{Bl)r0$lcqah>tOd?V)2Y zY9#V#FXZ!q6=Ry{V1a}bc*q{iupmD_X24;#2M6244^b>|7ia9xh9A6O$yh3CC~&Y4 zGTDY4tl|uTz%~@Pa}CnjWB+DPD0{3xR|S-^>$tX+i>?>ATm$FX5sZCA)t^mph+W4x zCOTLowGA%vDjVSo(luavh%|nLM?{+IM!2XES78@q3XmSHAx~@zV|KGQF}{+YZ?`i) z!9-qfEn!hHmDat?20_y8-esbLm2Mto*2yvW*gm47BAKPkG9K`4cN$H`(u91S$k&T} zgUL6Je6NsiHTk|I-%j$?An@Td@?Ar|$>e*Ee6NykHTm)q^N=N9P4d+z-v#9BO1{)i g;FOeh^|x{+Kj#MXDZK^dzx}iB4BDo$-lX>b0g8FWg#Z8m diff --git a/example/blockchain/000107.ldb b/example/blockchain/000107.ldb deleted file mode 100644 index 8f041675bcc7735ec2e5271065a83cc7c1014689..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 935 zcmbO$@gbB!lR1fX-Q#(u_FnRif4HUp*#R%d!^>@j^9+3a&-gu_@;XJgkMTV-0|*>C zaDY*RIU(Or&cN_uP>Hx2_s#mWJ%>{z{#u*zWNcH3O4gWVQqK5-nSoKC;Sj4{N4rk{ za{npCD_i6ve3sqXkYu1@sBc)FQ=k5B?T)2l|K~G4WMJ?- zoH`5%RmZ`+9>&j{I(3SSAemmqUqJR@1|9}Y#+14M1{TIIoIX5^j2et}D}bE0k~(z^ zj4X`LfHa8zn^#AGLGuZ7M$;w+h7X*2JU>1w|_m0O_t!~|#zU|Bv zsmnsH(o?!hgg-2F`s;9IvU|eYW>D&v~?$6peSm{ zFnK}P3wd$rGoj1=H@iNYbl^u`w8sPKnK^3@Fed45eVn{S5uqSTk%46=qpQ(BMg|Ca z$H-vO(Ad))z`)SZlHB_6Lc@YOZbpU_t%l2Jru<`iHm#%AHi>^nu1IYFjVCVu`a}H=tQyd$^cc6P?*g)nmYAt#awp2cM z&T(Lx`RaDjXNHYl=!%-6%@%^poeF!(FwN-&nsafL0Fw#>uR?xCVsQrJ56v%iGE6*d z>>Qtrgct;RfQ;85 zMmLc01jOh9CYPeRX0mD7abK;L^#hIf)WO{WI|AG8Z%c=Va7iIKc*&TD4wW{VW^T9X2tL5PlH;yP;d9 H)crO9s!%|T diff --git a/example/blockchain/000110.ldb b/example/blockchain/000110.ldb deleted file mode 100644 index 9414ccb2555f5759fecdf1a9cb48545a4b83eb7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1766 zcma)-3rtg29LCSTy`{aSEti+P1X`%rLR%D=kf{?;UI7f-bc%|TmsF9$bRvS@)C$Uc z0Hrw53@lEJgP{`v1?Pq=lTFzJMck$kRL0OPN>soh;LhzfH8HNcIXCBbPQLTy-sHRA zJuDttjO6Sj2fg#zgr&o)GIu|0w0m-QSfe|$`od1%VB4TVH%@Vu0R#kMuC~@zkg+R1 zn7_8S*3Uy8eKGOJ_?{6?jy4lX7nRpdmx$M=d~*?G1Oi{w#!(g4FB08JtM~U_BOJ_G za-EmsJ(zE7>kPLPXhT1W9*NR`EdffQs<2BM`T))%c%%~>I)ft-_BeKH3*wZ}UkB{egJiFuhH5LJEp@Ks4ezsZ{2uMh(1b@O!BVCV%GK{Vrv4g$s3Awce zjcH9CUCvi*!d%LBy>B~I6*>{zWr)xkPbGbpkybNG>n9g|pFh9IAwZO{<8W0!C-iI| zd5*MK8s8aocW~)geDvw|uz}Ln$C~AleJ%&q)wM#BZ{zLc2FY{5G6^D@A$9g7pufjG zKtbAVCEMc=(&i@@+;Z0%X-hzb))M?q{X5Dzgq+~`hEVi9)-H;rt*%rZS`jw#d;QuJ z>ai}f%9uWGKYFEsJ99&ArRq(eS;k3<_2P)4P}yP%dA3k2-6VnR;wd_Yz(!k!ZwUFa zocFfvYkcdPM80)x|AU6Wf`S;Or{1ZunRxWwizb+3DWu0fV(dddViVwjjhZYNBmeA= zrAKD?y( z*-NBCai%(PgBrXEj%|s#-m>6|JqeC?iMcYux~YuLT+v{iJ)<*Mf>$r^0 zTn%C!!aAKJTPosdHfAKHt_L5vQV3KTkIR$#*&xb*!Ignh3{x1;W3XbN1OtzOVhq4Q z5iY9r^aO4p8!`a3f|96Cm5CKFw?)9A5``n;v(?w&DG82fn2ShagSFM1G46!v&qHCE>EyYPG1j<% Vzgy_Voc`}?$rJ5v>Bflbe*tUYRy6 L1·0 S·3KiB Q·107 -07:44:40.894836 table@build created L1@16 N·75 S·3KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xdd;..\x87Dw,v19" -07:44:40.894908 version@stat F·[0 1] S·3KiB[0B 3KiB] Sc·[0.00 0.00] -07:44:40.897612 table@compaction committed F-3 S-318B Ke·0 D·28 T·6.361942ms -07:44:40.897743 table@remove removed @10 -07:44:40.897809 table@remove removed @5 -07:44:40.897868 table@remove removed @2 -07:44:46.230801 db@close closing -07:44:46.230990 db@close done T·179.078µs -=============== Nov 29, 2022 (CET) =============== -07:45:07.132700 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:45:07.132848 version@stat F·[0 1] S·3KiB[0B 3KiB] Sc·[0.00 0.00] -07:45:07.132882 db@open opening -07:45:07.132963 journal@recovery F·1 -07:45:07.134880 journal@recovery recovering @14 -07:45:07.138258 memdb@flush created L0@17 N·35 S·1KiB "b1K..\x1f\xd6q,v115":"r\xd1\xc2..H#h,v142" -07:45:07.138574 version@stat F·[1 1] S·4KiB[1KiB 3KiB] Sc·[0.25 0.00] -07:45:07.150201 db@janitor F·5 G·1 -07:45:07.150219 db@janitor removing table-13 -07:45:07.150272 db@open done T·17.379812ms -=============== Nov 29, 2022 (CET) =============== -07:45:22.714330 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:45:22.714469 version@stat F·[1 1] S·4KiB[1KiB 3KiB] Sc·[0.25 0.00] -07:45:22.714495 db@open opening -07:45:22.714562 journal@recovery F·1 -07:45:22.716495 journal@recovery recovering @18 -07:45:22.716939 version@stat F·[1 1] S·4KiB[1KiB 3KiB] Sc·[0.25 0.00] -07:45:22.729254 db@janitor F·4 G·0 -07:45:22.729300 db@open done T·14.787096ms -07:45:27.631654 db@close closing -07:45:27.631778 db@close done T·122.12µs -=============== Nov 29, 2022 (CET) =============== -07:47:50.195416 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:47:50.195551 version@stat F·[1 1] S·4KiB[1KiB 3KiB] Sc·[0.25 0.00] -07:47:50.195571 db@open opening -07:47:50.195625 journal@recovery F·1 -07:47:50.195761 journal@recovery recovering @20 -07:47:50.198242 memdb@flush created L0@22 N·28 S·942B "b\x06\xb5..\xf2҄,v151":"r\x87c..9?k,v164" -07:47:50.199098 version@stat F·[2 1] S·5KiB[2KiB 3KiB] Sc·[0.50 0.00] -07:47:50.212673 db@janitor F·5 G·0 -07:47:50.212730 db@open done T·17.148314ms -07:47:54.508347 db@close closing -07:47:54.508555 db@close done T·197.943µs -=============== Nov 29, 2022 (CET) =============== -07:58:29.865734 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:58:29.865902 version@stat F·[2 1] S·5KiB[2KiB 3KiB] Sc·[0.50 0.00] -07:58:29.865925 db@open opening -07:58:29.865998 journal@recovery F·1 -07:58:29.866162 journal@recovery recovering @23 -07:58:29.869386 memdb@flush created L0@25 N·28 S·938B "b4\xdd..\xa8\xfa[,v187":"r\xced..9ܕ,v200" -07:58:29.870371 version@stat F·[3 1] S·6KiB[2KiB 3KiB] Sc·[0.75 0.00] -07:58:29.882379 db@janitor F·6 G·0 -07:58:29.882415 db@open done T·16.477753ms -07:58:34.095856 db@close closing -07:58:34.096035 db@close done T·166.305µs -=============== Nov 29, 2022 (CET) =============== -07:59:00.168427 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:59:00.168581 version@stat F·[3 1] S·6KiB[2KiB 3KiB] Sc·[0.75 0.00] -07:59:00.168611 db@open opening -07:59:00.168689 journal@recovery F·1 -07:59:00.170441 journal@recovery recovering @26 -07:59:00.175443 memdb@flush created L0@28 N·28 S·941B "b6r..\xd5\xf1G,v209":"r\xa5\xd6..\x9d\x15\x87,v222" -07:59:00.176340 version@stat F·[4 1] S·7KiB[3KiB 3KiB] Sc·[1.00 0.00] -07:59:00.189416 db@janitor F·7 G·0 -07:59:00.189462 db@open done T·20.838718ms -07:59:00.189544 table@compaction L0·4 -> L1·1 S·7KiB Q·230 -07:59:00.193367 table@build created L1@31 N·160 S·7KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xdd;..\x87Dw,v19" -07:59:00.193437 version@stat F·[0 1] S·7KiB[0B 7KiB] Sc·[0.00 0.00] -07:59:00.196163 table@compaction committed F-4 S+638B Ke·0 D·34 T·6.585113ms -07:59:00.196303 table@remove removed @25 -07:59:00.196360 table@remove removed @22 -07:59:00.196413 table@remove removed @17 -07:59:00.196466 table@remove removed @16 -07:59:06.057455 db@close closing -07:59:06.057605 db@close done T·145.115µs -=============== Nov 29, 2022 (CET) =============== -08:32:21.921182 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:32:21.921422 version@stat F·[0 1] S·7KiB[0B 7KiB] Sc·[0.00 0.00] -08:32:21.921459 db@open opening -08:32:21.921554 journal@recovery F·1 -08:32:21.921764 journal@recovery recovering @29 -08:32:21.924936 memdb@flush created L0@32 N·35 S·1KiB "b\n\x1f..\xda6H,v259":"rP\xf4..I7u,v244" -08:32:21.925138 version@stat F·[1 1] S·8KiB[1KiB 7KiB] Sc·[0.25 0.00] -08:32:21.936959 db@janitor F·5 G·1 -08:32:21.936982 db@janitor removing table-28 -08:32:21.937051 db@open done T·15.577369ms -08:32:25.249429 db@close closing -08:32:25.249611 db@close done T·182.906µs -=============== Nov 29, 2022 (CET) =============== -08:33:22.413828 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:33:22.413979 version@stat F·[1 1] S·8KiB[1KiB 7KiB] Sc·[0.25 0.00] -08:33:22.414005 db@open opening -08:33:22.414069 journal@recovery F·1 -08:33:22.415690 journal@recovery recovering @33 -08:33:22.418834 memdb@flush created L0@35 N·21 S·715B "b\x80\xdb..Wa\xf0,v281":"r\xa3\xe2..\x1b\x8c\x18,v273" -08:33:22.419091 version@stat F·[2 1] S·9KiB[1KiB 7KiB] Sc·[0.50 0.00] -08:33:22.431309 db@janitor F·5 G·0 -08:33:22.431343 db@open done T·17.326534ms -08:33:32.547907 db@close closing -08:33:32.548105 db@close done T·189.939µs -=============== Nov 29, 2022 (CET) =============== -08:33:58.629600 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:33:58.629730 version@stat F·[2 1] S·9KiB[1KiB 7KiB] Sc·[0.50 0.00] -08:33:58.629750 db@open opening -08:33:58.629811 journal@recovery F·1 -08:33:58.629965 journal@recovery recovering @36 -08:33:58.633112 memdb@flush created L0@38 N·70 S·2KiB "b\f\xcd..\x1axP,v338":"r\xf7C..`\xf2\r,v323" -08:33:58.633353 version@stat F·[3 1] S·11KiB[3KiB 7KiB] Sc·[0.75 0.00] -08:33:58.644620 db@janitor F·6 G·0 -08:33:58.644647 db@open done T·14.887263ms -08:34:05.061197 db@close closing -08:34:05.061379 db@close done T·179.951µs -=============== Nov 29, 2022 (CET) =============== -08:34:23.230635 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:34:23.230880 version@stat F·[3 1] S·11KiB[3KiB 7KiB] Sc·[0.75 0.00] -08:34:23.230919 db@open opening -08:34:23.231031 journal@recovery F·1 -08:34:23.232932 journal@recovery recovering @39 -08:34:23.236435 memdb@flush created L0@41 N·42 S·1KiB "b\"_..{\xbc\x9f,v374":"r\xda\xc2..\x9d\xcc{,v394" -08:34:23.236705 version@stat F·[4 1] S·12KiB[5KiB 7KiB] Sc·[1.00 0.00] -08:34:23.249129 db@janitor F·7 G·0 -08:34:23.249173 db@open done T·18.236734ms -08:34:23.249233 table@compaction L0·4 -> L1·1 S·12KiB Q·402 -08:34:23.252938 table@build created L1@44 N·280 S·15KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xf7C..`\xf2\r,v323" -08:34:23.253013 version@stat F·[0 1] S·15KiB[0B 15KiB] Sc·[0.00 0.00] -08:34:23.255717 table@compaction committed F-4 S+2KiB Ke·0 D·48 T·6.455994ms -08:34:23.255853 table@remove removed @38 -08:34:23.255919 table@remove removed @35 -08:34:23.255975 table@remove removed @32 -08:34:23.256028 table@remove removed @31 -08:34:27.565320 db@close closing -08:34:27.565551 db@close done T·224.865µs -=============== Nov 29, 2022 (CET) =============== -08:34:43.148588 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:34:43.148764 version@stat F·[0 1] S·15KiB[0B 15KiB] Sc·[0.00 0.00] -08:34:43.148792 db@open opening -08:34:43.148866 journal@recovery F·1 -08:34:43.150802 journal@recovery recovering @42 -08:34:43.154093 memdb@flush created L0@45 N·28 S·841B "b3\x9a..8Ռ,v424":"r\xf6\xbe..\xc4\xdd\x13,v423" -08:34:43.154389 version@stat F·[1 1] S·15KiB[841B 15KiB] Sc·[0.25 0.00] -08:34:43.166735 db@janitor F·5 G·1 -08:34:43.166826 db@janitor removing table-41 -08:34:43.167006 db@open done T·18.196688ms -08:34:57.710814 db@close closing -08:34:57.711005 db@close done T·189.017µs -=============== Nov 29, 2022 (CET) =============== -08:35:00.573886 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:35:00.574055 version@stat F·[1 1] S·15KiB[841B 15KiB] Sc·[0.25 0.00] -08:35:00.574078 db@open opening -08:35:00.574152 journal@recovery F·1 -08:35:00.574305 journal@recovery recovering @46 -08:35:00.577496 memdb@flush created L0@48 N·98 S·3KiB "b\x03\x02..NU\x1e,v481":"r\xfd@..mn~,v473" -08:35:00.578480 version@stat F·[2 1] S·19KiB[4KiB 15KiB] Sc·[0.50 0.00] -08:35:00.590290 db@janitor F·5 G·0 -08:35:00.590328 db@open done T·16.238516ms -08:35:04.919068 db@close closing -08:35:04.919268 db@close done T·193.896µs -=============== Nov 29, 2022 (CET) =============== -08:48:48.753017 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:48:48.753236 version@stat F·[2 1] S·19KiB[4KiB 15KiB] Sc·[0.50 0.00] -08:48:48.753275 db@open opening -08:48:48.753391 journal@recovery F·1 -08:48:48.753604 journal@recovery recovering @49 -08:48:48.760290 memdb@flush created L0@51 N·28 S·935B "b\x151..\x0eZ\x95,v538":"r\x8b\xc8..\xa9Oa,v551" -08:48:48.760860 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:48:48.772603 db@janitor F·6 G·0 -08:48:48.772633 db@open done T·19.344141ms -=============== Nov 29, 2022 (CET) =============== -08:49:09.996093 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:49:09.996267 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:49:09.996294 db@open opening -08:49:09.996370 journal@recovery F·1 -08:49:09.999213 journal@recovery recovering @52 -08:49:10.001170 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:49:10.013078 db@janitor F·6 G·0 -08:49:10.013125 db@open done T·16.816337ms -=============== Nov 29, 2022 (CET) =============== -08:49:41.632675 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:49:41.632917 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:49:41.632956 db@open opening -08:49:41.633061 journal@recovery F·1 -08:49:41.633296 journal@recovery recovering @54 -08:49:41.633995 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:49:41.645625 db@janitor F·6 G·0 -08:49:41.645661 db@open done T·12.691685ms -=============== Nov 29, 2022 (CET) =============== -08:50:15.131176 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:50:15.131371 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:50:15.131405 db@open opening -08:50:15.131516 journal@recovery F·1 -08:50:15.133436 journal@recovery recovering @56 -08:50:15.133867 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:50:15.146041 db@janitor F·6 G·0 -08:50:15.146067 db@open done T·14.650479ms -=============== Nov 29, 2022 (CET) =============== -08:51:00.753198 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:51:00.753444 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:51:00.753482 db@open opening -08:51:00.753581 journal@recovery F·1 -08:51:00.755534 journal@recovery recovering @58 -08:51:00.756021 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:51:00.768622 db@janitor F·6 G·0 -08:51:00.768668 db@open done T·15.172194ms -=============== Nov 29, 2022 (CET) =============== -08:55:34.186825 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:55:34.186969 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:55:34.186993 db@open opening -08:55:34.187065 journal@recovery F·1 -08:55:34.188499 journal@recovery recovering @60 -08:55:34.188853 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -08:55:34.200271 db@janitor F·6 G·0 -08:55:34.200319 db@open done T·13.315296ms -08:55:40.541081 db@close closing -08:55:40.541198 db@close done T·115.097µs -=============== Nov 29, 2022 (CET) =============== -09:00:23.232522 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -09:00:23.232738 version@stat F·[3 1] S·20KiB[5KiB 15KiB] Sc·[0.75 0.00] -09:00:23.232775 db@open opening -09:00:23.232881 journal@recovery F·1 -09:00:23.233121 journal@recovery recovering @62 -09:00:23.239506 memdb@flush created L0@64 N·42 S·1KiB "b\fw..F\rH,v560":"r\xe1\b..φ\x81,v601" -09:00:23.239888 version@stat F·[4 1] S·21KiB[6KiB 15KiB] Sc·[1.00 0.00] -09:00:23.258743 db@janitor F·7 G·0 -09:00:23.258777 db@open done T·25.986546ms -09:00:23.258858 table@compaction L0·4 -> L1·1 S·21KiB Q·602 -09:00:23.263767 table@build created L1@67 N·420 S·25KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xfd@..mn~,v473" -09:00:23.263835 version@stat F·[0 1] S·25KiB[0B 25KiB] Sc·[0.00 0.00] -09:00:23.266631 table@compaction committed F-4 S+3KiB Ke·0 D·56 T·7.729411ms -09:00:23.266745 table@remove removed @51 -09:00:23.266791 table@remove removed @48 -09:00:23.266848 table@remove removed @45 -09:00:23.266916 table@remove removed @44 -09:00:29.773577 db@close closing -09:00:29.773708 db@close done T·129.384µs -=============== Nov 29, 2022 (CET) =============== -09:16:50.070492 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -09:16:50.070634 version@stat F·[0 1] S·25KiB[0B 25KiB] Sc·[0.00 0.00] -09:16:50.070652 db@open opening -09:16:50.070705 journal@recovery F·1 -09:16:50.070841 journal@recovery recovering @65 -09:16:50.075175 memdb@flush created L0@68 N·42 S·1KiB "b&\xed..\xa6\"\xdf,v638":"r\xfa1..\x1d\xdbV,v609" -09:16:50.077279 version@stat F·[1 1] S·26KiB[1KiB 25KiB] Sc·[0.25 0.00] -09:16:50.088902 db@janitor F·5 G·1 -09:16:50.088931 db@janitor removing table-64 -09:16:50.088985 db@open done T·18.324666ms -09:16:55.700304 db@close closing -09:16:55.700473 db@close done T·166.625µs -=============== Nov 29, 2022 (CET) =============== -09:49:45.778230 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -09:49:45.778380 version@stat F·[1 1] S·26KiB[1KiB 25KiB] Sc·[0.25 0.00] -09:49:45.778406 db@open opening -09:49:45.778473 journal@recovery F·1 -09:49:45.780071 journal@recovery recovering @69 -09:49:45.783199 memdb@flush created L0@71 N·35 S·1KiB "b\r}..\x89˟,v653":"r\xccd..\xf8\xa1\xcc,v680" -09:49:45.783427 version@stat F·[2 1] S·27KiB[2KiB 25KiB] Sc·[0.50 0.00] -09:49:45.794888 db@janitor F·5 G·0 -09:49:45.794922 db@open done T·16.503924ms -09:49:51.233600 db@close closing -09:49:51.233757 db@close done T·154.973µs -=============== Nov 29, 2022 (CET) =============== -11:13:42.269914 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:13:42.270349 version@stat F·[2 1] S·27KiB[2KiB 25KiB] Sc·[0.50 0.00] -11:13:42.270393 db@open opening -11:13:42.270490 journal@recovery F·1 -11:13:42.276857 journal@recovery recovering @72 -11:13:42.280289 memdb@flush created L0@74 N·35 S·969B "b\xae\x1f..\xb5ġ,v689":"r\xf3\xe6..y\xaf?,v688" -11:13:42.282579 version@stat F·[3 1] S·28KiB[3KiB 25KiB] Sc·[0.75 0.00] -11:13:42.294299 db@janitor F·6 G·0 -11:13:42.294327 db@open done T·23.920764ms -11:13:47.686648 db@close closing -11:13:47.686807 db@close done T·153.982µs -=============== Nov 29, 2022 (CET) =============== -11:14:23.708457 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:14:23.708700 version@stat F·[3 1] S·28KiB[3KiB 25KiB] Sc·[0.75 0.00] -11:14:23.708737 db@open opening -11:14:23.708841 journal@recovery F·1 -11:14:23.709060 journal@recovery recovering @75 -11:14:23.714721 memdb@flush created L0@77 N·35 S·970B "bN\xc9..>F\x92,v732":"rw\xe9..\xf3\f\x03,v745" -11:14:23.715043 version@stat F·[4 1] S·29KiB[4KiB 25KiB] Sc·[1.00 0.00] -11:14:23.728772 db@janitor F·7 G·0 -11:14:23.728822 db@open done T·20.069401ms -11:14:23.728884 table@compaction L0·4 -> L1·1 S·29KiB Q·753 -11:14:23.735044 table@build created L1@80 N·525 S·31KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xfd@..mn~,v473" -11:14:23.735133 version@stat F·[0 1] S·31KiB[0B 31KiB] Sc·[0.00 0.00] -11:14:23.737955 table@compaction committed F-4 S+1KiB Ke·0 D·42 T·9.032055ms -11:14:23.738119 table@remove removed @74 -11:14:23.738186 table@remove removed @71 -11:14:23.738242 table@remove removed @68 -11:14:23.738308 table@remove removed @67 -11:14:27.464043 db@close closing -11:14:27.464269 db@close done T·212.523µs -=============== Nov 29, 2022 (CET) =============== -11:14:35.688207 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:14:35.688457 version@stat F·[0 1] S·31KiB[0B 31KiB] Sc·[0.00 0.00] -11:14:35.688502 db@open opening -11:14:35.688622 journal@recovery F·1 -11:14:35.688899 journal@recovery recovering @78 -11:14:35.692321 memdb@flush created L0@81 N·21 S·722B "b9\xd6..\xb6^^,v768":"r\xfd\\..g\xe4c,v760" -11:14:35.693031 version@stat F·[1 1] S·31KiB[722B 31KiB] Sc·[0.25 0.00] -11:14:35.704631 db@janitor F·5 G·1 -11:14:35.704652 db@janitor removing table-77 -11:14:35.704703 db@open done T·16.184328ms -11:14:42.384623 db@close closing -11:14:42.384771 db@close done T·144.254µs -=============== Nov 29, 2022 (CET) =============== -11:14:54.469611 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:14:54.469818 version@stat F·[1 1] S·31KiB[722B 31KiB] Sc·[0.25 0.00] -11:14:54.469853 db@open opening -11:14:54.469949 journal@recovery F·1 -11:14:54.470176 journal@recovery recovering @82 -11:14:54.473554 memdb@flush created L0@84 N·42 S·1KiB "b6[..\xb6\x9f\x1d,v776":"r\xfd\xdf..^En,v803" -11:14:54.474587 version@stat F·[2 1] S·33KiB[2KiB 31KiB] Sc·[0.50 0.00] -11:14:54.486408 db@janitor F·5 G·0 -11:14:54.486453 db@open done T·16.586048ms -11:15:00.256970 db@close closing -11:15:00.257105 db@close done T·126.6µs -=============== Nov 29, 2022 (CET) =============== -11:33:07.397127 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:33:07.397388 version@stat F·[2 1] S·33KiB[2KiB 31KiB] Sc·[0.50 0.00] -11:33:07.397443 db@open opening -11:33:07.397588 journal@recovery F·1 -11:33:07.397842 journal@recovery recovering @85 -11:33:07.401262 memdb@flush created L0@87 N·35 S·1KiB "b6\x9e..\xdd\xc39,v833":"rʅ..X>\xf1,v853" -11:33:07.402433 version@stat F·[3 1] S·34KiB[3KiB 31KiB] Sc·[0.75 0.00] -11:33:07.414163 db@janitor F·6 G·0 -11:33:07.414200 db@open done T·16.734306ms -11:33:11.229931 db@close closing -11:33:11.230090 db@close done T·155.734µs -=============== Nov 29, 2022 (CET) =============== -11:36:41.243838 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:36:41.244052 version@stat F·[3 1] S·34KiB[3KiB 31KiB] Sc·[0.75 0.00] -11:36:41.244088 db@open opening -11:36:41.244203 journal@recovery F·1 -11:36:41.244432 journal@recovery recovering @88 -11:36:41.250160 memdb@flush created L0@90 N·21 S·783B "bW\xaa..\xdc\xc6\xca,v862":"r\xfb\xe0..\xea\x98\xf7,v875" -11:36:41.250506 version@stat F·[4 1] S·35KiB[4KiB 31KiB] Sc·[1.00 0.00] -11:36:41.265206 db@janitor F·7 G·0 -11:36:41.265254 db@open done T·21.151145ms -11:36:41.265298 table@compaction L0·4 -> L1·1 S·35KiB Q·876 -11:36:41.270981 table@build created L1@93 N·610 S·36KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xfd\xdf..^En,v803" -11:36:41.271038 version@stat F·[0 1] S·36KiB[0B 36KiB] Sc·[0.00 0.00] -11:36:41.273693 table@compaction committed F-4 S+1KiB Ke·0 D·34 T·8.358963ms -11:36:41.273807 table@remove removed @87 -11:36:41.273851 table@remove removed @84 -11:36:41.273891 table@remove removed @81 -11:36:41.273937 table@remove removed @80 -11:36:48.973721 db@close closing -11:36:48.973958 db@close done T·231.689µs -=============== Nov 29, 2022 (CET) =============== -11:40:21.464610 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:40:21.464775 version@stat F·[0 1] S·36KiB[0B 36KiB] Sc·[0.00 0.00] -11:40:21.464800 db@open opening -11:40:21.464868 journal@recovery F·1 -11:40:21.465026 journal@recovery recovering @91 -11:40:21.468182 memdb@flush created L0@94 N·49 S·1KiB "b)S..]$I,v898":"r\xd8\xf6..\x889\xd5,v883" -11:40:21.468837 version@stat F·[1 1] S·37KiB[1KiB 36KiB] Sc·[0.25 0.00] -11:40:21.480440 db@janitor F·5 G·1 -11:40:21.480465 db@janitor removing table-90 -11:40:21.480535 db@open done T·15.725154ms -11:40:26.940207 db@close closing -11:40:26.940344 db@close done T·134.875µs -=============== Nov 29, 2022 (CET) =============== -11:40:37.994469 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:40:37.994607 version@stat F·[1 1] S·37KiB[1KiB 36KiB] Sc·[0.25 0.00] -11:40:37.994631 db@open opening -11:40:37.994690 journal@recovery F·1 -11:40:37.996408 journal@recovery recovering @95 -11:40:37.999645 memdb@flush created L0@97 N·35 S·1KiB "bY\xae..\xf8\xac\x80,v941":"r\xf9\x12..i`\xfe,v961" -11:40:37.999919 version@stat F·[2 1] S·39KiB[2KiB 36KiB] Sc·[0.50 0.00] -11:40:38.011149 db@janitor F·5 G·0 -11:40:38.011179 db@open done T·16.53782ms -11:40:40.724628 db@close closing -11:40:40.725031 db@close done T·395.979µs -=============== Nov 29, 2022 (CET) =============== -11:40:58.995205 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:40:58.995419 version@stat F·[2 1] S·39KiB[2KiB 36KiB] Sc·[0.50 0.00] -11:40:58.995455 db@open opening -11:40:58.995575 journal@recovery F·1 -11:40:58.995802 journal@recovery recovering @98 -11:40:58.999127 memdb@flush created L0@100 N·14 S·621B "b\x8d\x81..<)4,v970":"r\xa8\x02.. \x13\x94,v969" -11:40:59.002275 version@stat F·[3 1] S·39KiB[3KiB 36KiB] Sc·[0.75 0.00] -11:40:59.013689 db@janitor F·6 G·0 -11:40:59.013718 db@open done T·18.250579ms -11:41:01.461842 db@close closing -11:41:01.462008 db@close done T·163.238µs -=============== Nov 29, 2022 (CET) =============== -11:41:17.816270 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:41:17.816441 version@stat F·[3 1] S·39KiB[3KiB 36KiB] Sc·[0.75 0.00] -11:41:17.816465 db@open opening -11:41:17.816550 journal@recovery F·1 -11:41:17.816850 journal@recovery recovering @101 -11:41:17.819872 memdb@flush created L0@103 N·14 S·637B "b\x17\xb5..\xda\xc3r,v978":"r,\x11..:{\xa1,v991" -11:41:17.820824 version@stat F·[4 1] S·40KiB[4KiB 36KiB] Sc·[1.00 0.00] -11:41:17.836802 db@janitor F·7 G·0 -11:41:17.836848 db@open done T·20.371822ms -11:41:17.836943 table@compaction L0·4 -> L1·1 S·40KiB Q·992 -11:41:17.842303 table@build created L1@106 N·690 S·41KiB "b\x00\xaa..\xdf\x1b\x9a,v56":"r\xfd\xdf..^En,v803" -11:41:17.842369 version@stat F·[0 1] S·41KiB[0B 41KiB] Sc·[0.00 0.00] -11:41:17.845108 table@compaction committed F-4 S+1KiB Ke·0 D·32 T·8.128852ms -11:41:17.845238 table@remove removed @100 -11:41:17.845298 table@remove removed @97 -11:41:17.845353 table@remove removed @94 -11:41:17.845418 table@remove removed @93 -11:41:22.549878 db@close closing -11:41:22.550053 db@close done T·173.237µs -=============== Nov 29, 2022 (CET) =============== -11:42:36.829762 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:42:36.829956 version@stat F·[0 1] S·41KiB[0B 41KiB] Sc·[0.00 0.00] -11:42:36.829994 db@open opening -11:42:36.830083 journal@recovery F·1 -11:42:36.830298 journal@recovery recovering @104 -11:42:36.833414 memdb@flush created L0@107 N·28 S·935B "b\x05\xae..d-\x8e,v1007":"r\xb4\x94..\x83\xe5S,v1020" -11:42:36.834362 version@stat F·[1 1] S·42KiB[935B 41KiB] Sc·[0.25 0.00] -11:42:36.846382 db@janitor F·5 G·1 -11:42:36.846404 db@janitor removing table-103 -11:42:36.846487 db@open done T·16.480647ms -11:42:44.520686 db@close closing -11:42:44.520928 db@close done T·237.238µs -=============== Nov 29, 2022 (CET) =============== -11:44:14.711696 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:44:14.711839 version@stat F·[1 1] S·42KiB[935B 41KiB] Sc·[0.25 0.00] -11:44:14.711863 db@open opening -11:44:14.711925 journal@recovery F·1 -11:44:14.713393 journal@recovery recovering @108 -11:44:14.716658 memdb@flush created L0@110 N·49 S·1KiB "b\x17\x91..\x8fp\x93,v1036":"r\xfe\x98..i\xe4\x93,v1028" -11:44:14.716902 version@stat F·[2 1] S·44KiB[2KiB 41KiB] Sc·[0.50 0.00] -11:44:14.728348 db@janitor F·5 G·0 -11:44:14.728382 db@open done T·16.509186ms -11:44:18.275814 db@close closing -11:44:18.275997 db@close done T·180.432µs diff --git a/example/blockchain/MANIFEST-000112 b/example/blockchain/MANIFEST-000112 deleted file mode 100644 index 6fc7d0502ca547c967b8c9ad176e550812f999a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 443 zcmbPHq4jJFBO{|!PHI_dPD+xVQ)NkNd1i5{bAE0?Vo_pAei2hXb0N!m4ps)uqMt&y z?@oU@?Mo$t#gqA5!rOk`RCAG5`737FsndNZGvOcOL1qRJU}wmC#;chmK2d6SY{b`u z{O-?NMSj2fn%A@=?O40MgRn)19BY5UWJVqquyW0!e={<2%eT50xb5q?Xvlug<62@i zw^+_MzG!3Pb?li>CNr`?RMODk?B(p5Nv!K0&pWmEl6U;WE&b09csU+kZY!K;;NySB z@9~t^DY|`(?;#%4EZQ=K&u72Qy@qw0SI9^gEc{SC+5Ya#gIChof3GoK(fl-+@eed8 z7_%0fXVOe!ShZ}v)H973ZKjTuz^W57Dh4UtG&f9)pdKRMvI4FRD{P(`3 nxWK%VyHxzr9!@hqSbV#8VY$S`;Lu&MC!WrVbIoH^hL{Whbp)-% diff --git a/example/libp2p/libp2p.key b/example/libp2p/libp2p.key deleted file mode 100755 index 378daa63d7..0000000000 --- a/example/libp2p/libp2p.key +++ /dev/null @@ -1 +0,0 @@ -08021220cb153983432524188e92d30c36a9bcef01aad506f8cbc5ec9fa8c97e6949f641 \ No newline at end of file diff --git a/example/trie/000105.ldb b/example/trie/000105.ldb deleted file mode 100644 index 618df53fcc65d5a7441d99b34677927ac3e11e46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49685 zcmeIb2|ShUx<9_|#WK%Rkwg(Plra^VWyq8UL&^{(B(sc*ij~YFQCfryNybn@gP}4; zDitNs#3E!|{qLpT-QN4`b8h?hI{o)P=d91OKIMI%mS;V~bzj%_`hLIHGr<&$m?uV` z$<*@GjVF9ncO-f*CE4k--WOzAcb$(**z;4rXXzd=kHG+J%CtKkzKCTku5L~z4i6aZ zob<3&Nx3*In3&{3btGeV*EhdUd-r$YL;|%kSD$$hbzIIQGIBqmsAB;u{s@>Jk=ALG z2%HZ4mOhCSA?dL9tjcf_zhv-f+)P#?NAcE6y*aP#bZ5_LE2uZ;`GGz>9*CM592igI zO;^ttlCvIF5%b8^x`mL&Y;~?Io#mefsgGU+YUc{JN{9KOItO<;ahd(PJaKCFeOlk3nIl~rk#j_ zxkbjdN2i`iJo!33@hMPXrO&ydtgNPP*Bi4}$7TZWRq9M@;kk%=hu5rF^>|Ot_mkT1 z6Y8dqS?Tt#y5Le+2kbVM57?Ip5g&BwfbehYloNu3N?tZn)eT}Q%pQh`ZVQ-wMs0mM z>o`0pY)jz==Epw8?6r*U&$k)(@5j~!MdGrtnA)epZZ|QCpp-W`@bPVpm8V5M7-gIs z`$oS`M@Vz!7fs_x;z8xQ+%*Klj!JSehBui&o&33dHw#A(XWq-(d18BO3}hq*Tg;!S z%tt-EQTGgY64+pH=Y=HwzTIYEJJPBW;vtq&V0Dl`JUIHh>8XMau|r(;kIlx}aLLpR z#1Tm#B^lR+rSa^^#5iXmwmSx{13aal+Q)+O4n#Uz63e}?)*e3m;t6l zGI#fUnMwb-6Q72@B}ARG`*wngfLrLd(7Apz+GqA|0Pz)nL}jtf;Wzv>zUr}V_?EC% zVpIE3fx!xf$gylOZUJJ#u`6~gQL7)-*?shuF#JxQRNkt@(r(y%!lA#|s>@gr-lyji zrUnCAi>_65q~3EMZE78!Uvai;1z=oHin{9}2myOZF2mN=o|RQ+;~Y#P^W#N!R_v+}&i{){gBR-<6mRQA4@j=W6&7&{kJ|5XMvN2|a5G*m%1(55vRC0s zZTq})^`)fj40wJzYijy?HA>H`HZfeFbw3%wE!?e1&^SvUJ#|;V*x!&I4}WtPmXYm3 z9q1p#Fo#in;vvurbV_z;Jy_xGQb&WEWYwtJ1egIv=(`XZf54{M=WF}K>VyD;mlgK+ zoAzz|jNkk*?&8p_#HqfoEA)uL;cN!!Pi}kG&mxuL?a$?6cc`!cIKK{Km1P^U+T>tsd8UAId+UpGs6X9xGB&T}KiO z*{42MW?ISV zch5X9F>|Ar%_A0Ea-ukkGRKFWEj)TUp+~eaSi4TeP|4wz>a$D3TF-_X_H|=6zJL3k z4)~wmKO@utFP3Z{&u4z6QjA=myXj1Lv(t&LldH$pyq>=9=hROh-xj6AJm5Oaps{5=K z9+FSLGQ$(OYdcsU&F>F=!+xiCVD zXS}C27uNZ6Q!Ot$XK9}Rt--#ieVa`G=oEowLL zh)uPP_`WraX-fh9MSU+;ex(w9B}W?l9$@d!kU@W*ac<{_k3_Rn*DcatWTgnZqYB=&?;(rP{Me+$Xl|IV>YbVCJ#Na=f2pb1klSC=OeZC2JSFy} z*6wRGFPNkLCStr5qlxl#$>BLr>ePA_4 z1W%YABPwUOXqNjlU(XyXC1>tdo=7^=WMF$i+P}3oeihw4dn~{`7zBr?M zDDYvcMqp9GYZrW&2M*|P{kYdXWN{d0e=%liFek!4s1sw!h!G%{QJ*OzaGV9wLK26E zyu419&e(XhumwtgPNhEl<;7XfS61$1R&WX6QdsuW6W*C_$*O)us8-oJD|X(?W>+oAsQRdQt~}(FX(y_)N0za~cDuL$06-+TzS++$swmKqS)%ql8<)4P_{vkIJ$}IC z{HN=&nT+MlbvO3cXV6->ozt%= z5yZ(+A33;!?$dWR&P!{Gwt5Cte+BN+^F&(kVe9<4qH>OVanhN{y?5$D7x`O-j}EO7FfXNKAHvrgjSg$|HH?j!+cJQ0! z)mbcYd;N(GTU&Z3scM{+F7JE#NXf~bDA|R?_UnA?a11@SM*8;p3BiF8s%*Arwg>KB ztT%LYa$GzrhJSoi)yWtFPx_iWbuaiNXt<0^-3!)h$MFQ&hlw}6i5`*;{lMky4a8w- zO`v@J4eD1qZ*7d$TuVSpfX$+zm#H-%|io(X4O9 zy(>y}TEoG#o^+~wlN?V(M}urj#T|2M2_7HzN_KfY#=WZq|NQ8DKt`X z!O`0()T=i>TJ`a1)|+wK+!%%tZmb?RCF2kS zId2sq)LtkWXFGsf`F&g}6ewYF=hgFJ9Vk;9wDOwqPLXSO=(Zi_y<}xLcbnll^M>&& zdHZ%%CN;kxen=|K6dk0a`y|VFui)0$aqvjSPCSx{Z&SvT(Y$xsam027i%))KcwClJX$D4f-GFR_Ry^-;>wYrj6D-{;7ZKxte10`kZYk zzV{A}4VS`Q9KTxlGxR){jUi{}seYQ;#uLxnStH?`b4u4SMjSXKtsaTMNS$Lww}ckEl*BpPxgf! zob`^A+sWYnp*%f5*KxCBXoi#_@63_=DwMJel_-Eoj7W$&kDtT4cMPdF!-c%>2L|2m zzMsu^Y#r;{9gZb*%rjY^XDY}%SW})KHT~tJ$$(4pP5g0z^~6Z!)*UH+?|H@=TIw`4 z_grXU1PPRyJ`h!mk!z{pmQ+jHNpKTwl#!Oo-!W$M_N)P^!-m;G?FMT;L14?xm&`$& zhIrx<>a9OY>bJGjfvBo0v=%?R^NeJ1@RZM|wo%myEB40`u4W;wqP)eGnGfbqPjLW! z@nCf>KgC9gmKc+XcDd(l6XQps%uhe6F0EJVM1z|YRS!Zc1;LP14AB2#g^H)9`t=Qmja zun9(D2%I9S=*2iJ2}C3b{A=os316%&)?ej`e=Pn)o7>ju?I~G_OM_MX@A%`dJOqA# zI~i3yz>gDy$A?QMtX{1h8Zpx{l#u0DD{d!m4-pvYHjj;zlMWDxI^if$l1?m2f^uWb;DlP;o-upN%n1{ zp)|MGSC}xs$kK%s+!od3SbeR%**Tm2q(VqfuVoH%=SS<^A4=N}(3MI*0ng$2m%>l5 zfZqbf?>@yjvHz;|K4Doi<}E4=7p#td&MDY@=@f=1R{dCr@dFsw|3$#~U_2n{EF~*N z;Bp`qVAQ{p;wWhuVl7_G|HS@r{`b!{iOf(HHE6_uB+^dUGJ|JaW8x*ibfhRvk6DQt zR89?lW_$j+t7?KMHCuMCbbfRl++`_sDl-+t0-e{T?~*-v$0j#$1x`^Vue5)|C7O!s zM+2_M%ieiVq53fh&;kqy5kf|85iXdcaseSO7@mYz4IE(Q+I;&=Q%jxeMt+5TQmR3Q z{-+;2_7FdEo=$l)kidfE(|M#X|C@4?+}-}-RHUS3$UtB+X}OJE`f(MZgH%`7w0G=) z-hs?@C&j{0mdd;@Bm*C#gT&=qMYz`Gm?R4qduglrX| zTMMY<3Dz5B*fTR$_>MBmn?v1p$2TeBP8@HWj1$Otc~_-cSx3m43T#}wpb#gNLE^>B z(%C`5&G7UiJ3B}?`po0B(qPIhBK%B> z-yNQ|=d|E)^BOvcDUplml8fn5me|ntD5k>?DV{u4Lwf8N^Xcdz<;;Z(TQ7V#mmqXQ z3OkdT*hV|}5Dz~RZanZ)F=Ay{QEs-vFxK129m`(+#_EAOiXYuRL^Yb2&4oJ00vyiK2 zN)ZJzSd5SjOCY^8z`$-?FNU>&%}w$S)7jNLS>;>ZM!f4hD{=9w%7sb~vz(JrC7w;- z3pJP6le(W}r>;y@Da&ztA(bTEja4Ta=lWkxo|mSSec}!_KJ2X**_y9vml{2m-|?Jw zPBY`BEZ_42&%pLAT(7}C%+GF|IX|C%EB%T`ZhCX#Au_ECja6|G3W6Y)AV?)2Evr!Z z<}ikV{FTb-E52xRrmPX&?9FQ{r&G_RdpizoHqY(!eJb(IVvo&zj(+eV|0@-tI8y0m zh%%eb-dOBhu!FUNl;7j^O)O;`H0>GmlX)DLkXAv?VuBlA7E`XW&$my5=MFp@wU5A0 z$=B(JOW)Z`Ez9y+^~0;h;JS^JXpd;$=#A~E3ch0J$>urxs_ic=-*)v5?yP3 zE%+9as7GyNz$eTeo{4ere@(dMrNKbj1fpvTTz@|El-g!6Erhv0u|;P68eu6gSZ5fX zmS5&h?b4&7U`!X;Ya$PKLBZ;OG~nQ$aOFo(#Xu>*;DTO>yKk>dr&`>${I z?TMQ6Z1cZFFir$2FlLa>E@o`MWd%lOY~i`oB;(~y%Jkuf>Mb!1dpA-$yZ&I&_iaj4 z@uk^c0@;cUxOBP{Q|`?t@{+vFz;3u`9~7F5xkN*r1R|4ho~Qy507!sI#<*+O;)&C$ zg*So@9p;KL{JJqzbe*eLaQVhvPgar}YsK@sIUDcLuO}H_y&2~;n4_X|SZ_3y>U7je z^E&VKwnl3s*~?}RfcJid@Oz+0TNLt~*&pHgKpqV>*a+ael%5_4)+#nL>CwSgqk`6KS>+WaXka&5dTnmVrE+}`|2&Ik?Ydp!@T}DvhF}avElam z8%b~6gzd^eItBzMkI|ERY2Wmc$LLwc=m|?GRsDScHBr-F54Z9spY7NfJrbF>tt6me zSYQN1LY(;U#2d*~5`&|{GEY|=p>?Q>4Nw(eqBD-3G05@_4QeR0P*uN(ClYucgn);2m(&!n*|IPIhKJZmVvOfxhT+NW5vsG(O3o+5f;KWcF`3ZdejHR5j+sV-#}u?l$11^ z=?~Hu-PhqV!Acl%Q1ush`zzg{$HKT>@wig%fVsjMcg949*K7yQtG63H4glC#eerRH zgN33&l)!`1KTvWWnCu{kgn$ME0w;8_6mr9M1nKy{A~*bV;C2^Q6=X~(QX}#O?ZscppN2z^$;wr%3Nj&$TAX!auV_}19Ik;;7 zSuFU^8KeIo9w3;%C`@AsLJ(LaA-H=$S3EfMDxNrm=fByO`L%=?Z(L(vpx59v^r-Eva$quIjJ;FVom@6d=tv>J^y2alvBF*T? zJ(_bP2Ta0(EeYce8u3Jvizg;9&WCq>pYi?pJ;H2H!Bwr5<9 zR-s)u+I1=ASboI=-CF7F7x=I9t9Mn{SjCWosV)O`h>pL!Tpat1dJ|8xK7&kNraTv zNrusC$MJKXB-&>=j+}?xb9Q!XxyM z;GhMI-}Dww#u(e6ZNaG#zUl4M?z?G|Y>(8)eP?pvz4COwiZ%;mw6I|HSn7}9`>EF7 zp=(>A!P1(~J)ExfF<~`V9+UB#`PVhoA~i?OfpGv#m(qa2wMFscVQT~Sfn&#@3 z(}xQB6U#+glcJbqN^LwfrN?io$Q+ia11djzrtWz4<7hMih>+az#Cr#tCa=DwPS%P& zA*XfloXMA4&Kou+v3|IwqyFfujQw^Pi5Bfx41@Y3ouaKR|8F%Zo3?k2E_ zJdE!C{&qFjsMl~=Zs4};rmVxSn$5TG-P83*1L*P5)1^>gyPOV(RwFIuk#I2`2C{ga z&B;dF4nuN91Yh$GznsTU7vL_z7IfO%=>ZIVW+)XPpz9DPX%bP?1o)x1ZXW#H6*5kW zD`Olm(D!b8Z;@~s!`)JA zjMi}tqLa32ZBV^7aB;V9w%e_ty?$=&94VCcS{K%+Z?J&hg<#)h>Dx3)x4o@KK%uSh zv1EfW@00Z&Ja6BCNU&#?jAu;1GX|oV-7!hbBX~wWxTo*ApbcjQHM$QQudWVb9yQFh zRJeCIM&XLm$?ff?XI?szXR+F|6hX;##-FvtzW$PgPC?QaxM-N@cdj_(**_GOQa2~& z5dP`)S27h@ZP&f$CvP>)UQt{J*8FPxqe^Fr#Q6uH`KKh#u*8W=P^VZqJT5nMxOhpucMBj3;3huYxJRRn7O?vuvJEOS&vHEOs+L z<;E6w^`9lXnxO=IzzN=~@U=)ya`q$6w!3z(Ox6;!U(nISr)-KZmZ`alIYGRX zVxiHiMyXRNFQWbU!k)aX^DGhl%@%8%UWwu|;y(zFJR1tF@=T7bwijI73qH6g0vdSs z^WHKg_OVV_=gui?TX}Pwqc5X4ZyP4wG0Hk)*lI-re~s3u!|=DhmPqIbU@6IelvpA# zDQMKY`LbGVQC#pgIfl>oLtYp@TKuhm2mrkE%up%`uo5!G0;!>kfy`n?wF1HLCaNOR zNSIM|Vbw%>vs>f1a(l|TNWlB-8%u-Y?(O$dx0 zGNi-d=Xs*klR!Xf0pl(*gC~ZyM`x6p8gyDG5bZm@epz5@3gPmQ)nTLE-ALs6#HJ2$ zd8hj7C?&s_r$X{#C!QZTE%mgb?)+XBfr;u_rY}VsibY)EH?exANNw##C1;R*#pLPR zxELPtJHk+T4XftC`pkt7)sTfwIel@LW1UG=cjly?e}87+F=zknC@F$lfEFkd?;^?e^m93O--NzN5V&%#NcI7V8Z8eN*oX z0$ni3eCBAvcxdN)GKr~Q*n>f>DJ1w-DP>gwwt3!}Xvlyl-fKyo5} z6C)5wNn1jj1+7H?LmBb^Y&L+ZV<}i}9u;Hno=1oDM00EAU)&3-s@f{C)3#FNg7E%E zy-jyjfa0%AZz(+GC4e)LPZ;rYc@{<6du7MgeaKCX?J(*1$h&rPO2cU2=@8ZlMLuir z#VL{H2$P?`r`LHQ*1)?HhX!iD7mnuPZ4)2&MaWXM#5Xme64-{n&G}k@!P`0Gv<*%1PDoJ=Le$tG2|MWzibUPGz8}Z+qi1S zrt>tJ=(Rd`c84AqeeIGq(qal&xq6Ih9J)(EkVvpLPmC%J1V>b9>QynG{@HZY;2m>P zi5q?3<>m!mdHE21##P1Sm6z?D2NMEZi$=%d9`c9;hBw6?O?9IuI3rrFU>gRPZma8u zP%b*?!t$R2`7CNKg8$H5Sc@ioJoSSTbx_-HQb;*jF!J{1cdfa3fHP)Q6o#Mk*`q7{)(gUr&4+tcv0RTU?l`vl5@8$rO5apksMFPEMmpy>zc22AENf| zC~Pj3z4%p`ZSuw?mwmoU3l`JmW>x{tv+UK4Ak-TCs0woT_xWxj-8W8|-X>l+!A)@qOc(9&=@uI36a0CRN*-vhuN^PL9 zTD!1^#+j@o-2`Nd%v?5w-wJjcjpK2AdB|pS!g=ot1eQCSfE^Z>lF&#Mcl}X^+m^QB z-Ye(t-Vb9v@SfiL1kC|;w<^ZdUfJYqb+tv&Cb^LcZVrtpHxn~KVNiqU#jTd}kFKvV zE4|2QnX!vmmSaKk8?Y_9pTr~C?CMSckWLW)JZ*_`-H=>yc+vh&sH$NKi76YJaTK98 ziX`?Rjar#Fl1B3&4PJdu6o?DzMa+^S0#Wsm&>nIGby5VzIXDnd14ia_*lJKhF^tJ= zv|rjNw;;;N3UqKM2co#PA`c<`{UH#4$l^eUSGuQre!Ki@aKHOO;PA)Ga{Oxh-jAL? z&Fvf$!jQ6B6VU6~gr+Y=c&v(O^$<}HF1(;9d;so(ghu1XQRiV{Wkls?+Faxl3>+sI2+q?1A>#aknrz+|DmF)i`)-uJai@H+Mwb4?wL9!5 z>Aq478qeX9{3Obb^~n^Swotk=n|u6=N_bXbV&3O(4ay&LnXl(vGlUH}fss6{UfvsB zf(z3&wVn&&cXxW0G<;yYd49y>P=>kMn#2W7_pbVL#zvqVYEz*y{a>eO_@5&qa^^MJ z;P%mxy@zQ+;@lcGxz9!nToz_ezqA=wpG+i<-2|FHu{zkSTuMjxKQXuXYyL-g6*IvM zW%mPmz&Q+t!<~U1F8(N@9g7D;;Fm)dSJ?NLD>T}d?Af_h{|UB^v^ioz#w}c!!^P;T z!5A=rxui476!Z4rdJZ6D9YcVQYF@p24Nb?VG3#=Y?ZYVB2?kME#_1Na6rCz9Y z$!;Qt`^%}>-sZSr7!oFSpeqhbcE=;^TIQrv4P|{o^Ik-DG{?`8FJ2bYDQ~@*DU#Yic z?j=-|EYRFnEf6y_ArX)sYcL4@L0J9oHR}6)J{|w1QJ?e0-JPwiRe)|o)PQd4bj{?) zQ%9`JKApA?wPb$%$({~e{gvh-B>#&g)i1)!pD=>$!XEdD`O?;?)ReDKsCG^A=xnp% zu;19~%#bI>!r#a5C$s{IABRP`DNq$L@m~d?M1xjHH%=7Lz8uIU1sk5vuris=Ecue( zrBgZG8YcYtZ2233;d8>|Yo4oIGN^&<-=2PQ2nY*-qVnb7A;Gf*KMrm&As~Z`;BGaW z@OAZFJ@O^r^p+dn>g;k92x;uhTj+*F_Z{NK<^oPo&PCew-+)q+zhn1)$CBDn#%N10 zQO&6s;)+b#U+Y;7-2E@m3Z`%5FSkrN%5n8VdN+^RYtH4kY%qaEN!dZeVkph#ZePlZ z_8&Z*Te)!rXHQIKz!P;73#s*oi?0Sq6Jj5(w4yD!Y+txKqeGWHWd`_abHQZ+L5_n$ z1co0rO`cvZ(WRzpbL~Z12|DBb*EkKQpEG$WkL`)rL4E3`j5i}lh9zeT-OqBE3+0q0 zLQ29Dd*xRR8qz{ua_xnkY1ZG@DI{~bg*hckA8O$!jb*P+gHawuwO=HOmWE5MvOBu_ z-pKlN@lOj(J6T?rS4r&O#yjQUaK?0y6}>*$3jhWl!*FYKq1)uDN~G>wL?W2OGVp zUJA%5b&gDKtO}q$2IyhIr8H%0&&P2;% zOiwc{YBZ27&n1}LnxT9g!D~n&BZFXSqL;rKH8<4S;E71`){kzWj{VitE<^eSt~Xxz zQ&Iwi0FK@ps-!Msrl~ zUr|r!jm%NG&JmnZg(7%q7ytnPRK;HT<~dAyHEG{y5}Z-YIv}OTokEemF9Gr+Kd1fh z97drKZQy^B zed2GSZNngZf%PW=Xro3y^DDs#ERIrI1is(&X{wfS=HNnGMmK5djh#;GDV~IpEf?K# zsI%DaD+8e){Q}ClN6F`wg$}bE5X>@ozaa^3s3&Vl-fu2JdHUbYEhfZY+4j}8)CT9s zoIC326|Q$@I~~((-vrSU3KADz(?>G|S(ehWUP6tHo-$#EGM56of0jIy7Cj2}fk^4k z7ZIh*hWk-&N_@Cm(x(?%o?$PKh}I7VZFaU9dO3r$i6jYG=6gQBRRX4d<<>~!s{g|U z|JslctwR!XMnNjz%&(jdg&Z&66hs{5b^>?QX()@Mh&D$F;h=DaI@CvnQRLD*1&c#Hxkq^qE$5b$fbAdpQd za{!>*3n6mzi8PHUIxFJC{!JAd3dhEhqvpmvAKuil-t-{g(`7%f2jD_%*+}h3faUiP zf0oZ~+wlyRRIwb++Nh<3LQX+&yuj?w)doI*$Qly%k;%7kdAA5C4<4`ytIbt!>W4^E z9mL?M3o$AuG4%pM)c1Q4dujRacRkABYhZB&k&TH~#|#syaVuwpBRRh(gL!EDsa|06 z57#7e0{ve$#{_zkPNEmL@Ru9Ju3Sznvn>bBlrDKIZjTe8&CbdhQlFinK16wtV%@nu zYrj_6Pf}{U#bZaZ9KXmue#(hH#l+^-YC)~L5`Y&=@rI4*poKm;JXpOS2CzMrBAj1k zJ}aucQ-7cMwXQht{Y(CHrP1GLjCN`FIjjU@i$h&V|C8KFkg(tqYSuqJqzB&02pJGK z`D>9v;6J|>sXsY14F1Ne%s+E~v-qglGmFAvl({k3{F5jIQ#@%b#r4V>!693U>y;U5 zWEVIAFzirrg;FN6Uq;g=aFkWUd2B7w>`u7Mk>Yc08_P5KrsA>-j_Uikr_O%>b?Jl- zkO4p-bd#d2?n{CEmIb{xLp}Ro?ynMTBnKAv36dK0h$v<5kF^H!O&z!iw9HJ~}? z7A^wHj1J@i`ec&MlGyZah&BrzFC@bZhay4feX?)FgQ;Mnp6uO+({ENq0{UU9ffMbM z16zUqf^ljTu)_sSnEkNV`t$8D6n71#6aRbKVd{wll;sRCfK(jYt0?zt?L^Ahz^hcQ zS7E|?F~#z%!2zx{$|o%@D9g#}e@Z)5wXvu#->1mYgUxW_6A-2N&+{yW2J)Ny=aDp! ze-jLX@;KcMF(H)`Vz(){Uve!|qdIkEv(`)gAd!WRoyTkDFPDSEKp_O4dZa1GzfX>f zoY#nKA}#|b9&)-+0yCfq(>v;E_iSA}Q5fOU3xzM5%OM~Ql_Q|2lAsDhPvMOTA|_T; z);B=Lv>f#rIYNedi-E8w)%Ysy^(&@y>mTc^VjgV?T$=$31Qo)ko7RJBm^z2bksN-H zV~4*vEj1n=E=P?vNewT<5>Q%rD3KT`!y1;sP?ot}qqk#$*}d}p{u2>d8@4>?)BVz_ z*Je~Z7uU4v{g+x$2FUoITPGd_qTpY+vk)GxdZi#^=OL~j72jyCGR2d<-;CBZyOkB! z6iUW0edt;>ywC`^M4<5$X1W;3fkZm`;_+v8k#v@cBN={`4&xc@0G-V&`6?L;IRa7r zN%}g%5(HeqrHmMS1_vQ)#$ekz;=$EtR}H_|Nv~X2rC2Cy_-0UMi=+FXCLdR8>GRaS`vfCB=_b0Xk4S1tw zaFA?~B|p;j2{qxA+(4VzKucJ{{Hu`$+QEh!$RSpg+GFUCQouw#?RtaYL*M_20kkvXVuGs1O0(c3(Zv{<1%0@~T2H9WyP2wnI zzx$tTUH+pnoyeknS?toy5Y!XE@v9i40Gxlk(58Y*(C9iNybb{8FToDNyk!wFSOyI~ zOiWOu3K0C`hWs%N9xcIGJY`E6HjS2Gz>*#@*%O@n3tot#*e{;4Whm+4K_R?A!TrA+ z6f$jECNBl3I!DDXQ2U?U+DMD@r5O4k=7)kyKX0PNE+T@B{+EXi<@LC@BZN*-Mohrt z*9BQhb7mRt5{%drP$-_dT5`4lOlLe0rv}=+<_8n$ZMIMD6FqhAkZ*(a4#4~Kq;&lG zJZ=dyw<%}qcd21u3#XN|>Regc5tD)8J#n2cB<5BL%SSFG(18xXahQ&@b5S(41k+}e zyZqukKu-}td7`9Ez!q8{P--k7wr9Z4hpqj?2(}+qXH%=erhLT!c%H$0piG0>gcBgPsC7HAPj_LrQ`^BA}Ytm zi?ES2myl&6Z4!j!2q>RdU4%`@I;icwXG}33N>W@&y+?L!qj-g zY(l{0niDFl^mjH$8r$h%&3av!8digzh#3xG7>L}8UKbpS)gD<6*SgSku(U0a)^(P= zysz(|{l05P^~Qp+<&f}vjvGJ+Pcn6~}hScbakV^+HTt1kStoCrmAqLg0A zcDJrYx4l~!{_2{lB%ydlDelAf%Fcn6?sgHYK46T2GUQe#!*;@N(@`vwLg3$Fs;HSGOf64Oodpk)J)Q&y*S2LZK|xJKp%^dp`g#dC7>+F;Msp4`98ua z8aTjt^1-%=DNEsa!R&Y>k;*BNP=;*@+jNNSp+~EQhJw@%i-^-7f_CY!5X5K>sJx{* zXm$Z?2InRyMJ;9c7;QYw=yj!MqISIp17_N4H@Ox*`{m3GMo~^ zhMqfQGwo1YtD$HL@_yYAD4gz(*_q?tv4N-&m@y&LB%Nh)v^ut*1~P`02c4x^-->%z zlM;$N5&!9%wU%T%|x3b2?J^5>(gkTf>;P6wqJP_hRK& zD$!SRq|xsI_WleR^yeApc7FJ{9IERK0qW@vA9FfF86xM$6RZ5aDbrs@=7IP;Ne4Mp z4Z@oU*aO(WVM}-x7Y6F-E#cppF=8Vw3_LCj6oxd)RTn%4=XjD>P=pZr2gjLC)WNB3ltQ`j>4}+5hj50 z&tz%|WCsdrzXV@AR80yoOH}6=sQ;{#-6>fa5d{n^?u4S`FYbhzwL}3fJ)34s0^)C# z^EhGx!&A?S${v({)R_L_6F0EJVM1z|YRS!Zc1; zLP14AB2#g^H)9`t=Qmja_F5dUZ6`cjrE4vIR)h2|!iZ_zK4Y$ZbVdT_HSV&U2ALc6 zsAVQWJP=t;a-uxGNdDAv^v#?7*#M~-o-yRanPnJeg5s_$gL9||p3t&}O>iWg zf9S8f*)cRj%8+;F$bA(`3`A*qz*acWjY#1~FU2rYV8jHMXF?%fBZ^MIjO9-9LtqQg z3QBe)2}7S0DnV!yiAlfQcw?Q6Z29N%rdL&|0W>Xk?k70;g(KEhbUfM#ZMGqWOk!EA zpinmD@Bv#6((f{5+p}xyWLft8clyV6VP72@{d9MK?YCO)qB%8Ly#ud8kLTye2Rw4g zH*fCVGzG5ws{5CR!bi@>MdsrIQG>DIZg4Blr!#9;@Y#l=1A>q;xit61!4Q_Ubb-hr z2qGzqz=w-%vbk9Q^VLQ4162%skMQ01C5v=EjW+o47_j@!;=ux()@>UIk;;D>_Rwd& zFUYj+IvXr2UbTtg0SczxIxX^E*bNy(v&+OfRW%0rIJygrzQSl+Emhf&w-R0oQ4|EOAUtXW2<7~GouKkJA z^I-$8`uZ^pf0i#Mhvfz~#rOJ(WL@|`pu{kgs_HKr=Y}T@bptuI3D6uBx6*Tu!Kpie}nEC ziBl1lAn^zmr%It9w%h04^iLJqKg88;@hBOfIg}GY?0y*D9O`LiG4+*}9eBY`8eS+Q z5LE((Lx;HV?TF!x@Ov*uix^e^MTUStlne%1&Zu zfwZGb8j%1}5*gO`h}|ylRvTx}rV5!U7pmQ3nJ?zBe%*H9t6KIQQu{?&(1}ZOP$R|t z7M}V)lLlLwFp}Ddzk`*I?hGzvWCvnmCa7FoDzv#!4hCc{tSJ}E7+p%g)AnFZ4vX9K zYVnuuK7LWfAGf;Yn0c<_H{U7mNubVeY`MZB z_?7oXlJniQGw}BzuK{Gq!r`XXuL#vDTW7`2d)e%YkBYBYJ#&()k8ft7Vx6`wxcKuD zEcQ|0Y&nDv)Z*i{T+XRxh;e(s1S>M1>_;8Qyh7?s+O<7gJ!dDL2?iZYPTlgEv?trh0ZX=}=)#skz5;W} zzahr!n9)GE6@vqdL*17owOST?LQfQ#0=U7{7vrw}0^J*hWe6IPi$fxE6u8O102V;} zxQjw^ftwKdIav;Dkt3L)s#cI`ctDV{JS<9Lj-JI5;NKGvhBiVQ7hO`E@%%U2vfOK| zS=cZ6@c?G0P&)g8kqE8PGZr1f2V)$-4j{s%-iw;;A;Jks7dlvN9RkW&1Mp$#ll620 zO;GcDNAN@x6&zN6NDWOr0|Ax30TT2nz?ed}N@%>kB!4^9qzF777fe98FoWxut-%<2 zil-iOPCaNhRSq}!cHm?C$F{>y-;RG2;?h=)aQIeTxs%^NB}@t4SY~U)3ynEb_xWFT zI&T`|Vf0cX1Mi$9wXQmw>Uk$o6$eLBFTNmRrJUgtL{Fd04!J$t;QH(x8>l;x?Q_c?rfIkvSJZk4 zIr*#}!H4G4HU4vz@16dw77Rr7|dP}e+b;{x-s?Lv09J?-_f7oUf_t}pv zvWj5AzNN_2QteEVG927WggLhdhLzL<|N3{+m$vc5Gk5t1%D2;5_`Tu_Rr^X@hF+|g z1J{XT2h*tl)jq0d{w#j|d4Ap_(gCS9X%=$zOevzvK?{Ts%P*SeUMVhcXKx00S^KEENDPFG;TcoUDVajp#0H?*x}}bYSop( ze3>2!(OPc34Y=eHbF85`gni5m3`FGby7 z7SJc9EY==q-2JTHxX2QR6JK6a>}$5)!8G9t~fIk+6iQ!MCUw72L`}(>APf4-m%FIT!B+m$t&&O zaEYek`q6;v@v?UwRH%Lof*}D#?7@pLF;gaXL#n&gdUcIzmh6VLoW@Dp2G%nZ4rZC= zTQ=k0NM9A4ty}}RvA-&4Wc2!1A?Gba#QPhlJo%8kZY|3Zo|-}%JKx&tT7Au<%MFlP=p}hjd!jmT;1Lj6fKWGXA2o5>e>XLBU)p&UVF3Vd zK9u?1k3dbSO2Gh|=T16)$~Rp6kw*S<+z|CMj2IQ_K?LAORg1Z}0>eNpkORJd{|>Ok zj1>jE7%^&;bQ-kNs}egly<7?R-Nr7uVndHw!wF)eQqZQ!8S$NK&srWy{~W;V{CS={ zNeA%s8~IE0`gk$))W+<`=#uSwfGPnwjuXzhy+#}lXkCF3!=Y4%aDaS zH`YyAya(rh+{)cAuxapY;=Z%1vrT@*5*fiNlBzWPf2#0J(RWfT6AIz`C44i%>kQS2 z7(@6Dg6|mkCc<|+e7}Wn4!Cr~DXADBQ~F3b^*fd!?>qJ;HT)0%)ob4z{;aU~j^6(d DB@HtD diff --git a/example/trie/000106.ldb b/example/trie/000106.ldb deleted file mode 100644 index e28d6dc70ea168403851285f3233cd417d81c9c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2471 zcmeH|Ycy1A7{~X!4dc=*lFL!bxSb}FYbcb;2<1qkMlt0Y{`)L`>@0u? zoiNa1^}29W0<#+-p!>nPeKW&+g>x=#e~IaQk)!zPaBv8QglhsgqQyjO;(06i)#}s` zTD?s5Lxkev#w1Kg_Wj%tHrLzDxs$psNYS-zOLKUZy zY$;dfR-A$C=jCsYCfqbaQ%zS!cp8k;tZ(POl&o<4v%Y$-8f7pnAPS zHzt227tNTNilmls25B*=}IGEP6(>^St4-sk?*@h(3^7263P_<_89GWZrlWS~P{$4ivZt=IFFVsdW~Of=T2_CF*(d9qQL zQ_9Tx9a5FohtdHRcIMG?=rIeQS4Y|Gj4P-pL81OoncdP$7avhM)qHbR>~V@6p9g=7 zyF3`PAO3dG?1cvzq(B6UEMbk&5amX(idrFk5{{34k>RId;BIT|%UAGJz_#B72bV>U zP{;jH{E*MN0Iyw&K|`&pB1muDr~BDVmOx`TTOHOQ;gh;~8a?XD(?*e+SI{3$&9O_(4oyD7 zxE*HiQ^iukXVn_#Q=yAgNE{+K(E~*>AWTP!;V2jk*7SILvOhhcNsgMmeVC*&$bzb* z5B61VtzJDR zrx2Lf$9IG5+@P3SiH6C$72vd&fVk+- zi@m%VTzal0Gd_Qz=iJt&V78Oz!k_CiY=EUiz;@@w@ zjLxUnwLt`tIROivtq5J0f+R3E!OV;(Y+fhTE+(wJLa>Fe0qJUp&S_c6Tvc+0W0kQ5)asU7T diff --git a/example/trie/000109.ldb b/example/trie/000109.ldb deleted file mode 100644 index 913f33ecd46f8120c7db2872ed00705da0664569..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3059 zcmd5;do+}57k{5Im~kDK5-BE>NiMloL>EL-G+jhYh+Jw)435hfg|jHoEA?l^pX@uJoH)P`B2i_M$Wzn?B^ z03N!x-+5MI87)t(LEMa*St>d5R{ukxhGD1*-*#bxY54aSNY~iHb68RTNCXIiARY-S zAwgM?W)H$3_?mj5p1yfn<@F7miXHv_nI9X=i39HwRqTdl9Q-u^10kF_=T}qHbYieOt!@>))ZgGd-7PASl>&1Dvwoc@oCz0C0(*7EW)r0 zbu4s1DSF2w1}_6B!v;ZC#O=z_Bn6* z1E)x4MNg8siTR^#y<``4zw_FuvWrO!`WB-QPs3{V+MWS8Lh8}mk{`-1D`J(9-Av&A&IRaB*CvV+joOOR8O>rU!Phm{9my2)YmBm_`kFT8rS?e1`&!w)4jr+ab~tY{D7s-OyZ1n{%$Cjbe&t-9S6%SPa_iNFHzu& z1=0{+F1$#nEfSJ|H1UpMNkT~QyY_0DBYY3*Q^%6T9?yHUu6_OVAeZukZ2);C(M~bu ztadcG6=rZK;2U;LL^U-;PIrA+vMa4jlx;hzBmV41YES|p3*b)uwBw!CQ0uMA8lozJtW6Ham zuR7@(?sOU4nwVx8m|Gg8wKejI)C^H}Wfw@6Bxk{Z^x|^Gva92;q~?go=I6~UC8C=2 z&>rtwD9O3PvAL=xK=NuuT5F*M7)wng2+o#2nGKL2PBA0GNm*%cCt9KXtnEB5YIEn0 zhc&cIMyjAFURB62Mc?QSPaJF&hc5nPNkk$+s$xdyOr03Ur*nJMdCjaFE(GN`a>}A( z%#Ci%lk%P&_^%k)aJx8kSzyS2PqrUbGa&jvDsEClrdQ;wu>#tz_Bh51A3`q)vq%^u zf;{+8YU!FOV_bC5jG9@v(9BIX)w*53&(0(Y#1hK_n`kdopQFP@5g=)3|D8P3MH_ z$z1_1D+}b5=}tCT9N~3LxLSDqXo2YTqoGXP^v`t;@8MG4IT+8%)5$+>HT~(9-$~5u zg|keC|H6uyXO*Ix18?N%IBFS#LIiIRQ8kEwX5wlkXsxcJLRO-@mwyO7Ck10073C$j zYGSKg8$EE%&vGOiiv^tp|Io#8}>;H%nWB*Hd z|4JXc87Ba30$ew2kAIyxRWd`S^A2^!?4~LhO1Z`rFuB6JYTuymqE~1GD!*=Ec`%5e z{Zd;HsM`)Alm4z3foBf_;A3uCUdzHoO_2C){cLi1guSFzeI`bpWP@83!|n?O4w;{B zUM>*7-P$1h54QDmLC9ud5MN&+BRp9iX3`XG@d;Z#V=u>hu!;pviX?m4Hd}YC={XJV z)oWEx*QC_HA(Ws8DEBZ{mw4)#GRb|vBe{g zp3NRoI*w8M7yzQehW6c$>T^afMZ)?Y8E}{a9%FXJzZpk6l?freG3ttAR>%avBF8~S4g8-zw03O70)Wq)Uv;t5T`CvotHs^)*n<{vAuDCPv zprpR+k4>WqagBz*G8*v8QL^PIC<-?X&GDqf1Y!(tmfE}q0d5y~vc4D+MB}1jTOtY; zX1l3=Cb6;mwAJW}c{RwX$KVR$I!B1I?99gVmB{v$AP0-^649`1 zOhiL;+`m&fLOE&RHHaly}(RM1YyDLpLTmo)W4HIkT-y>)Ct zuW0{`EnQVa9owNm%5VJ;#hnA?3SPWK=r+>-A@s1Bkz$lGpW^}l6EV!EZCVA139<6Q zA{wlM*y0cxIV&S=c1OHJoUev~zok~dJQDgOK|w4_VLku%|6WJuDM{+2J+J=+b@^3h diff --git a/example/trie/CURRENT b/example/trie/CURRENT deleted file mode 100644 index 0e6632492f..0000000000 --- a/example/trie/CURRENT +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000111 diff --git a/example/trie/CURRENT.bak b/example/trie/CURRENT.bak deleted file mode 100644 index db6fa61f96..0000000000 --- a/example/trie/CURRENT.bak +++ /dev/null @@ -1 +0,0 @@ -MANIFEST-000108 diff --git a/example/trie/LOCK b/example/trie/LOCK deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/example/trie/LOG b/example/trie/LOG deleted file mode 100644 index fb5a0d16be..0000000000 --- a/example/trie/LOG +++ /dev/null @@ -1,500 +0,0 @@ -=============== Nov 27, 2022 (CET) =============== -22:51:55.530536 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -22:51:55.540057 db@open opening -22:51:55.540920 version@stat F·[] S·0B[] Sc·[] -22:51:55.544104 db@janitor F·2 G·0 -22:51:55.544173 db@open done T·4.060863ms -22:52:00.992848 db@close closing -22:52:00.992938 db@close done T·89.158µs -=============== Nov 27, 2022 (CET) =============== -22:52:03.862949 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -22:52:03.863165 version@stat F·[] S·0B[] Sc·[] -22:52:03.863205 db@open opening -22:52:03.863277 journal@recovery F·1 -22:52:03.863501 journal@recovery recovering @1 -22:52:03.874407 memdb@flush created L0@2 N·20 S·1KiB "\x15\xbf\xd1..\x03\xca\xce,v7":"\xf5b\xab..\x92\xdel,v13" -22:52:03.874737 version@stat F·[1] S·1KiB[1KiB] Sc·[0.25] -22:52:03.886343 db@janitor F·3 G·0 -22:52:03.886391 db@open done T·23.168312ms -22:52:07.281589 db@close closing -22:52:07.281687 db@close done T·93.376µs -=============== Nov 27, 2022 (CET) =============== -22:58:06.424207 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -22:58:06.424515 version@stat F·[1] S·1KiB[1KiB] Sc·[0.25] -22:58:06.424542 db@open opening -22:58:06.424607 journal@recovery F·1 -22:58:06.424725 journal@recovery recovering @3 -22:58:06.429476 memdb@flush created L0@5 N·12 S·950B "\x11\xb7\xce..:`W,v29":"\xe6\xd3\x19..\x8e\xc8e,v26" -22:58:06.429756 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] -22:58:06.441675 db@janitor F·4 G·0 -22:58:06.441722 db@open done T·17.162407ms -=============== Nov 27, 2022 (CET) =============== -22:59:37.874956 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -22:59:37.875149 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] -22:59:37.875170 db@open opening -22:59:37.875229 journal@recovery F·1 -22:59:37.875821 journal@recovery recovering @6 -22:59:37.878628 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] -22:59:37.897993 db@janitor F·4 G·0 -22:59:37.898042 db@open done T·22.855551ms -22:59:39.680719 db@close closing -22:59:39.680833 db@close done T·104.407µs -=============== Nov 29, 2022 (CET) =============== -07:42:20.161946 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:42:20.162409 version@stat F·[2] S·1KiB[1KiB] Sc·[0.50] -07:42:20.162427 db@open opening -07:42:20.162471 journal@recovery F·1 -07:42:20.162587 journal@recovery recovering @8 -07:42:20.165989 memdb@flush created L0@10 N·4 S·629B "\xe4\x0e\xc1..\xc8mH,v38":"\xf3w\xb1..\xc2\"\xf9,v35" -07:42:20.166650 version@stat F·[3] S·2KiB[2KiB] Sc·[0.75] -07:42:20.178614 db@janitor F·5 G·0 -07:42:20.178656 db@open done T·16.21591ms -07:42:25.529683 db@close closing -07:42:25.529789 db@close done T·99.909µs -=============== Nov 29, 2022 (CET) =============== -07:44:40.846342 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:44:40.846517 version@stat F·[3] S·2KiB[2KiB] Sc·[0.75] -07:44:40.846541 db@open opening -07:44:40.846595 journal@recovery F·1 -07:44:40.846734 journal@recovery recovering @11 -07:44:40.857884 memdb@flush created L0@13 N·38 S·2KiB "\a\x91\x06..\x1dS\xb5,v54":"\xef|\xb7..\xb4G#,v65" -07:44:40.858198 version@stat F·[4] S·5KiB[5KiB] Sc·[1.00] -07:44:40.870117 db@janitor F·6 G·0 -07:44:40.870180 db@open done T·23.619927ms -07:44:40.870311 table@compaction L0·4 -> L1·0 S·5KiB Q·78 -07:44:40.877022 table@build created L1@16 N·37 S·3KiB "\a\x91\x06..\x1dS\xb5,v54":"\xf5b\xab..\x92\xdel,v15" -07:44:40.877096 version@stat F·[0 1] S·3KiB[0B 3KiB] Sc·[0.00 0.00] -07:44:40.882327 table@compaction committed F-3 S-1KiB Ke·0 D·37 T·11.965483ms -07:44:40.882453 table@remove removed @10 -07:44:40.882576 table@remove removed @5 -07:44:40.882625 table@remove removed @2 -07:44:46.231241 db@close closing -07:44:46.231338 db@close done T·94.729µs -=============== Nov 29, 2022 (CET) =============== -07:45:07.114170 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:45:07.114410 version@stat F·[0 1] S·3KiB[0B 3KiB] Sc·[0.00 0.00] -07:45:07.114441 db@open opening -07:45:07.114520 journal@recovery F·1 -07:45:07.114704 journal@recovery recovering @14 -07:45:07.119754 memdb@flush created L0@17 N·34 S·2KiB "\x04\x96\xec..\xd8\x05\x83,v96":"\xf4I9..\x85\xddS,v79" -07:45:07.120520 version@stat F·[1 1] S·6KiB[2KiB 3KiB] Sc·[0.25 0.00] -07:45:07.132479 db@janitor F·5 G·1 -07:45:07.132503 db@janitor removing table-13 -07:45:07.132570 db@open done T·18.113518ms -=============== Nov 29, 2022 (CET) =============== -07:45:22.693483 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:45:22.693706 version@stat F·[1 1] S·6KiB[2KiB 3KiB] Sc·[0.25 0.00] -07:45:22.693734 db@open opening -07:45:22.693804 journal@recovery F·1 -07:45:22.693988 journal@recovery recovering @18 -07:45:22.694779 version@stat F·[1 1] S·6KiB[2KiB 3KiB] Sc·[0.25 0.00] -07:45:22.714155 db@janitor F·4 G·0 -07:45:22.714210 db@open done T·20.447382ms -07:45:27.631977 db@close closing -07:45:27.632069 db@close done T·90.832µs -=============== Nov 29, 2022 (CET) =============== -07:47:50.174053 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:47:50.174223 version@stat F·[1 1] S·6KiB[2KiB 3KiB] Sc·[0.25 0.00] -07:47:50.174238 db@open opening -07:47:50.174278 journal@recovery F·1 -07:47:50.174389 journal@recovery recovering @20 -07:47:50.185166 memdb@flush created L0@22 N·26 S·2KiB "\x0eN6..W0\xb2,v139":"\xd7-G..j\xae\xbf,v116" -07:47:50.185429 version@stat F·[2 1] S·8KiB[4KiB 3KiB] Sc·[0.50 0.00] -07:47:50.195283 db@janitor F·5 G·0 -07:47:50.195315 db@open done T·21.065239ms -07:47:54.508803 db@close closing -07:47:54.508920 db@close done T·103.886µs -=============== Nov 29, 2022 (CET) =============== -07:58:29.841898 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:58:29.842096 version@stat F·[2 1] S·8KiB[4KiB 3KiB] Sc·[0.50 0.00] -07:58:29.842116 db@open opening -07:58:29.842173 journal@recovery F·1 -07:58:29.842308 journal@recovery recovering @23 -07:58:29.853930 memdb@flush created L0@25 N·24 S·2KiB "\x19՟..\x99\xcd\v,v146":"\xf1Ot..\xf6Y\xe6,v148" -07:58:29.854233 version@stat F·[3 1] S·10KiB[7KiB 3KiB] Sc·[0.75 0.00] -07:58:29.865580 db@janitor F·6 G·0 -07:58:29.865617 db@open done T·23.487832ms -07:58:34.096259 db@close closing -07:58:34.096433 db@close done T·167.317µs -=============== Nov 29, 2022 (CET) =============== -07:59:00.141319 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -07:59:00.141465 version@stat F·[3 1] S·10KiB[7KiB 3KiB] Sc·[0.75 0.00] -07:59:00.141480 db@open opening -07:59:00.141523 journal@recovery F·1 -07:59:00.141633 journal@recovery recovering @26 -07:59:00.151793 memdb@flush created L0@28 N·22 S·1KiB "\x01\xd0Q..\x98\x828,v173":"\xec\x194..\x9b{\x1a,v171" -07:59:00.153147 version@stat F·[4 1] S·12KiB[8KiB 3KiB] Sc·[1.00 0.00] -07:59:00.168235 db@janitor F·7 G·0 -07:59:00.168286 db@open done T·26.784089ms -07:59:00.168346 table@compaction L0·4 -> L1·1 S·12KiB Q·188 -07:59:00.172773 table@build created L1@31 N·90 S·11KiB "\x01\xd0Q..\x98\x828,v173":"\xf5b\xab..\x92\xdel,v15" -07:59:00.172851 version@stat F·[0 1] S·11KiB[0B 11KiB] Sc·[0.00 0.00] -07:59:00.180777 table@compaction committed F-4 S-1KiB Ke·0 D·53 T·12.38572ms -07:59:00.180928 table@remove removed @25 -07:59:00.181070 table@remove removed @22 -07:59:00.181123 table@remove removed @17 -07:59:00.181165 table@remove removed @16 -07:59:06.057858 db@close closing -07:59:06.057942 db@close done T·77.697µs -=============== Nov 29, 2022 (CET) =============== -08:32:21.897521 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:32:21.897867 version@stat F·[0 1] S·11KiB[0B 11KiB] Sc·[0.00 0.00] -08:32:21.897899 db@open opening -08:32:21.897989 journal@recovery F·1 -08:32:21.898161 journal@recovery recovering @29 -08:32:21.908918 memdb@flush created L0@32 N·28 S·2KiB "!\xf5x..\xb0\x8a\x1d,v199":"\xeddY..\xa7K\xf1,v211" -08:32:21.909215 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:32:21.920833 db@janitor F·5 G·1 -08:32:21.920861 db@janitor removing table-28 -08:32:21.920979 db@open done T·23.06199ms -08:32:25.249911 db@close closing -08:32:25.250025 db@close done T·107.073µs -=============== Nov 29, 2022 (CET) =============== -08:33:22.392995 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:33:22.393256 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:33:22.393287 db@open opening -08:33:22.393370 journal@recovery F·1 -08:33:22.393569 journal@recovery recovering @33 -08:33:22.394360 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:33:22.413653 db@janitor F·4 G·0 -08:33:22.413698 db@open done T·20.383494ms -08:33:32.548471 db@close closing -08:33:32.548590 db@close done T·111.782µs -=============== Nov 29, 2022 (CET) =============== -08:33:58.605960 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:33:58.606120 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:33:58.606139 db@open opening -08:33:58.606192 journal@recovery F·1 -08:33:58.606754 journal@recovery recovering @35 -08:33:58.610119 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:33:58.629444 db@janitor F·4 G·0 -08:33:58.629493 db@open done T·23.332548ms -08:34:05.061623 db@close closing -08:34:05.061732 db@close done T·106.08µs -=============== Nov 29, 2022 (CET) =============== -08:34:23.209590 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:34:23.209903 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:34:23.209941 db@open opening -08:34:23.210041 journal@recovery F·1 -08:34:23.210286 journal@recovery recovering @37 -08:34:23.211278 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:34:23.230407 db@janitor F·4 G·0 -08:34:23.230472 db@open done T·20.495394ms -08:34:27.565814 db@close closing -08:34:27.565900 db@close done T·83.288µs -=============== Nov 29, 2022 (CET) =============== -08:34:43.133530 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:34:43.133734 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:34:43.133759 db@open opening -08:34:43.133819 journal@recovery F·1 -08:34:43.133958 journal@recovery recovering @39 -08:34:43.134549 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:34:43.148403 db@janitor F·4 G·0 -08:34:43.148459 db@open done T·14.671595ms -08:34:57.711302 db@close closing -08:34:57.711394 db@close done T·88.056µs -=============== Nov 29, 2022 (CET) =============== -08:35:00.550364 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:35:00.550567 version@stat F·[1 1] S·13KiB[2KiB 11KiB] Sc·[0.25 0.00] -08:35:00.550587 db@open opening -08:35:00.550648 journal@recovery F·1 -08:35:00.550796 journal@recovery recovering @41 -08:35:00.562138 memdb@flush created L0@43 N·82 S·6KiB "\x00J\f..s\xb3U,v252":"\xfc4N..tYH,v231" -08:35:00.562424 version@stat F·[2 1] S·20KiB[9KiB 11KiB] Sc·[0.50 0.00] -08:35:00.573709 db@janitor F·5 G·0 -08:35:00.573759 db@open done T·23.156604ms -08:35:04.919517 db@close closing -08:35:04.919636 db@close done T·117.151µs -=============== Nov 29, 2022 (CET) =============== -08:48:48.728406 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:48:48.728657 version@stat F·[2 1] S·20KiB[9KiB 11KiB] Sc·[0.50 0.00] -08:48:48.728688 db@open opening -08:48:48.728776 journal@recovery F·1 -08:48:48.729592 journal@recovery recovering @44 -08:48:48.740938 memdb@flush created L0@46 N·22 S·2KiB "\x1b|\xf7..\xf72\x1e,v304":"\xfa\xaa\xa2..\xc5\xd1T,v302" -08:48:48.741248 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:48:48.752807 db@janitor F·6 G·0 -08:48:48.752856 db@open done T·24.148648ms -=============== Nov 29, 2022 (CET) =============== -08:49:09.982477 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:49:09.982660 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:49:09.982675 db@open opening -08:49:09.982721 journal@recovery F·1 -08:49:09.982862 journal@recovery recovering @47 -08:49:09.983075 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:49:09.995835 db@janitor F·6 G·0 -08:49:09.995908 db@open done T·13.215727ms -=============== Nov 29, 2022 (CET) =============== -08:49:41.609148 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:49:41.609395 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:49:41.609424 db@open opening -08:49:41.609504 journal@recovery F·1 -08:49:41.609683 journal@recovery recovering @49 -08:49:41.610363 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:49:41.632444 db@janitor F·6 G·0 -08:49:41.632506 db@open done T·23.061488ms -=============== Nov 29, 2022 (CET) =============== -08:50:15.106485 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:50:15.106773 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:50:15.106810 db@open opening -08:50:15.106920 journal@recovery F·1 -08:50:15.107130 journal@recovery recovering @51 -08:50:15.108048 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:50:15.130945 db@janitor F·6 G·0 -08:50:15.131021 db@open done T·24.178157ms -=============== Nov 29, 2022 (CET) =============== -08:51:00.732037 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:51:00.732202 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:51:00.732221 db@open opening -08:51:00.732272 journal@recovery F·1 -08:51:00.732405 journal@recovery recovering @53 -08:51:00.733144 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:51:00.752894 db@janitor F·6 G·0 -08:51:00.752969 db@open done T·20.715027ms -=============== Nov 29, 2022 (CET) =============== -08:55:34.166530 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:55:34.166721 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:55:34.166736 db@open opening -08:55:34.166782 journal@recovery F·1 -08:55:34.166899 journal@recovery recovering @55 -08:55:34.167067 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:55:34.186644 db@janitor F·6 G·0 -08:55:34.186697 db@open done T·19.929993ms -08:55:40.541442 db@close closing -08:55:40.541541 db@close done T·97.153µs -=============== Nov 29, 2022 (CET) =============== -08:59:41.463385 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -08:59:41.463562 version@stat F·[3 1] S·22KiB[11KiB 11KiB] Sc·[0.75 0.00] -08:59:41.463582 db@open opening -08:59:41.463631 journal@recovery F·1 -08:59:41.463771 journal@recovery recovering @57 -08:59:41.475567 memdb@flush created L0@59 N·36 S·2KiB "\x14<\xae..[l\x14,v335":"\xe7\x80\x1c.._\x8ee,v324" -08:59:41.475793 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] -08:59:41.486893 db@janitor F·7 G·0 -08:59:41.486950 db@open done T·23.352547ms -08:59:41.487049 table@compaction L0·4 -> L1·1 S·25KiB Q·360 -=============== Nov 29, 2022 (CET) =============== -09:00:03.139305 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -09:00:03.139562 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] -09:00:03.139593 db@open opening -09:00:03.139699 journal@recovery F·1 -09:00:03.139849 journal@recovery recovering @60 -09:00:03.140532 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] -09:00:03.162388 db@janitor F·7 G·0 -09:00:03.162467 db@open done T·22.823367ms -09:00:03.162504 table@compaction L0·4 -> L1·1 S·25KiB Q·360 -=============== Nov 29, 2022 (CET) =============== -09:00:23.207116 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -09:00:23.207323 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] -09:00:23.207344 db@open opening -09:00:23.207406 journal@recovery F·1 -09:00:23.208021 journal@recovery recovering @62 -09:00:23.209251 version@stat F·[4 1] S·25KiB[14KiB 11KiB] Sc·[1.00 0.00] -09:00:23.232273 db@janitor F·7 G·0 -09:00:23.232327 db@open done T·24.967579ms -09:00:23.232422 table@compaction L0·4 -> L1·1 S·25KiB Q·360 -09:00:23.245153 table@build created L1@66 N·174 S·26KiB "\x00J\f..s\xb3U,v252":"\xfc4N..tYH,v234" -09:00:23.245831 version@stat F·[0 1] S·26KiB[0B 26KiB] Sc·[0.00 0.00] -09:00:23.250034 table@compaction committed F-4 S+808B Ke·0 D·84 T·17.562381ms -09:00:23.250162 table@remove removed @59 -09:00:23.250201 table@remove removed @46 -09:00:23.250341 table@remove removed @43 -09:00:23.250373 table@remove removed @32 -09:00:23.250401 table@remove removed @31 -09:00:29.773978 db@close closing -09:00:29.774050 db@close done T·71.345µs -=============== Nov 29, 2022 (CET) =============== -09:16:50.047996 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -09:16:50.048182 version@stat F·[0 1] S·26KiB[0B 26KiB] Sc·[0.00 0.00] -09:16:50.048201 db@open opening -09:16:50.048243 journal@recovery F·1 -09:16:50.048721 journal@recovery recovering @64 -09:16:50.058769 memdb@flush created L0@67 N·34 S·2KiB "\x14C\x8d..R\\\xb4,v388":"\xe5\x9b\x7f..\xdbP4,v361" -09:16:50.059036 version@stat F·[1 1] S·28KiB[2KiB 26KiB] Sc·[0.25 0.00] -09:16:50.070318 db@janitor F·4 G·0 -09:16:50.070364 db@open done T·22.140208ms -09:16:55.700780 db@close closing -09:16:55.700875 db@close done T·92.324µs -=============== Nov 29, 2022 (CET) =============== -09:49:45.754492 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -09:49:45.754768 version@stat F·[1 1] S·28KiB[2KiB 26KiB] Sc·[0.25 0.00] -09:49:45.754810 db@open opening -09:49:45.754923 journal@recovery F·1 -09:49:45.755181 journal@recovery recovering @68 -09:49:45.765477 memdb@flush created L0@70 N·30 S·2KiB "\f\xe7\x9c..ë\x11,v400":"\xe76\x83..\a\xe5\xca,v415" -09:49:45.766390 version@stat F·[2 1] S·31KiB[5KiB 26KiB] Sc·[0.50 0.00] -09:49:45.778057 db@janitor F·5 G·0 -09:49:45.778102 db@open done T·23.271137ms -09:49:51.233998 db@close closing -09:49:51.234125 db@close done T·123.003µs -=============== Nov 29, 2022 (CET) =============== -11:13:42.253930 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:13:42.254615 version@stat F·[2 1] S·31KiB[5KiB 26KiB] Sc·[0.50 0.00] -11:13:42.254646 db@open opening -11:13:42.254705 journal@recovery F·1 -11:13:42.254874 journal@recovery recovering @71 -11:13:42.257910 memdb@flush created L0@73 N·1 S·492B "=\xe4\x1a..\xf1\xda.,v427":"=\xe4\x1a..\xf1\xda.,v427" -11:13:42.258137 version@stat F·[3 1] S·31KiB[5KiB 26KiB] Sc·[0.75 0.00] -11:13:42.269683 db@janitor F·6 G·0 -11:13:42.269749 db@open done T·15.07535ms -11:13:47.687039 db@close closing -11:13:47.687172 db@close done T·124.195µs -=============== Nov 29, 2022 (CET) =============== -11:14:23.692113 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:14:23.692343 version@stat F·[3 1] S·31KiB[5KiB 26KiB] Sc·[0.75 0.00] -11:14:23.692363 db@open opening -11:14:23.692417 journal@recovery F·1 -11:14:23.692552 journal@recovery recovering @74 -11:14:23.696111 memdb@flush created L0@76 N·1 S·492B "=\xe4\x1a..\xf1\xda.,v429":"=\xe4\x1a..\xf1\xda.,v429" -11:14:23.696625 version@stat F·[4 1] S·32KiB[6KiB 26KiB] Sc·[1.00 0.00] -11:14:23.708232 db@janitor F·7 G·0 -11:14:23.708297 db@open done T·15.902515ms -11:14:23.708332 table@compaction L0·4 -> L1·1 S·32KiB Q·430 -11:14:23.712124 table@build created L1@79 N·206 S·32KiB "\x00J\f..s\xb3U,v252":"\xfc4N..tYH,v234" -11:14:23.712183 version@stat F·[0 1] S·32KiB[0B 32KiB] Sc·[0.00 0.00] -11:14:23.719919 table@compaction committed F-4 S+23B Ke·0 D·34 T·11.548244ms -11:14:23.720077 table@remove removed @73 -11:14:23.720244 table@remove removed @70 -11:14:23.720321 table@remove removed @67 -11:14:23.720409 table@remove removed @66 -11:14:27.464580 db@close closing -11:14:27.464687 db@close done T·103.987µs -=============== Nov 29, 2022 (CET) =============== -11:14:35.665718 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:14:35.665944 version@stat F·[0 1] S·32KiB[0B 32KiB] Sc·[0.00 0.00] -11:14:35.665968 db@open opening -11:14:35.666029 journal@recovery F·1 -11:14:35.666189 journal@recovery recovering @77 -11:14:35.676084 memdb@flush created L0@80 N·1 S·492B "=\xe4\x1a..\xf1\xda.,v431":"=\xe4\x1a..\xf1\xda.,v431" -11:14:35.676293 version@stat F·[1 1] S·32KiB[492B 32KiB] Sc·[0.25 0.00] -11:14:35.687856 db@janitor F·5 G·1 -11:14:35.687893 db@janitor removing table-76 -11:14:35.688006 db@open done T·22.021528ms -11:14:42.385051 db@close closing -11:14:42.385137 db@close done T·90.101µs -=============== Nov 29, 2022 (CET) =============== -11:14:54.445849 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:14:54.446024 version@stat F·[1 1] S·32KiB[492B 32KiB] Sc·[0.25 0.00] -11:14:54.446045 db@open opening -11:14:54.446090 journal@recovery F·1 -11:14:54.446244 journal@recovery recovering @81 -11:14:54.457542 memdb@flush created L0@83 N·34 S·2KiB "\x06s\xd7..C̝,v466":"\xfe\x15\xd5..\xfa\xc2{,v456" -11:14:54.457920 version@stat F·[2 1] S·35KiB[3KiB 32KiB] Sc·[0.50 0.00] -11:14:54.469380 db@janitor F·5 G·0 -11:14:54.469436 db@open done T·23.37376ms -11:15:00.257359 db@close closing -11:15:00.257460 db@close done T·99.068µs -=============== Nov 29, 2022 (CET) =============== -11:33:07.370281 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:33:07.370471 version@stat F·[2 1] S·35KiB[3KiB 32KiB] Sc·[0.50 0.00] -11:33:07.370492 db@open opening -11:33:07.370543 journal@recovery F·1 -11:33:07.370670 journal@recovery recovering @84 -11:33:07.384761 memdb@flush created L0@86 N·28 S·2KiB " ;\x8c..\xb3.\xd3,v473":"\xde+\x92..\xdaM\xcb,v468" -11:33:07.385064 version@stat F·[3 1] S·37KiB[5KiB 32KiB] Sc·[0.75 0.00] -11:33:07.396822 db@janitor F·6 G·0 -11:33:07.396898 db@open done T·26.389813ms -11:33:11.230303 db@close closing -11:33:11.230404 db@close done T·91.523µs -=============== Nov 29, 2022 (CET) =============== -11:36:41.218234 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:36:41.218450 version@stat F·[3 1] S·37KiB[5KiB 32KiB] Sc·[0.75 0.00] -11:36:41.218476 db@open opening -11:36:41.218536 journal@recovery F·1 -11:36:41.218692 journal@recovery recovering @87 -11:36:41.230324 memdb@flush created L0@89 N·18 S·1KiB "\f\xce\xda..~\xde\x19,v512":"\xc1\xd5v..\xa9_\xd0,v511" -11:36:41.230703 version@stat F·[4 1] S·39KiB[7KiB 32KiB] Sc·[1.00 0.00] -11:36:41.243562 db@janitor F·7 G·0 -11:36:41.243625 db@open done T·25.13154ms -11:36:41.243698 table@compaction L0·4 -> L1·1 S·39KiB Q·515 -11:36:41.250854 table@build created L1@92 N·246 S·39KiB "\x00J\f..s\xb3U,v252":"\xfe\x15\xd5..\xfa\xc2{,v459" -11:36:41.250991 version@stat F·[0 1] S·39KiB[0B 39KiB] Sc·[0.00 0.00] -11:36:41.256213 table@compaction committed F-4 S+715B Ke·0 D·41 T·12.468741ms -11:36:41.256440 table@remove removed @86 -11:36:41.256493 table@remove removed @83 -11:36:41.256537 table@remove removed @80 -11:36:41.256589 table@remove removed @79 -11:36:48.974288 db@close closing -11:36:48.974425 db@close done T·131.418µs -=============== Nov 29, 2022 (CET) =============== -11:40:21.440991 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:40:21.441249 version@stat F·[0 1] S·39KiB[0B 39KiB] Sc·[0.00 0.00] -11:40:21.441278 db@open opening -11:40:21.441343 journal@recovery F·1 -11:40:21.442025 journal@recovery recovering @90 -11:40:21.452456 memdb@flush created L0@93 N·40 S·3KiB "\x00K^..}\x06+,v526":"\xfb[&..\xfa\xb8\x1f,v530" -11:40:21.452713 version@stat F·[1 1] S·43KiB[3KiB 39KiB] Sc·[0.25 0.00] -11:40:21.464385 db@janitor F·5 G·1 -11:40:21.464408 db@janitor removing table-89 -11:40:21.464471 db@open done T·23.181562ms -11:40:26.940578 db@close closing -11:40:26.940732 db@close done T·135.786µs -=============== Nov 29, 2022 (CET) =============== -11:40:37.971310 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:40:37.971565 version@stat F·[1 1] S·43KiB[3KiB 39KiB] Sc·[0.25 0.00] -11:40:37.971599 db@open opening -11:40:37.971680 journal@recovery F·1 -11:40:37.971865 journal@recovery recovering @94 -11:40:37.982092 memdb@flush created L0@96 N·30 S·2KiB "\x18\x8bK..\xf2-\x81,v568":"\uf612..\x7fm\xfc,v559" -11:40:37.982590 version@stat F·[2 1] S·45KiB[5KiB 39KiB] Sc·[0.50 0.00] -11:40:37.994292 db@janitor F·5 G·0 -11:40:37.994342 db@open done T·22.71424ms -11:40:40.725398 db@close closing -11:40:40.725522 db@close done T·121.53µs -=============== Nov 29, 2022 (CET) =============== -11:40:58.970497 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:40:58.970667 version@stat F·[2 1] S·45KiB[5KiB 39KiB] Sc·[0.50 0.00] -11:40:58.970683 db@open opening -11:40:58.970727 journal@recovery F·1 -11:40:58.971191 journal@recovery recovering @97 -11:40:58.983036 memdb@flush created L0@99 N·10 S·941B "\r\x17-..I\xe2s,v591":"\xe4d\x8b..\x05\"\xa1,v589" -11:40:58.983304 version@stat F·[3 1] S·46KiB[6KiB 39KiB] Sc·[0.75 0.00] -11:40:58.994970 db@janitor F·6 G·0 -11:40:58.995027 db@open done T·24.327832ms -11:41:01.462301 db@close closing -11:41:01.462420 db@close done T·115.288µs -=============== Nov 29, 2022 (CET) =============== -11:41:17.790982 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:41:17.791219 version@stat F·[3 1] S·46KiB[6KiB 39KiB] Sc·[0.75 0.00] -11:41:17.791251 db@open opening -11:41:17.791343 journal@recovery F·1 -11:41:17.791644 journal@recovery recovering @100 -11:41:17.804109 memdb@flush created L0@102 N·12 S·1KiB "_Ex..6D\t,v602":"\xb9\xe3\xdf..f\x93\xcb,v605" -11:41:17.804456 version@stat F·[4 1] S·47KiB[7KiB 39KiB] Sc·[1.00 0.00] -11:41:17.816095 db@janitor F·7 G·0 -11:41:17.816136 db@open done T·24.869396ms -11:41:17.816209 table@compaction L0·4 -> L1·1 S·47KiB Q·611 -11:41:17.823577 table@build created L1@105 N·292 S·48KiB "\x00J\f..s\xb3U,v252":"\xfe\x15\xd5..\xfa\xc2{,v459" -11:41:17.823700 version@stat F·[0 1] S·48KiB[0B 48KiB] Sc·[0.00 0.00] -11:41:17.828209 table@compaction committed F-4 S+906B Ke·0 D·46 T·11.951541ms -11:41:17.828425 table@remove removed @99 -11:41:17.828489 table@remove removed @96 -11:41:17.828549 table@remove removed @93 -11:41:17.828617 table@remove removed @92 -11:41:22.550350 db@close closing -11:41:22.550475 db@close done T·107.904µs -=============== Nov 29, 2022 (CET) =============== -11:42:36.806480 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:42:36.806778 version@stat F·[0 1] S·48KiB[0B 48KiB] Sc·[0.00 0.00] -11:42:36.806826 db@open opening -11:42:36.806907 journal@recovery F·1 -11:42:36.807096 journal@recovery recovering @103 -11:42:36.817410 memdb@flush created L0@106 N·24 S·2KiB "\x01*\xa2.. \xbcv,v635":"\xc0{\x17..\x04\x14\x7f,v618" -11:42:36.817692 version@stat F·[1 1] S·50KiB[2KiB 48KiB] Sc·[0.25 0.00] -11:42:36.829507 db@janitor F·5 G·1 -11:42:36.829533 db@janitor removing table-102 -11:42:36.829608 db@open done T·22.768559ms -11:42:44.521220 db@close closing -11:42:44.521341 db@close done T·118.173µs -=============== Nov 29, 2022 (CET) =============== -11:44:14.688221 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed -11:44:14.688424 version@stat F·[1 1] S·50KiB[2KiB 48KiB] Sc·[0.25 0.00] -11:44:14.688449 db@open opening -11:44:14.688517 journal@recovery F·1 -11:44:14.688700 journal@recovery recovering @107 -11:44:14.698549 memdb@flush created L0@109 N·40 S·2KiB "$TM..\xbf\xf6q,v640":"\xf7\x90\xf8..\xa5\xf4!,v668" -11:44:14.699389 version@stat F·[2 1] S·53KiB[5KiB 48KiB] Sc·[0.50 0.00] -11:44:14.711523 db@janitor F·5 G·0 -11:44:14.711564 db@open done T·23.09984ms -11:44:18.276344 db@close closing -11:44:18.276475 db@close done T·127.732µs diff --git a/example/trie/MANIFEST-000111 b/example/trie/MANIFEST-000111 deleted file mode 100644 index ba6e48d698d65e3509c8653ef7d0a9ea3a78b702..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 434 zcmZoo{N%oxk&#g?`Sng zr(JwYk0}ZJPqlum#@i9UByd&K$%cn|%N2g@kY^NPVgLblhTPBM8Y&^azCR|mtgDj9 zv)?IcB3atH^t$dzuAWm1m^Mw>|E-X*0is&t`-C3}{u8z**tEr(PL^@8XWX2Syv5^@ ztD?Xx`%O!~C^F8Wv9Vdpg*6zp7Ci}DDxW*&I0K{pSGS8kGi>xiSJV`3wh(0QRM=C- zSPgaUfok#cG+Xzzp(~zb&zf-4`ovV_hlY~oZxs3hi&a=e>KU`3u4T-e+QO{C;KdUd z^?Ji)sh#_@Z_k~Yj%Y~LmB^ogN#ArpXk*;TLK Date: Mon, 12 Dec 2022 16:52:12 +0100 Subject: [PATCH 03/24] Add proof tracer --- state/immutable-trie/hasher.go | 69 +++++++++++++++++++------------ state/immutable-trie/trie.go | 12 +++++- state/immutable-trie/trie_test.go | 54 +++++++++++++++++++++++- 3 files changed, 104 insertions(+), 31 deletions(-) diff --git a/state/immutable-trie/hasher.go b/state/immutable-trie/hasher.go index 2900422238..225d3abdf1 100644 --- a/state/immutable-trie/hasher.go +++ b/state/immutable-trie/hasher.go @@ -40,6 +40,13 @@ type hasher struct { buf []byte hash hashImpl tmp [32]byte + batch Putter +} + +func (h *hasher) WithBatch(batch Putter) *hasher { + h.batch = batch + + return h } func (h *hasher) Reset() { @@ -85,20 +92,15 @@ func (h *hasher) Hash(data []byte) []byte { return h.tmp[:] } -func (t *Txn) Hash() ([]byte, error) { - if t.root == nil { +func (h *hasher) doHash(rootNode Node) ([]byte, error) { + if rootNode == nil { return emptyRoot, nil } - h, ok := hasherPool.Get().(*hasher) - if !ok { - return nil, errors.New("invalid type assertion") - } - var root []byte arena, _ := h.AcquireArena() - val := t.hash(t.root, h, arena, 0) + val := h.hashImpl(rootNode, arena, true, 0) // REDO if val.Type() == fastrlp.TypeBytes { @@ -108,8 +110,8 @@ func (t *Txn) Hash() ([]byte, error) { root = h.hash.Sum(nil) - if t.batch != nil { - t.batch.Put(root, val.Raw()) + if h.batch != nil { + h.batch.Put(root, val.Raw()) } } else { root = make([]byte, 32) @@ -122,37 +124,53 @@ func (t *Txn) Hash() ([]byte, error) { root = h.hash.Sum(nil) - if t.batch != nil { - t.batch.Put(root, tmp) + if h.batch != nil { + h.batch.Put(root, tmp) } } h.ReleaseArenas(0) - hasherPool.Put(h) return root, nil } -func (t *Txn) hash(node Node, h *hasher, a *fastrlp.Arena, d int) *fastrlp.Value { +func (t *Txn) Hash() ([]byte, error) { + h, ok := hasherPool.Get().(*hasher) + if !ok { + return nil, errors.New("invalid type assertion") + } + + defer hasherPool.Put(h) + + h.WithBatch(t.batch) + + root, err := h.doHash(t.root) + if err != nil { + return nil, err + } + + return root, nil +} + +func (h *hasher) hashImpl(node Node, a *fastrlp.Arena, useHash bool, d int) *fastrlp.Value { var val *fastrlp.Value var aa *fastrlp.Arena var idx int - if h, ok := node.Hash(); ok { - return a.NewCopyBytes(h) + if useHash { + if h, ok := node.Hash(); ok { + return a.NewCopyBytes(h) + } } switch n := node.(type) { case *ValueNode: - fmt.Println("-- val node --") - fmt.Println(n.buf) return a.NewCopyBytes(n.buf) case *ShortNode: - fmt.Println("-- short node --") - child := t.hash(n.child, h, a, d+1) + child := h.hashImpl(n.child, a, true, d+1) val = a.NewArray() val.Set(a.NewBytes(encodeCompact(n.key))) @@ -167,7 +185,7 @@ func (t *Txn) hash(node Node, h *hasher, a *fastrlp.Arena, d int) *fastrlp.Value if i == nil { val.Set(a.NewNull()) } else { - val.Set(t.hash(i, h, aa, d+1)) + val.Set(h.hashImpl(i, aa, true, d+1)) } } @@ -175,7 +193,7 @@ func (t *Txn) hash(node Node, h *hasher, a *fastrlp.Arena, d int) *fastrlp.Value if n.value == nil { val.Set(a.NewNull()) } else { - val.Set(t.hash(n.value, h, a, d+1)) + val.Set(h.hashImpl(n.value, a, true, d+1)) } default: @@ -193,15 +211,12 @@ func (t *Txn) hash(node Node, h *hasher, a *fastrlp.Arena, d int) *fastrlp.Value h.ReleaseArenas(idx) } - fmt.Println("-- buf --") - fmt.Println(h.buf) - tmp := h.Hash(h.buf) hh := node.SetHash(tmp) // Write data - if t.batch != nil { - t.batch.Put(tmp, h.buf) + if h.batch != nil { + h.batch.Put(tmp, h.buf) } return a.NewCopyBytes(hh) diff --git a/state/immutable-trie/trie.go b/state/immutable-trie/trie.go index ad9e384eb0..a9d3833607 100644 --- a/state/immutable-trie/trie.go +++ b/state/immutable-trie/trie.go @@ -242,11 +242,16 @@ type Putter interface { Put(k, v []byte) } +type Tracer interface { + Trace(node Node) +} + type Txn struct { root Node epoch uint32 storage Storage batch Putter + trace Tracer } func (t *Txn) Commit() *Trie { @@ -259,7 +264,11 @@ func (t *Txn) Lookup(key []byte) []byte { return res } -func (t *Txn) lookup(node interface{}, key []byte) (Node, []byte) { +func (t *Txn) lookup(node Node, key []byte) (Node, []byte) { + if t.trace != nil { + t.trace.Trace(node) + } + switch n := node.(type) { case nil: return nil, nil @@ -333,7 +342,6 @@ func (t *Txn) writeNode(n *FullNode) *FullNode { } func (t *Txn) Insert(key, value []byte) { - fmt.Println("-insert", bytesToHexNibbles(key)) root := t.insert(t.root, bytesToHexNibbles(key), value) if root != nil { t.root = root diff --git a/state/immutable-trie/trie_test.go b/state/immutable-trie/trie_test.go index bf651710fe..12f9c41d66 100644 --- a/state/immutable-trie/trie_test.go +++ b/state/immutable-trie/trie_test.go @@ -1,6 +1,7 @@ package itrie import ( + "encoding/hex" "fmt" "math/big" "testing" @@ -10,7 +11,6 @@ import ( ) func TestTrie_Proof(t *testing.T) { - acct := state.Account{ Balance: big.NewInt(10), } @@ -21,5 +21,55 @@ func TestTrie_Proof(t *testing.T) { txn.Insert([]byte{0x1, 0x2}, val) txn.Insert([]byte{0x1, 0x1}, val) - fmt.Println(txn.Hash()) + tracer := &tracer{} + txn.trace = tracer + + txn.Hash() + txn.Lookup([]byte{0x1, 0x2}) + + tracer.Proof() + fmt.Println(tracer.Traces()) +} + +type tracer struct { + nodes []Node + + traces map[string]string +} + +func (t *tracer) Traces() map[string]string { + return t.traces +} + +func (t *tracer) Trace(n Node) { + if t.nodes == nil { + t.nodes = []Node{} + } + + t.nodes = append(t.nodes, n) +} + +func (t *tracer) Proof() { + hasher, _ := hasherPool.Get().(*hasher) + defer hasherPool.Put(hasher) + + hasher.WithBatch(t) + + arena, _ := hasher.AcquireArena() + defer hasher.ReleaseArenas(0) + + for _, i := range t.nodes { + hasher.hashImpl(i, arena, false, 0) + } +} + +func (t *tracer) Put(k, v []byte) { + if t.traces == nil { + t.traces = map[string]string{} + } + + kStr := hex.EncodeToString(k) + if _, ok := t.traces[kStr]; !ok { + t.traces[kStr] = hex.EncodeToString(v) + } } From caaac8df7143e64a4d133d355daeaaf07fad9096 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Tue, 13 Dec 2022 17:30:02 +0100 Subject: [PATCH 04/24] prov --- blockchain/blockchain.go | 2 +- command/root/root.go | 2 + command/sidecar/sidecar.go | 94 +++++++++++++++++++++++++++++ consensus/dev/dev.go | 21 ++++++- consensus/ibft/consensus_backend.go | 2 +- state/executor.go | 14 +++-- state/immutable-trie/snapshot.go | 61 +++++++++++++++++-- state/immutable-trie/state.go | 4 +- state/immutable-trie/trie.go | 9 ++- state/immutable-trie/trie_test.go | 46 +------------- state/state.go | 2 +- state/testing.go | 24 ++++---- tests/state_test.go | 2 +- tests/testing.go | 2 +- types/types.go | 4 ++ 15 files changed, 213 insertions(+), 76 deletions(-) create mode 100644 command/sidecar/sidecar.go diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index 390aad3add..5de7d9c9cd 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -862,7 +862,7 @@ func (b *Blockchain) executeBlockTransactions(block *types.Block) (*BlockResult, return nil, err } - _, root := txn.Commit() + _, _, root := txn.Commit() // Append the receipts to the receipts cache b.receiptsCache.Add(header.Hash, txn.Receipts()) diff --git a/command/root/root.go b/command/root/root.go index ffb3e28c25..2e440cee39 100644 --- a/command/root/root.go +++ b/command/root/root.go @@ -14,6 +14,7 @@ import ( "github.com/0xPolygon/polygon-edge/command/peers" "github.com/0xPolygon/polygon-edge/command/secrets" "github.com/0xPolygon/polygon-edge/command/server" + "github.com/0xPolygon/polygon-edge/command/sidecar" "github.com/0xPolygon/polygon-edge/command/status" "github.com/0xPolygon/polygon-edge/command/txpool" "github.com/0xPolygon/polygon-edge/command/version" @@ -54,6 +55,7 @@ func (rc *RootCommand) registerSubCommands() { server.GetCommand(), whitelist.GetCommand(), license.GetCommand(), + sidecar.GetCommand(), ) } diff --git a/command/sidecar/sidecar.go b/command/sidecar/sidecar.go new file mode 100644 index 0000000000..afb177dbce --- /dev/null +++ b/command/sidecar/sidecar.go @@ -0,0 +1,94 @@ +package sidecar + +import ( + "context" + "fmt" + "io/ioutil" + "path/filepath" + "time" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/helper" + "github.com/0xPolygon/polygon-edge/server/proto" + "github.com/spf13/cobra" + "google.golang.org/protobuf/types/known/emptypb" +) + +func GetCommand() *cobra.Command { + sidecarCmd := &cobra.Command{ + Use: "sidecar", + Short: "Runs the sidecar middleware application", + Run: func(cmd *cobra.Command, args []string) { + outputter := command.InitializeOutputter(cmd) + + addr := helper.GetGRPCAddress(cmd) + + sidecar, err := newSidecar(addr) + if err != nil { + panic(err) + } + + helper.HandleSignals(sidecar.Close, outputter) + }, + } + + helper.RegisterGRPCAddressFlag(sidecarCmd) + + return sidecarCmd +} + +type sidecar struct { + clt proto.SystemClient + closeCh chan struct{} +} + +func newSidecar(grpcAddress string) (*sidecar, error) { + client, err := helper.GetSystemClientConnection(grpcAddress) + if err != nil { + return nil, err + } + + s := &sidecar{ + clt: client, + closeCh: make(chan struct{}), + } + + go s.run() + + return s, nil +} + +func (s *sidecar) run() { + path := "test-chain-dev/consensus" + lastBlock := int64(0) + + for { + status, err := s.clt.GetStatus(context.Background(), &emptypb.Empty{}) + if err != nil { + panic(err) + } + + if lastBlock == status.Current.Number { + continue + } + + lastBlock = status.Current.Number + + data, err := ioutil.ReadFile(filepath.Join(path, fmt.Sprintf("trace_%d", status.Current.Number))) + if err != nil { + panic(err) + } + + fmt.Println(string(data)) + + select { + case <-time.After(500 * time.Millisecond): + case <-s.closeCh: + return + } + } +} + +func (s *sidecar) Close() { + close(s.closeCh) +} diff --git a/consensus/dev/dev.go b/consensus/dev/dev.go index 63b571e06e..1612cb2f2e 100644 --- a/consensus/dev/dev.go +++ b/consensus/dev/dev.go @@ -1,7 +1,10 @@ package dev import ( + "encoding/json" "fmt" + "io/ioutil" + "path/filepath" "time" "github.com/0xPolygon/polygon-edge/blockchain" @@ -29,6 +32,8 @@ type Dev struct { blockchain *blockchain.Blockchain executor *state.Executor + + dataDir string } // Factory implements the base factory method @@ -44,6 +49,7 @@ func Factory( blockchain: params.Blockchain, executor: params.Executor, txpool: params.TxPool, + dataDir: params.Config.Path, } rawInterval, ok := params.Config.Config["interval"] @@ -183,7 +189,20 @@ func (d *Dev) writeNewBlock(parent *types.Header) error { txns := d.writeTransactions(gasLimit, transition) // Commit the changes - _, root := transition.Commit() + _, trace, root := transition.Commit() + + // write the trace + { + raw, err := json.Marshal(trace) + if err != nil { + panic(err) + } + + if err := ioutil.WriteFile( + filepath.Join(d.dataDir, fmt.Sprintf("trace_%d", header.Number)), raw, 0600); err != nil { + panic(err) + } + } // Update the header header.StateRoot = root diff --git a/consensus/ibft/consensus_backend.go b/consensus/ibft/consensus_backend.go index 7828b0ad69..a1bcf3fe76 100644 --- a/consensus/ibft/consensus_backend.go +++ b/consensus/ibft/consensus_backend.go @@ -184,7 +184,7 @@ func (i *backendIBFT) buildBlock(parent *types.Header) (*types.Block, error) { return nil, err } - _, root := transition.Commit() + _, _, root := transition.Commit() header.StateRoot = root header.GasUsed = transition.TotalGas() diff --git a/state/executor.go b/state/executor.go index a34e259546..f241a88176 100644 --- a/state/executor.go +++ b/state/executor.go @@ -72,7 +72,7 @@ func (e *Executor) WriteGenesis(alloc map[types.Address]*chain.GenesisAccount) t } objs := txn.Commit(false) - _, root := snap.Commit(objs) + _, _, root := snap.Commit(objs) return types.BytesToHash(root) } @@ -300,11 +300,17 @@ func (t *Transition) Write(txn *types.Transaction) error { } // Commit commits the final result -func (t *Transition) Commit() (Snapshot, types.Hash) { +func (t *Transition) Commit() (Snapshot, *types.Trace, types.Hash) { + // pre-commit op + targetAddr := types.Address{} + targetAddr[t.ctx.Number/20] = 1 + + t.state.AddBalance(targetAddr, big.NewInt(10)) + objs := t.state.Commit(t.config.EIP155) - s2, root := t.snap.Commit(objs) + s2, traces, root := t.snap.Commit(objs) - return s2, types.BytesToHash(root) + return s2, traces, types.BytesToHash(root) } func (t *Transition) subGasPool(amount uint64) error { diff --git a/state/immutable-trie/snapshot.go b/state/immutable-trie/snapshot.go index 13fd20f8ef..60825bc982 100644 --- a/state/immutable-trie/snapshot.go +++ b/state/immutable-trie/snapshot.go @@ -1,6 +1,8 @@ package itrie import ( + "encoding/hex" + "github.com/0xPolygon/polygon-edge/crypto" "github.com/0xPolygon/polygon-edge/state" "github.com/0xPolygon/polygon-edge/types" @@ -8,8 +10,9 @@ import ( ) type Snapshot struct { - state *State - trie *Trie + state *State + trie *Trie + tracer *tracer } var emptyStateHash = types.StringToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") @@ -29,6 +32,8 @@ func (s *Snapshot) GetStorage(addr types.Address, root types.Hash, rawkey types. } } + trie.tracer = s.tracer + key := crypto.Keccak256(rawkey.Bytes()) val, ok := trie.Get(key) @@ -53,6 +58,7 @@ func (s *Snapshot) GetStorage(addr types.Address, root types.Hash, rawkey types. func (s *Snapshot) GetAccount(addr types.Address) (*state.Account, error) { key := crypto.Keccak256(addr.Bytes()) + s.trie.tracer = s.tracer data, ok := s.trie.Get(key) if !ok { @@ -71,8 +77,55 @@ func (s *Snapshot) GetCode(hash types.Hash) ([]byte, bool) { return s.state.GetCode(hash) } -func (s *Snapshot) Commit(objs []*state.Object) (state.Snapshot, []byte) { +func (s *Snapshot) Commit(objs []*state.Object) (state.Snapshot, *types.Trace, []byte) { trie, root := s.trie.Commit(objs) - return &Snapshot{trie: trie, state: s.state}, root + s.tracer.Proof() + + return &Snapshot{trie: trie, state: s.state}, &types.Trace{Trace: s.tracer.Traces()}, root +} + +type tracer struct { + nodes []Node + + traces map[string]string +} + +func (t *tracer) Traces() map[string]string { + return t.traces +} + +func (t *tracer) Trace(n Node) { + if t.nodes == nil { + t.nodes = []Node{} + } + + t.nodes = append(t.nodes, n) +} + +func (t *tracer) Proof() { + hasher, _ := hasherPool.Get().(*hasher) + defer hasherPool.Put(hasher) + + hasher.WithBatch(t) + + arena, _ := hasher.AcquireArena() + defer hasher.ReleaseArenas(0) + + for _, i := range t.nodes { + if i != nil { + hasher.hashImpl(i, arena, false, 0) + } + } +} + +func (t *tracer) Put(k, v []byte) { + if t.traces == nil { + t.traces = map[string]string{} + } + + kStr := hex.EncodeToString(k) + if _, ok := t.traces[kStr]; !ok { + t.traces[kStr] = hex.EncodeToString(v) + } } diff --git a/state/immutable-trie/state.go b/state/immutable-trie/state.go index d0538e50f2..a5f8a5233a 100644 --- a/state/immutable-trie/state.go +++ b/state/immutable-trie/state.go @@ -26,7 +26,7 @@ func NewState(storage Storage) *State { } func (s *State) NewSnapshot() state.Snapshot { - return &Snapshot{state: s, trie: s.newTrie()} + return &Snapshot{state: s, tracer: &tracer{}, trie: s.newTrie()} } func (s *State) NewSnapshotAt(root types.Hash) (state.Snapshot, error) { @@ -35,7 +35,7 @@ func (s *State) NewSnapshotAt(root types.Hash) (state.Snapshot, error) { return nil, err } - return &Snapshot{state: s, trie: t}, nil + return &Snapshot{state: s, tracer: &tracer{}, trie: t}, nil } func (s *State) newTrie() *Trie { diff --git a/state/immutable-trie/trie.go b/state/immutable-trie/trie.go index a9d3833607..6306d908e9 100644 --- a/state/immutable-trie/trie.go +++ b/state/immutable-trie/trie.go @@ -94,6 +94,7 @@ type Trie struct { root Node epoch uint32 storage Storage + tracer Tracer } func NewTrie() *Trie { @@ -102,6 +103,8 @@ func NewTrie() *Trie { func (t *Trie) Get(k []byte) ([]byte, bool) { txn := t.Txn() + txn.tracer = t.tracer + res := txn.Lookup(k) return res, res != nil @@ -251,7 +254,7 @@ type Txn struct { epoch uint32 storage Storage batch Putter - trace Tracer + tracer Tracer } func (t *Txn) Commit() *Trie { @@ -265,8 +268,8 @@ func (t *Txn) Lookup(key []byte) []byte { } func (t *Txn) lookup(node Node, key []byte) (Node, []byte) { - if t.trace != nil { - t.trace.Trace(node) + if t.tracer != nil { + t.tracer.Trace(node) } switch n := node.(type) { diff --git a/state/immutable-trie/trie_test.go b/state/immutable-trie/trie_test.go index 12f9c41d66..8078054e92 100644 --- a/state/immutable-trie/trie_test.go +++ b/state/immutable-trie/trie_test.go @@ -1,7 +1,6 @@ package itrie import ( - "encoding/hex" "fmt" "math/big" "testing" @@ -22,7 +21,7 @@ func TestTrie_Proof(t *testing.T) { txn.Insert([]byte{0x1, 0x1}, val) tracer := &tracer{} - txn.trace = tracer + txn.tracer = tracer txn.Hash() txn.Lookup([]byte{0x1, 0x2}) @@ -30,46 +29,3 @@ func TestTrie_Proof(t *testing.T) { tracer.Proof() fmt.Println(tracer.Traces()) } - -type tracer struct { - nodes []Node - - traces map[string]string -} - -func (t *tracer) Traces() map[string]string { - return t.traces -} - -func (t *tracer) Trace(n Node) { - if t.nodes == nil { - t.nodes = []Node{} - } - - t.nodes = append(t.nodes, n) -} - -func (t *tracer) Proof() { - hasher, _ := hasherPool.Get().(*hasher) - defer hasherPool.Put(hasher) - - hasher.WithBatch(t) - - arena, _ := hasher.AcquireArena() - defer hasher.ReleaseArenas(0) - - for _, i := range t.nodes { - hasher.hashImpl(i, arena, false, 0) - } -} - -func (t *tracer) Put(k, v []byte) { - if t.traces == nil { - t.traces = map[string]string{} - } - - kStr := hex.EncodeToString(k) - if _, ok := t.traces[kStr]; !ok { - t.traces[kStr] = hex.EncodeToString(v) - } -} diff --git a/state/state.go b/state/state.go index 36c0ac01b0..f585d55d74 100644 --- a/state/state.go +++ b/state/state.go @@ -21,7 +21,7 @@ type State interface { type Snapshot interface { readSnapshot - Commit(objs []*Object) (Snapshot, []byte) + Commit(objs []*Object) (Snapshot, *types.Trace, []byte) } // Account is the account reference in the ethereum state diff --git a/state/testing.go b/state/testing.go index 6880725b12..198aae4838 100644 --- a/state/testing.go +++ b/state/testing.go @@ -119,13 +119,13 @@ func testDeleteCommonStateRoot(t *testing.T, buildPreState buildPreState) { txn.SetState(addr2, hash1, hash1) txn.SetState(addr2, hash2, hash1) - snap2, _ := snap.Commit(txn.Commit(false)) + snap2, _, _ := snap.Commit(txn.Commit(false)) txn2 := newTxn(snap2) txn2.SetState(addr1, hash0, hash0) txn2.SetState(addr1, hash1, hash0) - snap3, _ := snap2.Commit(txn2.Commit(false)) + snap3, _, _ := snap2.Commit(txn2.Commit(false)) txn3 := newTxn(snap3) assert.Equal(t, hash1, txn3.GetState(addr1, hash2)) @@ -146,7 +146,7 @@ func testWriteState(t *testing.T, buildPreState buildPreState) { assert.Equal(t, hash1, txn.GetState(addr1, hash1)) assert.Equal(t, hash2, txn.GetState(addr1, hash2)) - snap, _ = snap.Commit(txn.Commit(false)) + snap, _, _ = snap.Commit(txn.Commit(false)) txn = newTxn(snap) assert.Equal(t, hash1, txn.GetState(addr1, hash1)) @@ -161,7 +161,7 @@ func testWriteEmptyState(t *testing.T, buildPreState buildPreState) { // Without EIP150 the data is added txn.SetState(addr1, hash1, hash0) - snap, _ = snap.Commit(txn.Commit(false)) + snap, _, _ = snap.Commit(txn.Commit(false)) txn = newTxn(snap) assert.True(t, txn.Exist(addr1)) @@ -171,7 +171,7 @@ func testWriteEmptyState(t *testing.T, buildPreState buildPreState) { // With EIP150 the empty data is removed txn.SetState(addr1, hash1, hash0) - snap, _ = snap.Commit(txn.Commit(true)) + snap, _, _ = snap.Commit(txn.Commit(true)) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) @@ -188,7 +188,7 @@ func testUpdateStateWithEmpty(t *testing.T, buildPreState buildPreState) { // TODO, test with false (should not be deleted) // TODO, test with balance on the account and nonce - snap, _ = snap.Commit(txn.Commit(true)) + snap, _, _ = snap.Commit(txn.Commit(true)) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) @@ -202,7 +202,7 @@ func testSuicideAccountInPreState(t *testing.T, buildPreState buildPreState) { txn := newTxn(snap) txn.Suicide(addr1) - snap, _ = snap.Commit(txn.Commit(true)) + snap, _, _ = snap.Commit(txn.Commit(true)) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) @@ -220,7 +220,7 @@ func testSuicideAccount(t *testing.T, buildPreState buildPreState) { // Note, even if has commit suicide it still exists in the current txn assert.True(t, txn.Exist(addr1)) - snap, _ = snap.Commit(txn.Commit(true)) + snap, _, _ = snap.Commit(txn.Commit(true)) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) @@ -241,7 +241,7 @@ func testSuicideAccountWithData(t *testing.T, buildPreState buildPreState) { txn.SetState(addr1, hash1, hash1) txn.Suicide(addr1) - snap, _ = snap.Commit(txn.Commit(true)) + snap, _, _ = snap.Commit(txn.Commit(true)) txn = newTxn(snap) @@ -264,7 +264,7 @@ func testSuicideCoinbase(t *testing.T, buildPreState buildPreState) { txn := newTxn(snap) txn.Suicide(addr1) txn.AddSealingReward(addr1, big.NewInt(10)) - snap, _ = snap.Commit(txn.Commit(true)) + snap, _, _ = snap.Commit(txn.Commit(true)) txn = newTxn(snap) assert.Equal(t, big.NewInt(10), txn.GetBalance(addr1)) @@ -318,7 +318,7 @@ func testChangePrestateAccountBalanceToZero(t *testing.T, buildPreState buildPre txn := newTxn(snap) txn.SetBalance(addr1, big.NewInt(0)) - snap, _ = snap.Commit(txn.Commit(true)) + snap, _, _ = snap.Commit(txn.Commit(true)) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) @@ -333,7 +333,7 @@ func testChangeAccountBalanceToZero(t *testing.T, buildPreState buildPreState) { txn.SetBalance(addr1, big.NewInt(10)) txn.SetBalance(addr1, big.NewInt(0)) - snap, _ = snap.Commit(txn.Commit(true)) + snap, _, _ = snap.Commit(txn.Commit(true)) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) diff --git a/tests/state_test.go b/tests/state_test.go index aa27337142..44d48ba2ae 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -71,7 +71,7 @@ func RunSpecificTest(t *testing.T, file string, c stateCase, name, fork string, txn.AddSealingReward(env.Coinbase, big.NewInt(0)) objs := txn.Commit(forks.EIP155) - _, root := snapshot.Commit(objs) + _, _, root := snapshot.Commit(objs) if !bytes.Equal(root, p.Root.Bytes()) { t.Fatalf( diff --git a/tests/testing.go b/tests/testing.go index f24d2c6755..83f550d362 100644 --- a/tests/testing.go +++ b/tests/testing.go @@ -245,7 +245,7 @@ func buildState( } objs := txn.Commit(false) - snap, root := snap.Commit(objs) + snap, _, root := snap.Commit(objs) return s, snap, types.BytesToHash(root) } diff --git a/types/types.go b/types/types.go index 232460d5e5..8279cf8cc3 100644 --- a/types/types.go +++ b/types/types.go @@ -153,3 +153,7 @@ var ( // EmptyUncleHash is the root when there are no uncles EmptyUncleHash = StringToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") ) + +type Trace struct { + Trace map[string]string +} From 5e69d658e18079a13c5b782792479635853c73f5 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Tue, 10 Jan 2023 15:49:38 +0100 Subject: [PATCH 05/24] Add protobuf files --- command/sidecar/sidecar.go | 9 +- server/proto/system.pb.go | 554 +++++++++++++++++++++------------ server/proto/system.proto | 10 + server/proto/system_grpc.pb.go | 74 +++-- server/system_service.go | 26 ++ 5 files changed, 442 insertions(+), 231 deletions(-) diff --git a/command/sidecar/sidecar.go b/command/sidecar/sidecar.go index afb177dbce..63bcff3c62 100644 --- a/command/sidecar/sidecar.go +++ b/command/sidecar/sidecar.go @@ -3,8 +3,6 @@ package sidecar import ( "context" "fmt" - "io/ioutil" - "path/filepath" "time" "github.com/0xPolygon/polygon-edge/command" @@ -59,7 +57,6 @@ func newSidecar(grpcAddress string) (*sidecar, error) { } func (s *sidecar) run() { - path := "test-chain-dev/consensus" lastBlock := int64(0) for { @@ -72,14 +69,12 @@ func (s *sidecar) run() { continue } - lastBlock = status.Current.Number - - data, err := ioutil.ReadFile(filepath.Join(path, fmt.Sprintf("trace_%d", status.Current.Number))) + trace, err := s.clt.GetTrace(context.Background(), &proto.GetTraceRequest{Number: uint64(status.Current.Number)}) if err != nil { panic(err) } - fmt.Println(string(data)) + fmt.Println(trace.Trace) select { case <-time.After(500 * time.Millisecond): diff --git a/server/proto/system.pb.go b/server/proto/system.pb.go index ace5018810..890272cb0b 100644 --- a/server/proto/system.pb.go +++ b/server/proto/system.pb.go @@ -1,15 +1,16 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.19.4 -// source: system.proto +// protoc-gen-go v1.25.0 +// protoc v3.12.0 +// source: server/proto/system.proto package proto import ( + proto "github.com/golang/protobuf/proto" + empty "github.com/golang/protobuf/ptypes/empty" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - emptypb "google.golang.org/protobuf/types/known/emptypb" reflect "reflect" sync "sync" ) @@ -21,6 +22,104 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type GetTraceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Number uint64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"` +} + +func (x *GetTraceRequest) Reset() { + *x = GetTraceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_server_proto_system_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTraceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTraceRequest) ProtoMessage() {} + +func (x *GetTraceRequest) ProtoReflect() protoreflect.Message { + mi := &file_server_proto_system_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTraceRequest.ProtoReflect.Descriptor instead. +func (*GetTraceRequest) Descriptor() ([]byte, []int) { + return file_server_proto_system_proto_rawDescGZIP(), []int{0} +} + +func (x *GetTraceRequest) GetNumber() uint64 { + if x != nil { + return x.Number + } + return 0 +} + +type GetTraceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Trace map[string]string `protobuf:"bytes,1,rep,name=trace,proto3" json:"trace,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *GetTraceResponse) Reset() { + *x = GetTraceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_server_proto_system_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTraceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTraceResponse) ProtoMessage() {} + +func (x *GetTraceResponse) ProtoReflect() protoreflect.Message { + mi := &file_server_proto_system_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTraceResponse.ProtoReflect.Descriptor instead. +func (*GetTraceResponse) Descriptor() ([]byte, []int) { + return file_server_proto_system_proto_rawDescGZIP(), []int{1} +} + +func (x *GetTraceResponse) GetTrace() map[string]string { + if x != nil { + return x.Trace + } + return nil +} + type BlockchainEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -33,7 +132,7 @@ type BlockchainEvent struct { func (x *BlockchainEvent) Reset() { *x = BlockchainEvent{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[0] + mi := &file_server_proto_system_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -46,7 +145,7 @@ func (x *BlockchainEvent) String() string { func (*BlockchainEvent) ProtoMessage() {} func (x *BlockchainEvent) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[0] + mi := &file_server_proto_system_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -59,7 +158,7 @@ func (x *BlockchainEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockchainEvent.ProtoReflect.Descriptor instead. func (*BlockchainEvent) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{0} + return file_server_proto_system_proto_rawDescGZIP(), []int{2} } func (x *BlockchainEvent) GetAdded() []*BlockchainEvent_Header { @@ -90,7 +189,7 @@ type ServerStatus struct { func (x *ServerStatus) Reset() { *x = ServerStatus{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[1] + mi := &file_server_proto_system_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -103,7 +202,7 @@ func (x *ServerStatus) String() string { func (*ServerStatus) ProtoMessage() {} func (x *ServerStatus) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[1] + mi := &file_server_proto_system_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -116,7 +215,7 @@ func (x *ServerStatus) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerStatus.ProtoReflect.Descriptor instead. func (*ServerStatus) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{1} + return file_server_proto_system_proto_rawDescGZIP(), []int{3} } func (x *ServerStatus) GetNetwork() int64 { @@ -160,7 +259,7 @@ type Peer struct { func (x *Peer) Reset() { *x = Peer{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[2] + mi := &file_server_proto_system_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -173,7 +272,7 @@ func (x *Peer) String() string { func (*Peer) ProtoMessage() {} func (x *Peer) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[2] + mi := &file_server_proto_system_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -186,7 +285,7 @@ func (x *Peer) ProtoReflect() protoreflect.Message { // Deprecated: Use Peer.ProtoReflect.Descriptor instead. func (*Peer) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{2} + return file_server_proto_system_proto_rawDescGZIP(), []int{4} } func (x *Peer) GetId() string { @@ -221,7 +320,7 @@ type PeersAddRequest struct { func (x *PeersAddRequest) Reset() { *x = PeersAddRequest{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[3] + mi := &file_server_proto_system_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -234,7 +333,7 @@ func (x *PeersAddRequest) String() string { func (*PeersAddRequest) ProtoMessage() {} func (x *PeersAddRequest) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[3] + mi := &file_server_proto_system_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -247,7 +346,7 @@ func (x *PeersAddRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersAddRequest.ProtoReflect.Descriptor instead. func (*PeersAddRequest) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{3} + return file_server_proto_system_proto_rawDescGZIP(), []int{5} } func (x *PeersAddRequest) GetId() string { @@ -268,7 +367,7 @@ type PeersAddResponse struct { func (x *PeersAddResponse) Reset() { *x = PeersAddResponse{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[4] + mi := &file_server_proto_system_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -281,7 +380,7 @@ func (x *PeersAddResponse) String() string { func (*PeersAddResponse) ProtoMessage() {} func (x *PeersAddResponse) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[4] + mi := &file_server_proto_system_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -294,7 +393,7 @@ func (x *PeersAddResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersAddResponse.ProtoReflect.Descriptor instead. func (*PeersAddResponse) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{4} + return file_server_proto_system_proto_rawDescGZIP(), []int{6} } func (x *PeersAddResponse) GetMessage() string { @@ -315,7 +414,7 @@ type PeersStatusRequest struct { func (x *PeersStatusRequest) Reset() { *x = PeersStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[5] + mi := &file_server_proto_system_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -328,7 +427,7 @@ func (x *PeersStatusRequest) String() string { func (*PeersStatusRequest) ProtoMessage() {} func (x *PeersStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[5] + mi := &file_server_proto_system_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -341,7 +440,7 @@ func (x *PeersStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersStatusRequest.ProtoReflect.Descriptor instead. func (*PeersStatusRequest) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{5} + return file_server_proto_system_proto_rawDescGZIP(), []int{7} } func (x *PeersStatusRequest) GetId() string { @@ -362,7 +461,7 @@ type PeersListResponse struct { func (x *PeersListResponse) Reset() { *x = PeersListResponse{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[6] + mi := &file_server_proto_system_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -375,7 +474,7 @@ func (x *PeersListResponse) String() string { func (*PeersListResponse) ProtoMessage() {} func (x *PeersListResponse) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[6] + mi := &file_server_proto_system_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -388,7 +487,7 @@ func (x *PeersListResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PeersListResponse.ProtoReflect.Descriptor instead. func (*PeersListResponse) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{6} + return file_server_proto_system_proto_rawDescGZIP(), []int{8} } func (x *PeersListResponse) GetPeers() []*Peer { @@ -409,7 +508,7 @@ type BlockByNumberRequest struct { func (x *BlockByNumberRequest) Reset() { *x = BlockByNumberRequest{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[7] + mi := &file_server_proto_system_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -422,7 +521,7 @@ func (x *BlockByNumberRequest) String() string { func (*BlockByNumberRequest) ProtoMessage() {} func (x *BlockByNumberRequest) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[7] + mi := &file_server_proto_system_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -435,7 +534,7 @@ func (x *BlockByNumberRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockByNumberRequest.ProtoReflect.Descriptor instead. func (*BlockByNumberRequest) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{7} + return file_server_proto_system_proto_rawDescGZIP(), []int{9} } func (x *BlockByNumberRequest) GetNumber() uint64 { @@ -456,7 +555,7 @@ type BlockResponse struct { func (x *BlockResponse) Reset() { *x = BlockResponse{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[8] + mi := &file_server_proto_system_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -469,7 +568,7 @@ func (x *BlockResponse) String() string { func (*BlockResponse) ProtoMessage() {} func (x *BlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[8] + mi := &file_server_proto_system_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -482,7 +581,7 @@ func (x *BlockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockResponse.ProtoReflect.Descriptor instead. func (*BlockResponse) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{8} + return file_server_proto_system_proto_rawDescGZIP(), []int{10} } func (x *BlockResponse) GetData() []byte { @@ -504,7 +603,7 @@ type ExportRequest struct { func (x *ExportRequest) Reset() { *x = ExportRequest{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[9] + mi := &file_server_proto_system_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -517,7 +616,7 @@ func (x *ExportRequest) String() string { func (*ExportRequest) ProtoMessage() {} func (x *ExportRequest) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[9] + mi := &file_server_proto_system_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -530,7 +629,7 @@ func (x *ExportRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExportRequest.ProtoReflect.Descriptor instead. func (*ExportRequest) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{9} + return file_server_proto_system_proto_rawDescGZIP(), []int{11} } func (x *ExportRequest) GetFrom() uint64 { @@ -562,7 +661,7 @@ type ExportEvent struct { func (x *ExportEvent) Reset() { *x = ExportEvent{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[10] + mi := &file_server_proto_system_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -575,7 +674,7 @@ func (x *ExportEvent) String() string { func (*ExportEvent) ProtoMessage() {} func (x *ExportEvent) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[10] + mi := &file_server_proto_system_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -588,7 +687,7 @@ func (x *ExportEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use ExportEvent.ProtoReflect.Descriptor instead. func (*ExportEvent) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{10} + return file_server_proto_system_proto_rawDescGZIP(), []int{12} } func (x *ExportEvent) GetFrom() uint64 { @@ -631,7 +730,7 @@ type BlockchainEvent_Header struct { func (x *BlockchainEvent_Header) Reset() { *x = BlockchainEvent_Header{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[11] + mi := &file_server_proto_system_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -644,7 +743,7 @@ func (x *BlockchainEvent_Header) String() string { func (*BlockchainEvent_Header) ProtoMessage() {} func (x *BlockchainEvent_Header) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[11] + mi := &file_server_proto_system_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -657,7 +756,7 @@ func (x *BlockchainEvent_Header) ProtoReflect() protoreflect.Message { // Deprecated: Use BlockchainEvent_Header.ProtoReflect.Descriptor instead. func (*BlockchainEvent_Header) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{0, 0} + return file_server_proto_system_proto_rawDescGZIP(), []int{2, 0} } func (x *BlockchainEvent_Header) GetNumber() int64 { @@ -686,7 +785,7 @@ type ServerStatus_Block struct { func (x *ServerStatus_Block) Reset() { *x = ServerStatus_Block{} if protoimpl.UnsafeEnabled { - mi := &file_system_proto_msgTypes[12] + mi := &file_server_proto_system_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -699,7 +798,7 @@ func (x *ServerStatus_Block) String() string { func (*ServerStatus_Block) ProtoMessage() {} func (x *ServerStatus_Block) ProtoReflect() protoreflect.Message { - mi := &file_system_proto_msgTypes[12] + mi := &file_server_proto_system_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -712,7 +811,7 @@ func (x *ServerStatus_Block) ProtoReflect() protoreflect.Message { // Deprecated: Use ServerStatus_Block.ProtoReflect.Descriptor instead. func (*ServerStatus_Block) Descriptor() ([]byte, []int) { - return file_system_proto_rawDescGZIP(), []int{1, 0} + return file_server_proto_system_proto_rawDescGZIP(), []int{3, 0} } func (x *ServerStatus_Block) GetNumber() int64 { @@ -729,157 +828,202 @@ func (x *ServerStatus_Block) GetHash() string { return "" } -var File_system_proto protoreflect.FileDescriptor - -var file_system_proto_rawDesc = []byte{ - 0x0a, 0x0c, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, - 0x76, 0x31, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xaf, 0x01, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, - 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x1a, 0x34, 0x0a, 0x06, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, - 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, - 0x68, 0x22, 0xc3, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x18, 0x0a, 0x07, - 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, - 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x30, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, - 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x32, 0x70, 0x41, - 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, - 0x64, 0x72, 0x1a, 0x33, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x6e, - 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x4a, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x14, 0x0a, - 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, - 0x64, 0x72, 0x73, 0x22, 0x21, 0x0a, 0x0f, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2c, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, - 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x33, 0x0a, 0x11, 0x50, 0x65, - 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x1e, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, - 0x2e, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, - 0x23, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x22, 0x33, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x0b, 0x45, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, - 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x16, 0x0a, 0x06, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6c, 0x61, - 0x74, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0x8d, 0x03, 0x0a, 0x06, 0x53, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x12, 0x35, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x10, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x08, 0x50, 0x65, - 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x12, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, +var File_server_proto_system_proto protoreflect.FileDescriptor + +var file_server_proto_system_proto_rawDesc = []byte{ + 0x0a, 0x19, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x76, 0x31, 0x1a, + 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x29, 0x0a, 0x0f, + 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, + 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x74, 0x72, + 0x61, 0x63, 0x65, 0x1a, 0x38, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaf, 0x01, + 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x30, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, 0x61, 0x64, + 0x64, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x1a, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, + 0xc3, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x65, + 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x65, 0x6e, + 0x65, 0x73, 0x69, 0x73, 0x12, 0x30, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x07, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, 0x64, + 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, 0x64, 0x72, + 0x1a, 0x33, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x4a, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, + 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, + 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, + 0x73, 0x22, 0x21, 0x0a, 0x0f, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x22, 0x2c, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x33, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, + 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2e, 0x0a, + 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x23, 0x0a, + 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x22, 0x33, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, + 0x74, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, + 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xc4, 0x03, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x12, 0x35, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, - 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x12, 0x3a, - 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x0d, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x76, 0x31, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, - 0x72, 0x74, 0x12, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x42, 0x0f, 0x5a, 0x0d, 0x2f, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x10, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x12, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x35, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x12, 0x13, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, + 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, + 0x3c, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x31, 0x2e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, + 0x06, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, + 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x31, 0x2e, + 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x42, 0x0f, 0x5a, + 0x0d, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_system_proto_rawDescOnce sync.Once - file_system_proto_rawDescData = file_system_proto_rawDesc + file_server_proto_system_proto_rawDescOnce sync.Once + file_server_proto_system_proto_rawDescData = file_server_proto_system_proto_rawDesc ) -func file_system_proto_rawDescGZIP() []byte { - file_system_proto_rawDescOnce.Do(func() { - file_system_proto_rawDescData = protoimpl.X.CompressGZIP(file_system_proto_rawDescData) +func file_server_proto_system_proto_rawDescGZIP() []byte { + file_server_proto_system_proto_rawDescOnce.Do(func() { + file_server_proto_system_proto_rawDescData = protoimpl.X.CompressGZIP(file_server_proto_system_proto_rawDescData) }) - return file_system_proto_rawDescData -} - -var file_system_proto_msgTypes = make([]protoimpl.MessageInfo, 13) -var file_system_proto_goTypes = []interface{}{ - (*BlockchainEvent)(nil), // 0: v1.BlockchainEvent - (*ServerStatus)(nil), // 1: v1.ServerStatus - (*Peer)(nil), // 2: v1.Peer - (*PeersAddRequest)(nil), // 3: v1.PeersAddRequest - (*PeersAddResponse)(nil), // 4: v1.PeersAddResponse - (*PeersStatusRequest)(nil), // 5: v1.PeersStatusRequest - (*PeersListResponse)(nil), // 6: v1.PeersListResponse - (*BlockByNumberRequest)(nil), // 7: v1.BlockByNumberRequest - (*BlockResponse)(nil), // 8: v1.BlockResponse - (*ExportRequest)(nil), // 9: v1.ExportRequest - (*ExportEvent)(nil), // 10: v1.ExportEvent - (*BlockchainEvent_Header)(nil), // 11: v1.BlockchainEvent.Header - (*ServerStatus_Block)(nil), // 12: v1.ServerStatus.Block - (*emptypb.Empty)(nil), // 13: google.protobuf.Empty -} -var file_system_proto_depIdxs = []int32{ - 11, // 0: v1.BlockchainEvent.added:type_name -> v1.BlockchainEvent.Header - 11, // 1: v1.BlockchainEvent.removed:type_name -> v1.BlockchainEvent.Header - 12, // 2: v1.ServerStatus.current:type_name -> v1.ServerStatus.Block - 2, // 3: v1.PeersListResponse.peers:type_name -> v1.Peer - 13, // 4: v1.System.GetStatus:input_type -> google.protobuf.Empty - 3, // 5: v1.System.PeersAdd:input_type -> v1.PeersAddRequest - 13, // 6: v1.System.PeersList:input_type -> google.protobuf.Empty - 5, // 7: v1.System.PeersStatus:input_type -> v1.PeersStatusRequest - 13, // 8: v1.System.Subscribe:input_type -> google.protobuf.Empty - 7, // 9: v1.System.BlockByNumber:input_type -> v1.BlockByNumberRequest - 9, // 10: v1.System.Export:input_type -> v1.ExportRequest - 1, // 11: v1.System.GetStatus:output_type -> v1.ServerStatus - 4, // 12: v1.System.PeersAdd:output_type -> v1.PeersAddResponse - 6, // 13: v1.System.PeersList:output_type -> v1.PeersListResponse - 2, // 14: v1.System.PeersStatus:output_type -> v1.Peer - 0, // 15: v1.System.Subscribe:output_type -> v1.BlockchainEvent - 8, // 16: v1.System.BlockByNumber:output_type -> v1.BlockResponse - 10, // 17: v1.System.Export:output_type -> v1.ExportEvent - 11, // [11:18] is the sub-list for method output_type - 4, // [4:11] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_system_proto_init() } -func file_system_proto_init() { - if File_system_proto != nil { + return file_server_proto_system_proto_rawDescData +} + +var file_server_proto_system_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_server_proto_system_proto_goTypes = []interface{}{ + (*GetTraceRequest)(nil), // 0: v1.GetTraceRequest + (*GetTraceResponse)(nil), // 1: v1.GetTraceResponse + (*BlockchainEvent)(nil), // 2: v1.BlockchainEvent + (*ServerStatus)(nil), // 3: v1.ServerStatus + (*Peer)(nil), // 4: v1.Peer + (*PeersAddRequest)(nil), // 5: v1.PeersAddRequest + (*PeersAddResponse)(nil), // 6: v1.PeersAddResponse + (*PeersStatusRequest)(nil), // 7: v1.PeersStatusRequest + (*PeersListResponse)(nil), // 8: v1.PeersListResponse + (*BlockByNumberRequest)(nil), // 9: v1.BlockByNumberRequest + (*BlockResponse)(nil), // 10: v1.BlockResponse + (*ExportRequest)(nil), // 11: v1.ExportRequest + (*ExportEvent)(nil), // 12: v1.ExportEvent + nil, // 13: v1.GetTraceResponse.TraceEntry + (*BlockchainEvent_Header)(nil), // 14: v1.BlockchainEvent.Header + (*ServerStatus_Block)(nil), // 15: v1.ServerStatus.Block + (*empty.Empty)(nil), // 16: google.protobuf.Empty +} +var file_server_proto_system_proto_depIdxs = []int32{ + 13, // 0: v1.GetTraceResponse.trace:type_name -> v1.GetTraceResponse.TraceEntry + 14, // 1: v1.BlockchainEvent.added:type_name -> v1.BlockchainEvent.Header + 14, // 2: v1.BlockchainEvent.removed:type_name -> v1.BlockchainEvent.Header + 15, // 3: v1.ServerStatus.current:type_name -> v1.ServerStatus.Block + 4, // 4: v1.PeersListResponse.peers:type_name -> v1.Peer + 16, // 5: v1.System.GetStatus:input_type -> google.protobuf.Empty + 0, // 6: v1.System.GetTrace:input_type -> v1.GetTraceRequest + 5, // 7: v1.System.PeersAdd:input_type -> v1.PeersAddRequest + 16, // 8: v1.System.PeersList:input_type -> google.protobuf.Empty + 7, // 9: v1.System.PeersStatus:input_type -> v1.PeersStatusRequest + 16, // 10: v1.System.Subscribe:input_type -> google.protobuf.Empty + 9, // 11: v1.System.BlockByNumber:input_type -> v1.BlockByNumberRequest + 11, // 12: v1.System.Export:input_type -> v1.ExportRequest + 3, // 13: v1.System.GetStatus:output_type -> v1.ServerStatus + 1, // 14: v1.System.GetTrace:output_type -> v1.GetTraceResponse + 6, // 15: v1.System.PeersAdd:output_type -> v1.PeersAddResponse + 8, // 16: v1.System.PeersList:output_type -> v1.PeersListResponse + 4, // 17: v1.System.PeersStatus:output_type -> v1.Peer + 2, // 18: v1.System.Subscribe:output_type -> v1.BlockchainEvent + 10, // 19: v1.System.BlockByNumber:output_type -> v1.BlockResponse + 12, // 20: v1.System.Export:output_type -> v1.ExportEvent + 13, // [13:21] is the sub-list for method output_type + 5, // [5:13] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_server_proto_system_proto_init() } +func file_server_proto_system_proto_init() { + if File_server_proto_system_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_system_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTraceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_server_proto_system_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTraceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_server_proto_system_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockchainEvent); i { case 0: return &v.state @@ -891,7 +1035,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServerStatus); i { case 0: return &v.state @@ -903,7 +1047,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Peer); i { case 0: return &v.state @@ -915,7 +1059,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersAddRequest); i { case 0: return &v.state @@ -927,7 +1071,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersAddResponse); i { case 0: return &v.state @@ -939,7 +1083,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersStatusRequest); i { case 0: return &v.state @@ -951,7 +1095,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PeersListResponse); i { case 0: return &v.state @@ -963,7 +1107,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockByNumberRequest); i { case 0: return &v.state @@ -975,7 +1119,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockResponse); i { case 0: return &v.state @@ -987,7 +1131,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExportRequest); i { case 0: return &v.state @@ -999,7 +1143,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExportEvent); i { case 0: return &v.state @@ -1011,7 +1155,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockchainEvent_Header); i { case 0: return &v.state @@ -1023,7 +1167,7 @@ func file_system_proto_init() { return nil } } - file_system_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServerStatus_Block); i { case 0: return &v.state @@ -1040,18 +1184,18 @@ func file_system_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_system_proto_rawDesc, + RawDescriptor: file_server_proto_system_proto_rawDesc, NumEnums: 0, - NumMessages: 13, + NumMessages: 16, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_system_proto_goTypes, - DependencyIndexes: file_system_proto_depIdxs, - MessageInfos: file_system_proto_msgTypes, + GoTypes: file_server_proto_system_proto_goTypes, + DependencyIndexes: file_server_proto_system_proto_depIdxs, + MessageInfos: file_server_proto_system_proto_msgTypes, }.Build() - File_system_proto = out.File - file_system_proto_rawDesc = nil - file_system_proto_goTypes = nil - file_system_proto_depIdxs = nil + File_server_proto_system_proto = out.File + file_server_proto_system_proto_rawDesc = nil + file_server_proto_system_proto_goTypes = nil + file_server_proto_system_proto_depIdxs = nil } diff --git a/server/proto/system.proto b/server/proto/system.proto index e7e929df44..f71ab09106 100644 --- a/server/proto/system.proto +++ b/server/proto/system.proto @@ -10,6 +10,8 @@ service System { // GetInfo returns info about the client rpc GetStatus(google.protobuf.Empty) returns (ServerStatus); + rpc GetTrace(GetTraceRequest) returns (GetTraceResponse); + // PeersAdd adds a new peer rpc PeersAdd(PeersAddRequest) returns (PeersAddResponse); @@ -29,6 +31,14 @@ service System { rpc Export(ExportRequest) returns (stream ExportEvent); } +message GetTraceRequest { + uint64 number = 1; +} + +message GetTraceResponse { + map trace = 1; +} + message BlockchainEvent { repeated Header added = 1; repeated Header removed = 2; diff --git a/server/proto/system_grpc.pb.go b/server/proto/system_grpc.pb.go index eba359b689..f5af25122f 100644 --- a/server/proto/system_grpc.pb.go +++ b/server/proto/system_grpc.pb.go @@ -4,10 +4,10 @@ package proto import ( context "context" + empty "github.com/golang/protobuf/ptypes/empty" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" - emptypb "google.golang.org/protobuf/types/known/emptypb" ) // This is a compile-time assertion to ensure that this generated file @@ -20,15 +20,16 @@ const _ = grpc.SupportPackageIsVersion7 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type SystemClient interface { // GetInfo returns info about the client - GetStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ServerStatus, error) + GetStatus(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ServerStatus, error) + GetTrace(ctx context.Context, in *GetTraceRequest, opts ...grpc.CallOption) (*GetTraceResponse, error) // PeersAdd adds a new peer PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error) // PeersList returns the list of peers - PeersList(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*PeersListResponse, error) + PeersList(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*PeersListResponse, error) // PeersInfo returns the info of a peer PeersStatus(ctx context.Context, in *PeersStatusRequest, opts ...grpc.CallOption) (*Peer, error) // Subscribe subscribes to blockchain events - Subscribe(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (System_SubscribeClient, error) + Subscribe(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (System_SubscribeClient, error) // Export returns blockchain data BlockByNumber(ctx context.Context, in *BlockByNumberRequest, opts ...grpc.CallOption) (*BlockResponse, error) // Export returns blockchain data @@ -43,7 +44,7 @@ func NewSystemClient(cc grpc.ClientConnInterface) SystemClient { return &systemClient{cc} } -func (c *systemClient) GetStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ServerStatus, error) { +func (c *systemClient) GetStatus(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*ServerStatus, error) { out := new(ServerStatus) err := c.cc.Invoke(ctx, "/v1.System/GetStatus", in, out, opts...) if err != nil { @@ -52,6 +53,15 @@ func (c *systemClient) GetStatus(ctx context.Context, in *emptypb.Empty, opts .. return out, nil } +func (c *systemClient) GetTrace(ctx context.Context, in *GetTraceRequest, opts ...grpc.CallOption) (*GetTraceResponse, error) { + out := new(GetTraceResponse) + err := c.cc.Invoke(ctx, "/v1.System/GetTrace", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *systemClient) PeersAdd(ctx context.Context, in *PeersAddRequest, opts ...grpc.CallOption) (*PeersAddResponse, error) { out := new(PeersAddResponse) err := c.cc.Invoke(ctx, "/v1.System/PeersAdd", in, out, opts...) @@ -61,7 +71,7 @@ func (c *systemClient) PeersAdd(ctx context.Context, in *PeersAddRequest, opts . return out, nil } -func (c *systemClient) PeersList(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*PeersListResponse, error) { +func (c *systemClient) PeersList(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (*PeersListResponse, error) { out := new(PeersListResponse) err := c.cc.Invoke(ctx, "/v1.System/PeersList", in, out, opts...) if err != nil { @@ -79,7 +89,7 @@ func (c *systemClient) PeersStatus(ctx context.Context, in *PeersStatusRequest, return out, nil } -func (c *systemClient) Subscribe(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (System_SubscribeClient, error) { +func (c *systemClient) Subscribe(ctx context.Context, in *empty.Empty, opts ...grpc.CallOption) (System_SubscribeClient, error) { stream, err := c.cc.NewStream(ctx, &System_ServiceDesc.Streams[0], "/v1.System/Subscribe", opts...) if err != nil { return nil, err @@ -157,15 +167,16 @@ func (x *systemExportClient) Recv() (*ExportEvent, error) { // for forward compatibility type SystemServer interface { // GetInfo returns info about the client - GetStatus(context.Context, *emptypb.Empty) (*ServerStatus, error) + GetStatus(context.Context, *empty.Empty) (*ServerStatus, error) + GetTrace(context.Context, *GetTraceRequest) (*GetTraceResponse, error) // PeersAdd adds a new peer PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error) // PeersList returns the list of peers - PeersList(context.Context, *emptypb.Empty) (*PeersListResponse, error) + PeersList(context.Context, *empty.Empty) (*PeersListResponse, error) // PeersInfo returns the info of a peer PeersStatus(context.Context, *PeersStatusRequest) (*Peer, error) // Subscribe subscribes to blockchain events - Subscribe(*emptypb.Empty, System_SubscribeServer) error + Subscribe(*empty.Empty, System_SubscribeServer) error // Export returns blockchain data BlockByNumber(context.Context, *BlockByNumberRequest) (*BlockResponse, error) // Export returns blockchain data @@ -177,19 +188,22 @@ type SystemServer interface { type UnimplementedSystemServer struct { } -func (UnimplementedSystemServer) GetStatus(context.Context, *emptypb.Empty) (*ServerStatus, error) { +func (UnimplementedSystemServer) GetStatus(context.Context, *empty.Empty) (*ServerStatus, error) { return nil, status.Errorf(codes.Unimplemented, "method GetStatus not implemented") } +func (UnimplementedSystemServer) GetTrace(context.Context, *GetTraceRequest) (*GetTraceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTrace not implemented") +} func (UnimplementedSystemServer) PeersAdd(context.Context, *PeersAddRequest) (*PeersAddResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PeersAdd not implemented") } -func (UnimplementedSystemServer) PeersList(context.Context, *emptypb.Empty) (*PeersListResponse, error) { +func (UnimplementedSystemServer) PeersList(context.Context, *empty.Empty) (*PeersListResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PeersList not implemented") } func (UnimplementedSystemServer) PeersStatus(context.Context, *PeersStatusRequest) (*Peer, error) { return nil, status.Errorf(codes.Unimplemented, "method PeersStatus not implemented") } -func (UnimplementedSystemServer) Subscribe(*emptypb.Empty, System_SubscribeServer) error { +func (UnimplementedSystemServer) Subscribe(*empty.Empty, System_SubscribeServer) error { return status.Errorf(codes.Unimplemented, "method Subscribe not implemented") } func (UnimplementedSystemServer) BlockByNumber(context.Context, *BlockByNumberRequest) (*BlockResponse, error) { @@ -212,7 +226,7 @@ func RegisterSystemServer(s grpc.ServiceRegistrar, srv SystemServer) { } func _System_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) + in := new(empty.Empty) if err := dec(in); err != nil { return nil, err } @@ -224,7 +238,25 @@ func _System_GetStatus_Handler(srv interface{}, ctx context.Context, dec func(in FullMethod: "/v1.System/GetStatus", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(SystemServer).GetStatus(ctx, req.(*emptypb.Empty)) + return srv.(SystemServer).GetStatus(ctx, req.(*empty.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _System_GetTrace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTraceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SystemServer).GetTrace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/v1.System/GetTrace", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SystemServer).GetTrace(ctx, req.(*GetTraceRequest)) } return interceptor(ctx, in, info, handler) } @@ -248,7 +280,7 @@ func _System_PeersAdd_Handler(srv interface{}, ctx context.Context, dec func(int } func _System_PeersList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) + in := new(empty.Empty) if err := dec(in); err != nil { return nil, err } @@ -260,7 +292,7 @@ func _System_PeersList_Handler(srv interface{}, ctx context.Context, dec func(in FullMethod: "/v1.System/PeersList", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(SystemServer).PeersList(ctx, req.(*emptypb.Empty)) + return srv.(SystemServer).PeersList(ctx, req.(*empty.Empty)) } return interceptor(ctx, in, info, handler) } @@ -284,7 +316,7 @@ func _System_PeersStatus_Handler(srv interface{}, ctx context.Context, dec func( } func _System_Subscribe_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(emptypb.Empty) + m := new(empty.Empty) if err := stream.RecvMsg(m); err != nil { return err } @@ -354,6 +386,10 @@ var System_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetStatus", Handler: _System_GetStatus_Handler, }, + { + MethodName: "GetTrace", + Handler: _System_GetTrace_Handler, + }, { MethodName: "PeersAdd", Handler: _System_PeersAdd_Handler, @@ -383,5 +419,5 @@ var System_ServiceDesc = grpc.ServiceDesc{ ServerStreams: true, }, }, - Metadata: "system.proto", + Metadata: "server/proto/system.proto", } diff --git a/server/system_service.go b/server/system_service.go index 0d81a6d6c1..2e96bfec80 100644 --- a/server/system_service.go +++ b/server/system_service.go @@ -3,8 +3,11 @@ package server import ( "bytes" "context" + "encoding/json" "errors" "fmt" + "io/ioutil" + "path/filepath" "github.com/0xPolygon/polygon-edge/blockchain" "github.com/0xPolygon/polygon-edge/network/common" @@ -20,6 +23,29 @@ type systemService struct { server *Server } +func (s *systemService) GetTrace(ctx context.Context, req *proto.GetTraceRequest) (*proto.GetTraceResponse, error) { + path := filepath.Join(s.server.config.DataDir, "consensus") + + data, err := ioutil.ReadFile(filepath.Join(path, fmt.Sprintf("trace_%d", req.Number))) + if err != nil { + return nil, err + } + + var traceData struct { + Trace map[string]string `json:"trace"` + } + + if err := json.Unmarshal(data, &traceData); err != nil { + return nil, err + } + + resp := &proto.GetTraceResponse{ + Trace: traceData.Trace, + } + + return resp, nil +} + // GetStatus returns the current system status, in the form of: // // Network: From 202bb995729573ec008003d60c95872a6148e9bb Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Wed, 8 Feb 2023 09:05:39 +0100 Subject: [PATCH 06/24] Separate account from storage trie --- command/sidecar/sidecar.go | 4 +- consensus/dev/dev.go | 2 +- server/proto/system.pb.go | 288 ++++++++++++++++-------------- server/proto/system.proto | 3 +- server/system_service.go | 12 +- state/executor.go | 4 +- state/immutable-trie/snapshot.go | 68 +++++-- state/immutable-trie/state.go | 4 +- state/immutable-trie/trie_test.go | 9 +- types/types.go | 3 +- 10 files changed, 228 insertions(+), 169 deletions(-) diff --git a/command/sidecar/sidecar.go b/command/sidecar/sidecar.go index 63bcff3c62..d5c1ca9a05 100644 --- a/command/sidecar/sidecar.go +++ b/command/sidecar/sidecar.go @@ -74,7 +74,9 @@ func (s *sidecar) run() { panic(err) } - fmt.Println(trace.Trace) + fmt.Println("-----") + fmt.Println(trace.AccountTrace) + fmt.Println(trace.StorageTrace) select { case <-time.After(500 * time.Millisecond): diff --git a/consensus/dev/dev.go b/consensus/dev/dev.go index 1612cb2f2e..f03d952961 100644 --- a/consensus/dev/dev.go +++ b/consensus/dev/dev.go @@ -199,7 +199,7 @@ func (d *Dev) writeNewBlock(parent *types.Header) error { } if err := ioutil.WriteFile( - filepath.Join(d.dataDir, fmt.Sprintf("trace_%d", header.Number)), raw, 0600); err != nil { + filepath.Join(d.dataDir, fmt.Sprintf("trace_%d", header.Number))+".json", raw, 0600); err != nil { panic(err) } } diff --git a/server/proto/system.pb.go b/server/proto/system.pb.go index 890272cb0b..1ecee0869e 100644 --- a/server/proto/system.pb.go +++ b/server/proto/system.pb.go @@ -78,7 +78,8 @@ type GetTraceResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Trace map[string]string `protobuf:"bytes,1,rep,name=trace,proto3" json:"trace,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + AccountTrace map[string]string `protobuf:"bytes,1,rep,name=accountTrace,proto3" json:"accountTrace,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + StorageTrace map[string]string `protobuf:"bytes,2,rep,name=storageTrace,proto3" json:"storageTrace,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *GetTraceResponse) Reset() { @@ -113,9 +114,16 @@ func (*GetTraceResponse) Descriptor() ([]byte, []int) { return file_server_proto_system_proto_rawDescGZIP(), []int{1} } -func (x *GetTraceResponse) GetTrace() map[string]string { +func (x *GetTraceResponse) GetAccountTrace() map[string]string { if x != nil { - return x.Trace + return x.AccountTrace + } + return nil +} + +func (x *GetTraceResponse) GetStorageTrace() map[string]string { + if x != nil { + return x.StorageTrace } return nil } @@ -730,7 +738,7 @@ type BlockchainEvent_Header struct { func (x *BlockchainEvent_Header) Reset() { *x = BlockchainEvent_Header{} if protoimpl.UnsafeEnabled { - mi := &file_server_proto_system_proto_msgTypes[14] + mi := &file_server_proto_system_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -743,7 +751,7 @@ func (x *BlockchainEvent_Header) String() string { func (*BlockchainEvent_Header) ProtoMessage() {} func (x *BlockchainEvent_Header) ProtoReflect() protoreflect.Message { - mi := &file_server_proto_system_proto_msgTypes[14] + mi := &file_server_proto_system_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -785,7 +793,7 @@ type ServerStatus_Block struct { func (x *ServerStatus_Block) Reset() { *x = ServerStatus_Block{} if protoimpl.UnsafeEnabled { - mi := &file_server_proto_system_proto_msgTypes[15] + mi := &file_server_proto_system_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -798,7 +806,7 @@ func (x *ServerStatus_Block) String() string { func (*ServerStatus_Block) ProtoMessage() {} func (x *ServerStatus_Block) ProtoReflect() protoreflect.Message { - mi := &file_server_proto_system_proto_msgTypes[15] + mi := &file_server_proto_system_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -837,99 +845,109 @@ var file_server_proto_system_proto_rawDesc = []byte{ 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x29, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x83, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, - 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, - 0x74, 0x72, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x74, 0x72, - 0x61, 0x63, 0x65, 0x1a, 0x38, 0x0a, 0x0a, 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaf, 0x01, - 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x30, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, 0x61, 0x64, - 0x64, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x1a, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, - 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, - 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, - 0xc3, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x65, - 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x65, 0x6e, - 0x65, 0x73, 0x69, 0x73, 0x12, 0x30, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x07, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, 0x64, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, 0x64, 0x72, - 0x1a, 0x33, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x4a, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, - 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, - 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, - 0x73, 0x22, 0x21, 0x0a, 0x0f, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x22, 0x2c, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x33, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, - 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2e, 0x0a, - 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x23, 0x0a, - 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x22, 0x33, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, - 0x74, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, - 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xc4, 0x03, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x12, 0x35, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x10, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x54, - 0x72, 0x61, 0x63, 0x65, 0x12, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x35, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x12, 0x13, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, - 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x65, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, - 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, - 0x3c, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x31, 0x2e, - 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, - 0x06, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x42, 0x0f, 0x5a, - 0x0d, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xac, 0x02, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0c, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, + 0x61, 0x67, 0x65, 0x54, 0x72, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x72, 0x61, 0x63, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x1a, 0x3f, 0x0a, 0x11, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3f, 0x0a, 0x11, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaf, 0x01, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x61, 0x64, + 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x07, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x64, 0x1a, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0xc3, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x30, 0x0a, + 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, + 0x18, 0x0a, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, 0x64, 0x72, 0x1a, 0x33, 0x0a, 0x05, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x4a, + 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x22, 0x21, 0x0a, 0x0f, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2c, 0x0a, + 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x50, + 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x33, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, + 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2e, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, + 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x23, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x33, 0x0a, 0x0d, 0x45, + 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, + 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, + 0x22, 0x5d, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, + 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x02, 0x74, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, + 0xc4, 0x03, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x35, 0x0a, 0x09, 0x47, 0x65, + 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x10, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, 0x13, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x41, 0x64, 0x64, 0x12, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, + 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3a, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0b, 0x50, + 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x09, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x12, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x42, 0x0f, 0x5a, 0x0d, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -944,7 +962,7 @@ func file_server_proto_system_proto_rawDescGZIP() []byte { return file_server_proto_system_proto_rawDescData } -var file_server_proto_system_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_server_proto_system_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_server_proto_system_proto_goTypes = []interface{}{ (*GetTraceRequest)(nil), // 0: v1.GetTraceRequest (*GetTraceResponse)(nil), // 1: v1.GetTraceResponse @@ -959,38 +977,40 @@ var file_server_proto_system_proto_goTypes = []interface{}{ (*BlockResponse)(nil), // 10: v1.BlockResponse (*ExportRequest)(nil), // 11: v1.ExportRequest (*ExportEvent)(nil), // 12: v1.ExportEvent - nil, // 13: v1.GetTraceResponse.TraceEntry - (*BlockchainEvent_Header)(nil), // 14: v1.BlockchainEvent.Header - (*ServerStatus_Block)(nil), // 15: v1.ServerStatus.Block - (*empty.Empty)(nil), // 16: google.protobuf.Empty + nil, // 13: v1.GetTraceResponse.AccountTraceEntry + nil, // 14: v1.GetTraceResponse.StorageTraceEntry + (*BlockchainEvent_Header)(nil), // 15: v1.BlockchainEvent.Header + (*ServerStatus_Block)(nil), // 16: v1.ServerStatus.Block + (*empty.Empty)(nil), // 17: google.protobuf.Empty } var file_server_proto_system_proto_depIdxs = []int32{ - 13, // 0: v1.GetTraceResponse.trace:type_name -> v1.GetTraceResponse.TraceEntry - 14, // 1: v1.BlockchainEvent.added:type_name -> v1.BlockchainEvent.Header - 14, // 2: v1.BlockchainEvent.removed:type_name -> v1.BlockchainEvent.Header - 15, // 3: v1.ServerStatus.current:type_name -> v1.ServerStatus.Block - 4, // 4: v1.PeersListResponse.peers:type_name -> v1.Peer - 16, // 5: v1.System.GetStatus:input_type -> google.protobuf.Empty - 0, // 6: v1.System.GetTrace:input_type -> v1.GetTraceRequest - 5, // 7: v1.System.PeersAdd:input_type -> v1.PeersAddRequest - 16, // 8: v1.System.PeersList:input_type -> google.protobuf.Empty - 7, // 9: v1.System.PeersStatus:input_type -> v1.PeersStatusRequest - 16, // 10: v1.System.Subscribe:input_type -> google.protobuf.Empty - 9, // 11: v1.System.BlockByNumber:input_type -> v1.BlockByNumberRequest - 11, // 12: v1.System.Export:input_type -> v1.ExportRequest - 3, // 13: v1.System.GetStatus:output_type -> v1.ServerStatus - 1, // 14: v1.System.GetTrace:output_type -> v1.GetTraceResponse - 6, // 15: v1.System.PeersAdd:output_type -> v1.PeersAddResponse - 8, // 16: v1.System.PeersList:output_type -> v1.PeersListResponse - 4, // 17: v1.System.PeersStatus:output_type -> v1.Peer - 2, // 18: v1.System.Subscribe:output_type -> v1.BlockchainEvent - 10, // 19: v1.System.BlockByNumber:output_type -> v1.BlockResponse - 12, // 20: v1.System.Export:output_type -> v1.ExportEvent - 13, // [13:21] is the sub-list for method output_type - 5, // [5:13] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 13, // 0: v1.GetTraceResponse.accountTrace:type_name -> v1.GetTraceResponse.AccountTraceEntry + 14, // 1: v1.GetTraceResponse.storageTrace:type_name -> v1.GetTraceResponse.StorageTraceEntry + 15, // 2: v1.BlockchainEvent.added:type_name -> v1.BlockchainEvent.Header + 15, // 3: v1.BlockchainEvent.removed:type_name -> v1.BlockchainEvent.Header + 16, // 4: v1.ServerStatus.current:type_name -> v1.ServerStatus.Block + 4, // 5: v1.PeersListResponse.peers:type_name -> v1.Peer + 17, // 6: v1.System.GetStatus:input_type -> google.protobuf.Empty + 0, // 7: v1.System.GetTrace:input_type -> v1.GetTraceRequest + 5, // 8: v1.System.PeersAdd:input_type -> v1.PeersAddRequest + 17, // 9: v1.System.PeersList:input_type -> google.protobuf.Empty + 7, // 10: v1.System.PeersStatus:input_type -> v1.PeersStatusRequest + 17, // 11: v1.System.Subscribe:input_type -> google.protobuf.Empty + 9, // 12: v1.System.BlockByNumber:input_type -> v1.BlockByNumberRequest + 11, // 13: v1.System.Export:input_type -> v1.ExportRequest + 3, // 14: v1.System.GetStatus:output_type -> v1.ServerStatus + 1, // 15: v1.System.GetTrace:output_type -> v1.GetTraceResponse + 6, // 16: v1.System.PeersAdd:output_type -> v1.PeersAddResponse + 8, // 17: v1.System.PeersList:output_type -> v1.PeersListResponse + 4, // 18: v1.System.PeersStatus:output_type -> v1.Peer + 2, // 19: v1.System.Subscribe:output_type -> v1.BlockchainEvent + 10, // 20: v1.System.BlockByNumber:output_type -> v1.BlockResponse + 12, // 21: v1.System.Export:output_type -> v1.ExportEvent + 14, // [14:22] is the sub-list for method output_type + 6, // [6:14] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name } func init() { file_server_proto_system_proto_init() } @@ -1155,7 +1175,7 @@ func file_server_proto_system_proto_init() { return nil } } - file_server_proto_system_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockchainEvent_Header); i { case 0: return &v.state @@ -1167,7 +1187,7 @@ func file_server_proto_system_proto_init() { return nil } } - file_server_proto_system_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServerStatus_Block); i { case 0: return &v.state @@ -1186,7 +1206,7 @@ func file_server_proto_system_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_server_proto_system_proto_rawDesc, NumEnums: 0, - NumMessages: 16, + NumMessages: 17, NumExtensions: 0, NumServices: 1, }, diff --git a/server/proto/system.proto b/server/proto/system.proto index f71ab09106..ca73293343 100644 --- a/server/proto/system.proto +++ b/server/proto/system.proto @@ -36,7 +36,8 @@ message GetTraceRequest { } message GetTraceResponse { - map trace = 1; + map accountTrace = 1; + map storageTrace = 2; } message BlockchainEvent { diff --git a/server/system_service.go b/server/system_service.go index 2e96bfec80..130f6911ad 100644 --- a/server/system_service.go +++ b/server/system_service.go @@ -26,21 +26,19 @@ type systemService struct { func (s *systemService) GetTrace(ctx context.Context, req *proto.GetTraceRequest) (*proto.GetTraceResponse, error) { path := filepath.Join(s.server.config.DataDir, "consensus") - data, err := ioutil.ReadFile(filepath.Join(path, fmt.Sprintf("trace_%d", req.Number))) + data, err := ioutil.ReadFile(filepath.Join(path, fmt.Sprintf("trace_%d", req.Number)) + ".json") if err != nil { return nil, err } - var traceData struct { - Trace map[string]string `json:"trace"` - } - - if err := json.Unmarshal(data, &traceData); err != nil { + var trace *types.Trace + if err := json.Unmarshal(data, &trace); err != nil { return nil, err } resp := &proto.GetTraceResponse{ - Trace: traceData.Trace, + AccountTrace: trace.AccountTrie, + StorageTrace: trace.StorageTrie, } return resp, nil diff --git a/state/executor.go b/state/executor.go index f241a88176..8a56dafc14 100644 --- a/state/executor.go +++ b/state/executor.go @@ -301,10 +301,10 @@ func (t *Transition) Write(txn *types.Transaction) error { // Commit commits the final result func (t *Transition) Commit() (Snapshot, *types.Trace, types.Hash) { - // pre-commit op + + // pre-commit op (TODO: Remove, only for zero tests) targetAddr := types.Address{} targetAddr[t.ctx.Number/20] = 1 - t.state.AddBalance(targetAddr, big.NewInt(10)) objs := t.state.Commit(t.config.EIP155) diff --git a/state/immutable-trie/snapshot.go b/state/immutable-trie/snapshot.go index 60825bc982..0383d5b0af 100644 --- a/state/immutable-trie/snapshot.go +++ b/state/immutable-trie/snapshot.go @@ -10,13 +10,29 @@ import ( ) type Snapshot struct { - state *State - trie *Trie - tracer *tracer + state *State + trie *Trie + + // tracers is the list of tracers executed, one for each trie + tracers []*tracer + + // trace is the object that holds the traces + trace *types.Trace } var emptyStateHash = types.StringToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") +func (s *Snapshot) createTracer(isAccountTrie bool) *tracer { + if s.tracers == nil { + s.tracers = []*tracer{} + } + + tr := &tracer{isAccountTrie: isAccountTrie, trace: s.trace} + s.tracers = append(s.tracers, tr) + + return tr +} + func (s *Snapshot) GetStorage(addr types.Address, root types.Hash, rawkey types.Hash) types.Hash { var ( err error @@ -32,7 +48,7 @@ func (s *Snapshot) GetStorage(addr types.Address, root types.Hash, rawkey types. } } - trie.tracer = s.tracer + trie.tracer = s.createTracer(false) key := crypto.Keccak256(rawkey.Bytes()) @@ -58,7 +74,7 @@ func (s *Snapshot) GetStorage(addr types.Address, root types.Hash, rawkey types. func (s *Snapshot) GetAccount(addr types.Address) (*state.Account, error) { key := crypto.Keccak256(addr.Bytes()) - s.trie.tracer = s.tracer + s.trie.tracer = s.createTracer(true) data, ok := s.trie.Get(key) if !ok { @@ -80,19 +96,24 @@ func (s *Snapshot) GetCode(hash types.Hash) ([]byte, bool) { func (s *Snapshot) Commit(objs []*state.Object) (state.Snapshot, *types.Trace, []byte) { trie, root := s.trie.Commit(objs) - s.tracer.Proof() + for _, t := range s.tracers { + t.Proof() + } - return &Snapshot{trie: trie, state: s.state}, &types.Trace{Trace: s.tracer.Traces()}, root + return &Snapshot{trie: trie, state: s.state}, s.trace, root } type tracer struct { - nodes []Node + // isAccountTrie represents whether the trace is in an + // acount or storage trie + isAccountTrie bool - traces map[string]string -} + // nodes is the list of nodes from the partial merkle trie + // accessed during the trace + nodes []Node -func (t *tracer) Traces() map[string]string { - return t.traces + // trace is the reference object to dump the traces + trace *types.Trace } func (t *tracer) Trace(n Node) { @@ -120,12 +141,23 @@ func (t *tracer) Proof() { } func (t *tracer) Put(k, v []byte) { - if t.traces == nil { - t.traces = map[string]string{} - } - kStr := hex.EncodeToString(k) - if _, ok := t.traces[kStr]; !ok { - t.traces[kStr] = hex.EncodeToString(v) + + if t.isAccountTrie { + if t.trace.AccountTrie == nil { + t.trace.AccountTrie = map[string]string{} + } + + if _, ok := t.trace.AccountTrie[kStr]; !ok { + t.trace.AccountTrie[kStr] = hex.EncodeToString(v) + } + } else { + if t.trace.StorageTrie == nil { + t.trace.StorageTrie = map[string]string{} + } + + if _, ok := t.trace.StorageTrie[kStr]; !ok { + t.trace.StorageTrie[kStr] = hex.EncodeToString(v) + } } } diff --git a/state/immutable-trie/state.go b/state/immutable-trie/state.go index a5f8a5233a..4fcb392292 100644 --- a/state/immutable-trie/state.go +++ b/state/immutable-trie/state.go @@ -26,7 +26,7 @@ func NewState(storage Storage) *State { } func (s *State) NewSnapshot() state.Snapshot { - return &Snapshot{state: s, tracer: &tracer{}, trie: s.newTrie()} + return &Snapshot{state: s, trace: &types.Trace{}, trie: s.newTrie()} } func (s *State) NewSnapshotAt(root types.Hash) (state.Snapshot, error) { @@ -35,7 +35,7 @@ func (s *State) NewSnapshotAt(root types.Hash) (state.Snapshot, error) { return nil, err } - return &Snapshot{state: s, tracer: &tracer{}, trie: t}, nil + return &Snapshot{state: s, trace: &types.Trace{}, trie: t}, nil } func (s *State) newTrie() *Trie { diff --git a/state/immutable-trie/trie_test.go b/state/immutable-trie/trie_test.go index 8078054e92..d39314a452 100644 --- a/state/immutable-trie/trie_test.go +++ b/state/immutable-trie/trie_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/0xPolygon/polygon-edge/state" + "github.com/0xPolygon/polygon-edge/types" "github.com/umbracle/fastrlp" ) @@ -20,12 +21,16 @@ func TestTrie_Proof(t *testing.T) { txn.Insert([]byte{0x1, 0x2}, val) txn.Insert([]byte{0x1, 0x1}, val) - tracer := &tracer{} + tracer := &tracer{ + isAccountTrie: true, + trace: &types.Trace{}, + } txn.tracer = tracer txn.Hash() txn.Lookup([]byte{0x1, 0x2}) tracer.Proof() - fmt.Println(tracer.Traces()) + fmt.Println(tracer.trace.AccountTrie) + fmt.Println(tracer.trace.StorageTrie) } diff --git a/types/types.go b/types/types.go index 8279cf8cc3..b1f25d6d51 100644 --- a/types/types.go +++ b/types/types.go @@ -155,5 +155,6 @@ var ( ) type Trace struct { - Trace map[string]string + AccountTrie map[string]string `json:"accountTrie"` + StorageTrie map[string]string `json:"storageTrie"` } From 432748199d9ab3c3baee44d8e1b9b79daae6f86a Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Wed, 8 Feb 2023 09:07:20 +0100 Subject: [PATCH 07/24] Add ibft backend support for zero --- consensus/ibft/consensus_backend.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/consensus/ibft/consensus_backend.go b/consensus/ibft/consensus_backend.go index a1bcf3fe76..e72d4d534f 100644 --- a/consensus/ibft/consensus_backend.go +++ b/consensus/ibft/consensus_backend.go @@ -2,8 +2,11 @@ package ibft import ( "context" + "encoding/json" "fmt" + "io/ioutil" "math" + "path/filepath" "time" "github.com/0xPolygon/go-ibft/messages" @@ -184,7 +187,21 @@ func (i *backendIBFT) buildBlock(parent *types.Header) (*types.Block, error) { return nil, err } - _, _, root := transition.Commit() + _, trace, root := transition.Commit() + + // write the trace + { + raw, err := json.Marshal(trace) + if err != nil { + panic(err) + } + + if err := ioutil.WriteFile( + filepath.Join(i.config.Path, fmt.Sprintf("trace_%d", header.Number))+".json", raw, 0600); err != nil { + panic(err) + } + } + header.StateRoot = root header.GasUsed = transition.TotalGas() From a630aa7182eb37657b285bcc85305e66a320f79c Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Tue, 7 Mar 2023 14:04:20 +0100 Subject: [PATCH 08/24] Add journaling to generate zero traces --- state/txn.go | 154 +++++++++++++++++++++++++++++++++++++++++++++- state/txn_test.go | 73 ++++++++++++++++++++++ 2 files changed, 225 insertions(+), 2 deletions(-) diff --git a/state/txn.go b/state/txn.go index 4084809822..339925c9ab 100644 --- a/state/txn.go +++ b/state/txn.go @@ -1,6 +1,9 @@ package state import ( + "bytes" + "encoding/json" + "fmt" "math/big" iradix "github.com/hashicorp/go-immutable-radix" @@ -34,6 +37,9 @@ type Txn struct { snapshots []*iradix.Tree txn *iradix.Txn codeCache *lru.Cache + + // tracing + journal []*journalEntry } func NewTxn(snapshot Snapshot) *Txn { @@ -54,6 +60,7 @@ func newTxn(snapshot readSnapshot) *Txn { snapshots: []*iradix.Tree{}, txn: i.Txn(), codeCache: codeCache, + journal: []*journalEntry{}, } } @@ -77,6 +84,65 @@ func (txn *Txn) RevertToSnapshot(id int) { txn.txn = tree.Txn() } +func (txn *Txn) getCompactJournal() map[types.Address]*journalEntry { + // Instead of creating a new object to represent the aggregate on how + // an account has changed during the compaction, we piggyback the same + // journalEntry object for now. + res := map[types.Address]*journalEntry{} + + for _, entry := range txn.journal { + fmt.Println("--") + entry.printJSON() + + obj, ok := res[entry.Addr] + if !ok { + obj = &journalEntry{} + res[entry.Addr] = obj + } + + obj.merge(entry) + + obj.printJSON() + } + + // reset the journal + txn.journal = txn.journal[:0] + + return res +} + +func (txn *Txn) addJournalEntry(j *journalEntry) { + txn.journal = append(txn.journal, j) +} + +const ( + nonceChange = "nonce" + codeChange = "code" + balanceChange = "balance" +) + +func (txn *Txn) trackAccountChange(addr types.Address, changeType string, object *StateObject) { + entry := &journalEntry{ + Addr: addr, + } + + if changeType == nonceChange { + // the node has changed + entry.Nonce = &object.Account.Nonce + } else if changeType == codeChange { + // the code has been initialized + entry.Code = object.Code + } else if changeType == balanceChange { + // the balance has changed + entry.Balance = object.Account.Balance + } else { + // this is covered on unit tests + panic(fmt.Sprintf("BUG: Not expected change '%s'", changeType)) + } + + txn.addJournalEntry(entry) +} + // GetAccount returns an account func (txn *Txn) GetAccount(addr types.Address) (*Account, bool) { object, exists := txn.getStateObject(addr) @@ -138,11 +204,13 @@ func (txn *Txn) upsertAccount(addr types.Address, create bool, f func(object *St func (txn *Txn) AddSealingReward(addr types.Address, balance *big.Int) { txn.upsertAccount(addr, true, func(object *StateObject) { if object.Suicide { - *object = *newStateObject(txn) + *object = *newStateObject() object.Account.Balance.SetBytes(balance.Bytes()) } else { object.Account.Balance.Add(object.Account.Balance, balance) } + + txn.trackAccountChange(addr, balanceChange, object) }) } @@ -150,6 +218,8 @@ func (txn *Txn) AddSealingReward(addr types.Address, balance *big.Int) { func (txn *Txn) AddBalance(addr types.Address, balance *big.Int) { txn.upsertAccount(addr, true, func(object *StateObject) { object.Account.Balance.Add(object.Account.Balance, balance) + + txn.trackAccountChange(addr, balanceChange, object) }) } @@ -167,6 +237,8 @@ func (txn *Txn) SubBalance(addr types.Address, amount *big.Int) error { txn.upsertAccount(addr, true, func(object *StateObject) { object.Account.Balance.Sub(object.Account.Balance, amount) + + txn.trackAccountChange(addr, balanceChange, object) }) return nil @@ -176,6 +248,8 @@ func (txn *Txn) SubBalance(addr types.Address, amount *big.Int) error { func (txn *Txn) SetBalance(addr types.Address, balance *big.Int) { txn.upsertAccount(addr, true, func(object *StateObject) { object.Account.Balance.SetBytes(balance.Bytes()) + + txn.trackAccountChange(addr, balanceChange, object) }) } @@ -316,6 +390,13 @@ func (txn *Txn) SetState( } else { object.Txn.Insert(key.Bytes(), value.Bytes()) } + + txn.addJournalEntry(&journalEntry{ + Addr: addr, + Storage: map[types.Hash]types.Hash{ + key: value, + }, + }) }) } @@ -348,6 +429,8 @@ func (txn *Txn) GetState(addr types.Address, key types.Hash) types.Hash { func (txn *Txn) IncrNonce(addr types.Address) { txn.upsertAccount(addr, true, func(object *StateObject) { object.Account.Nonce++ + + txn.trackAccountChange(addr, nonceChange, object) }) } @@ -355,6 +438,8 @@ func (txn *Txn) IncrNonce(addr types.Address) { func (txn *Txn) SetNonce(addr types.Address, nonce uint64) { txn.upsertAccount(addr, true, func(object *StateObject) { object.Account.Nonce = nonce + + txn.trackAccountChange(addr, nonceChange, object) }) } @@ -376,6 +461,8 @@ func (txn *Txn) SetCode(addr types.Address, code []byte) { object.Account.CodeHash = crypto.Keccak256(code) object.DirtyCode = true object.Code = code + + txn.trackAccountChange(addr, codeChange, object) }) } @@ -425,6 +512,11 @@ func (txn *Txn) Suicide(addr types.Address) bool { } else { suicided = true object.Suicide = true + + txn.addJournalEntry(&journalEntry{ + Addr: addr, + Suicide: &suicided, + }) } if object != nil { object.Account.Balance = new(big.Int) @@ -506,7 +598,7 @@ func (txn *Txn) Empty(addr types.Address) bool { return obj.Empty() } -func newStateObject(txn *Txn) *StateObject { +func newStateObject() *StateObject { return &StateObject{ Account: &Account{ Balance: big.NewInt(0), @@ -618,3 +710,61 @@ func (txn *Txn) Commit(deleteEmptyObjects bool) []*Object { return objs } + +type journalEntry struct { + // Addr is the address of the account affected by the + // journal change + Addr types.Address `json:"address"` + + // Balance tracks changes in the account Balance + Balance *big.Int `json:"balance,omitempty"` + + // Nonce tracks changes in the account Nonce + Nonce *uint64 `json:"nonce,omitempty"` + + // Storage track changes in the storage + Storage map[types.Hash]types.Hash `json:"storage,omitempty"` + + // Code tracks the initialization of the contract Code + Code []byte `json:"code,omitempty"` + + // Suicide tracks whether the contract has been self destructed + Suicide *bool `json:"suicide,omitempty"` +} + +func (j *journalEntry) printJSON() { + data, err := json.Marshal(j) + if err != nil { + panic(err) + } + + fmt.Println(string(data)) +} + +func (j *journalEntry) merge(jj *journalEntry) { + if jj.Nonce != nil && jj.Nonce != j.Nonce { + j.Nonce = jj.Nonce + } + + if jj.Balance != nil && jj.Balance != j.Balance { + j.Balance = jj.Balance + } + + if jj.Storage != nil { + if j.Storage == nil { + j.Storage = map[types.Hash]types.Hash{} + } + + for k, v := range jj.Storage { + j.Storage[k] = v + } + } + + if jj.Code != nil && !bytes.Equal(jj.Code, j.Code) { + j.Code = jj.Code + } + + if jj.Suicide != nil && jj.Suicide != j.Suicide { + j.Suicide = jj.Suicide + } +} diff --git a/state/txn_test.go b/state/txn_test.go index d1ff74b519..7cadfa7a36 100644 --- a/state/txn_test.go +++ b/state/txn_test.go @@ -7,6 +7,7 @@ import ( "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type mockSnapshot struct { @@ -66,3 +67,75 @@ func TestSnapshotUpdateData(t *testing.T) { txn.RevertToSnapshot(ss) assert.Equal(t, hash1, txn.GetState(addr1, hash1)) } + +func TestTxn_TracesCompaction(t *testing.T) { + txn := newTestTxn(defaultPreState) + + addr := types.Address{} + + txn.SetBalance(addr, big.NewInt(1)) + txn.SetBalance(addr, big.NewInt(2)) // updates + + txn.SetNonce(addr, 1) + txn.SetNonce(addr, 2) // updates + + oneHash := types.Hash{0x1} + + txn.SetState(addr, types.ZeroHash, types.ZeroHash) + txn.SetState(addr, types.ZeroHash, oneHash) // updates + txn.SetState(addr, oneHash, types.ZeroHash) + + trace := txn.getCompactJournal() + require.Len(t, trace, 1) + + nonce := uint64(2) + + require.Equal(t, trace[addr], &journalEntry{ + Balance: big.NewInt(2), + Nonce: &nonce, + Storage: map[types.Hash]types.Hash{ + types.ZeroHash: oneHash, + oneHash: types.ZeroHash, + }, + }) +} + +func TestJournalEntry_Merge(t *testing.T) { + one := uint64(1) + boolTrue := true + + entryAllSet := func() *journalEntry { + // use a function because the merge function + // modifies the caller and the test would + // have side effects. + return &journalEntry{ + Nonce: &one, + Balance: big.NewInt(1), + Storage: map[types.Hash]types.Hash{ + types.ZeroHash: types.ZeroHash, + }, + Code: []byte{0x1}, + Suicide: &boolTrue, + } + } + + cases := []struct { + a, b, c *journalEntry // a.merge(b) = c + }{ + { + &journalEntry{}, + entryAllSet(), + entryAllSet(), + }, + { + entryAllSet(), + &journalEntry{}, + entryAllSet(), + }, + } + + for _, c := range cases { + c.a.merge(c.b) + require.Equal(t, c.c, c.a) + } +} From 4349eca69de38ca315b447357d416f7942015bc6 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Wed, 8 Mar 2023 10:05:37 +0100 Subject: [PATCH 09/24] Add touched trace --- state/txn.go | 20 ++++++++++++++++++-- state/txn_test.go | 8 ++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/state/txn.go b/state/txn.go index 339925c9ab..a38a51a843 100644 --- a/state/txn.go +++ b/state/txn.go @@ -502,6 +502,12 @@ func (txn *Txn) GetCodeHash(addr types.Address) types.Hash { return types.BytesToHash(object.Account.CodeHash) } +func boolTruePtr() *bool { + t := true + + return &t +} + // Suicide marks the given account as suicided func (txn *Txn) Suicide(addr types.Address) bool { var suicided bool @@ -515,7 +521,7 @@ func (txn *Txn) Suicide(addr types.Address) bool { txn.addJournalEntry(&journalEntry{ Addr: addr, - Suicide: &suicided, + Suicide: boolTruePtr(), }) } if object != nil { @@ -577,7 +583,10 @@ func (txn *Txn) GetCommittedState(addr types.Address, key types.Hash) types.Hash func (txn *Txn) TouchAccount(addr types.Address) { txn.upsertAccount(addr, true, func(obj *StateObject) { - + txn.addJournalEntry(&journalEntry{ + Addr: addr, + Touched: boolTruePtr(), + }) }) } @@ -730,6 +739,9 @@ type journalEntry struct { // Suicide tracks whether the contract has been self destructed Suicide *bool `json:"suicide,omitempty"` + + // Touched tracks whether the account has been touched/created + Touched *bool `json:"touched,omitempty"` } func (j *journalEntry) printJSON() { @@ -767,4 +779,8 @@ func (j *journalEntry) merge(jj *journalEntry) { if jj.Suicide != nil && jj.Suicide != j.Suicide { j.Suicide = jj.Suicide } + + if jj.Touched != nil && jj.Touched != j.Touched { + j.Touched = jj.Touched + } } diff --git a/state/txn_test.go b/state/txn_test.go index 7cadfa7a36..df8a6659b8 100644 --- a/state/txn_test.go +++ b/state/txn_test.go @@ -85,6 +85,9 @@ func TestTxn_TracesCompaction(t *testing.T) { txn.SetState(addr, types.ZeroHash, oneHash) // updates txn.SetState(addr, oneHash, types.ZeroHash) + txn.TouchAccount(addr) + require.Len(t, txn.journal, 8) + trace := txn.getCompactJournal() require.Len(t, trace, 1) @@ -97,12 +100,12 @@ func TestTxn_TracesCompaction(t *testing.T) { types.ZeroHash: oneHash, oneHash: types.ZeroHash, }, + Touched: boolTruePtr(), }) } func TestJournalEntry_Merge(t *testing.T) { one := uint64(1) - boolTrue := true entryAllSet := func() *journalEntry { // use a function because the merge function @@ -115,7 +118,8 @@ func TestJournalEntry_Merge(t *testing.T) { types.ZeroHash: types.ZeroHash, }, Code: []byte{0x1}, - Suicide: &boolTrue, + Suicide: boolTruePtr(), + Touched: boolTruePtr(), } } From d3d6d1823bcc7e8ceddc6f0a688a0d1dd9ce6aec Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Wed, 8 Mar 2023 10:07:46 +0100 Subject: [PATCH 10/24] Remove json prints --- state/txn.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/state/txn.go b/state/txn.go index a38a51a843..3c5fc0426f 100644 --- a/state/txn.go +++ b/state/txn.go @@ -2,7 +2,6 @@ package state import ( "bytes" - "encoding/json" "fmt" "math/big" @@ -91,9 +90,6 @@ func (txn *Txn) getCompactJournal() map[types.Address]*journalEntry { res := map[types.Address]*journalEntry{} for _, entry := range txn.journal { - fmt.Println("--") - entry.printJSON() - obj, ok := res[entry.Addr] if !ok { obj = &journalEntry{} @@ -101,8 +97,6 @@ func (txn *Txn) getCompactJournal() map[types.Address]*journalEntry { } obj.merge(entry) - - obj.printJSON() } // reset the journal @@ -744,15 +738,6 @@ type journalEntry struct { Touched *bool `json:"touched,omitempty"` } -func (j *journalEntry) printJSON() { - data, err := json.Marshal(j) - if err != nil { - panic(err) - } - - fmt.Println(string(data)) -} - func (j *journalEntry) merge(jj *journalEntry) { if jj.Nonce != nil && jj.Nonce != j.Nonce { j.Nonce = jj.Nonce From 6b0ca1a94763daa8aaf0bd29f0f3a41a1ee56660 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Wed, 8 Mar 2023 11:04:05 +0100 Subject: [PATCH 11/24] Move state delta to types --- command/sidecar/sidecar.go | 13 +- consensus/dev/dev.go | 1 + consensus/ibft/consensus_backend.go | 1 + server/proto/system.pb.go | 278 +++++++++++++--------------- server/proto/system.proto | 3 +- server/system_service.go | 9 +- state/executor.go | 17 +- state/txn.go | 79 ++------ state/txn_test.go | 14 +- types/types.go | 75 ++++++++ 10 files changed, 247 insertions(+), 243 deletions(-) diff --git a/command/sidecar/sidecar.go b/command/sidecar/sidecar.go index d5c1ca9a05..1597ad3afb 100644 --- a/command/sidecar/sidecar.go +++ b/command/sidecar/sidecar.go @@ -2,12 +2,14 @@ package sidecar import ( "context" + "encoding/json" "fmt" "time" "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/helper" "github.com/0xPolygon/polygon-edge/server/proto" + "github.com/0xPolygon/polygon-edge/types" "github.com/spf13/cobra" "google.golang.org/protobuf/types/known/emptypb" ) @@ -69,14 +71,19 @@ func (s *sidecar) run() { continue } - trace, err := s.clt.GetTrace(context.Background(), &proto.GetTraceRequest{Number: uint64(status.Current.Number)}) + traceResp, err := s.clt.GetTrace(context.Background(), &proto.GetTraceRequest{Number: uint64(status.Current.Number)}) if err != nil { panic(err) } + var trace *types.Trace + if err := json.Unmarshal(traceResp.Trace, &trace); err != nil { + panic(err) + } + fmt.Println("-----") - fmt.Println(trace.AccountTrace) - fmt.Println(trace.StorageTrace) + fmt.Println(trace.AccountTrie) + fmt.Println(trace.StorageTrie) select { case <-time.After(500 * time.Millisecond): diff --git a/consensus/dev/dev.go b/consensus/dev/dev.go index f03d952961..c2555c73b5 100644 --- a/consensus/dev/dev.go +++ b/consensus/dev/dev.go @@ -190,6 +190,7 @@ func (d *Dev) writeNewBlock(parent *types.Header) error { // Commit the changes _, trace, root := transition.Commit() + trace.ParentStateRoot = parent.StateRoot // write the trace { diff --git a/consensus/ibft/consensus_backend.go b/consensus/ibft/consensus_backend.go index e72d4d534f..2d653d9288 100644 --- a/consensus/ibft/consensus_backend.go +++ b/consensus/ibft/consensus_backend.go @@ -188,6 +188,7 @@ func (i *backendIBFT) buildBlock(parent *types.Header) (*types.Block, error) { } _, trace, root := transition.Commit() + trace.ParentStateRoot = parent.StateRoot // write the trace { diff --git a/server/proto/system.pb.go b/server/proto/system.pb.go index 1ecee0869e..b777a1378b 100644 --- a/server/proto/system.pb.go +++ b/server/proto/system.pb.go @@ -78,8 +78,7 @@ type GetTraceResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - AccountTrace map[string]string `protobuf:"bytes,1,rep,name=accountTrace,proto3" json:"accountTrace,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - StorageTrace map[string]string `protobuf:"bytes,2,rep,name=storageTrace,proto3" json:"storageTrace,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Trace []byte `protobuf:"bytes,1,opt,name=trace,proto3" json:"trace,omitempty"` } func (x *GetTraceResponse) Reset() { @@ -114,16 +113,9 @@ func (*GetTraceResponse) Descriptor() ([]byte, []int) { return file_server_proto_system_proto_rawDescGZIP(), []int{1} } -func (x *GetTraceResponse) GetAccountTrace() map[string]string { +func (x *GetTraceResponse) GetTrace() []byte { if x != nil { - return x.AccountTrace - } - return nil -} - -func (x *GetTraceResponse) GetStorageTrace() map[string]string { - if x != nil { - return x.StorageTrace + return x.Trace } return nil } @@ -738,7 +730,7 @@ type BlockchainEvent_Header struct { func (x *BlockchainEvent_Header) Reset() { *x = BlockchainEvent_Header{} if protoimpl.UnsafeEnabled { - mi := &file_server_proto_system_proto_msgTypes[15] + mi := &file_server_proto_system_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -751,7 +743,7 @@ func (x *BlockchainEvent_Header) String() string { func (*BlockchainEvent_Header) ProtoMessage() {} func (x *BlockchainEvent_Header) ProtoReflect() protoreflect.Message { - mi := &file_server_proto_system_proto_msgTypes[15] + mi := &file_server_proto_system_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -793,7 +785,7 @@ type ServerStatus_Block struct { func (x *ServerStatus_Block) Reset() { *x = ServerStatus_Block{} if protoimpl.UnsafeEnabled { - mi := &file_server_proto_system_proto_msgTypes[16] + mi := &file_server_proto_system_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -806,7 +798,7 @@ func (x *ServerStatus_Block) String() string { func (*ServerStatus_Block) ProtoMessage() {} func (x *ServerStatus_Block) ProtoReflect() protoreflect.Message { - mi := &file_server_proto_system_proto_msgTypes[16] + mi := &file_server_proto_system_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -845,109 +837,93 @@ var file_server_proto_system_proto_rawDesc = []byte{ 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x29, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xac, 0x02, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, - 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x0c, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x61, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, 0x4a, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, - 0x61, 0x67, 0x65, 0x54, 0x72, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, 0x72, 0x61, 0x63, - 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x54, - 0x72, 0x61, 0x63, 0x65, 0x1a, 0x3f, 0x0a, 0x11, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, - 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3f, 0x0a, 0x11, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x54, 0x72, 0x61, 0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xaf, 0x01, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x61, 0x64, - 0x64, 0x65, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x07, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x64, 0x1a, 0x34, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0xc3, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x30, 0x0a, - 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x70, 0x32, 0x70, 0x41, 0x64, 0x64, 0x72, 0x1a, 0x33, 0x0a, 0x05, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, - 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x4a, - 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x22, 0x21, 0x0a, 0x0f, 0x50, 0x65, - 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2c, 0x0a, - 0x10, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x50, - 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x22, 0x33, 0x0a, 0x11, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, - 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x22, 0x2e, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, - 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x23, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x33, 0x0a, 0x0d, 0x45, - 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, - 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, - 0x22, 0x5d, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, - 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x02, 0x74, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x04, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, - 0xc4, 0x03, 0x0a, 0x06, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x35, 0x0a, 0x09, 0x47, 0x65, - 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x28, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, 0x72, + 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x72, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x74, 0x72, 0x61, 0x63, + 0x65, 0x22, 0xaf, 0x01, 0x0a, 0x0f, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x52, 0x05, 0x61, 0x64, 0x64, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, + 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x1a, 0x34, 0x0a, + 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, + 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, + 0x61, 0x73, 0x68, 0x22, 0xc3, 0x01, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x18, + 0x0a, 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x67, 0x65, 0x6e, 0x65, 0x73, 0x69, 0x73, 0x12, 0x30, 0x0a, 0x07, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x42, 0x6c, 0x6f, 0x63, + 0x6b, 0x52, 0x07, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x32, + 0x70, 0x41, 0x64, 0x64, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x32, 0x70, + 0x41, 0x64, 0x64, 0x72, 0x1a, 0x33, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x0a, + 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x22, 0x4a, 0x0a, 0x04, 0x50, 0x65, 0x65, + 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, + 0x61, 0x64, 0x64, 0x72, 0x73, 0x22, 0x21, 0x0a, 0x0f, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2c, 0x0a, 0x10, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x33, 0x0a, 0x11, + 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1e, 0x0a, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, + 0x73, 0x22, 0x2e, 0x0a, 0x14, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, + 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x22, 0x23, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x33, 0x0a, 0x0d, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, + 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x5d, 0x0a, 0x0b, 0x45, + 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, + 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, + 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02, 0x74, 0x6f, 0x12, 0x16, + 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, + 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xc4, 0x03, 0x0a, 0x06, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x35, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x10, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x35, 0x0a, 0x08, + 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x12, + 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, + 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3a, 0x0a, 0x09, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x10, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x35, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, 0x13, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x41, 0x64, 0x64, 0x12, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x41, - 0x64, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x65, 0x65, 0x72, 0x73, 0x41, 0x64, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3a, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x15, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0b, 0x50, - 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x08, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x09, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x13, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x12, 0x11, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x42, 0x0f, 0x5a, 0x0d, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x15, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x73, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x08, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x62, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x76, + 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, 0x79, 0x4e, 0x75, + 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x42, + 0x79, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, + 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x11, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, + 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, + 0x01, 0x42, 0x0f, 0x5a, 0x0d, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -962,7 +938,7 @@ func file_server_proto_system_proto_rawDescGZIP() []byte { return file_server_proto_system_proto_rawDescData } -var file_server_proto_system_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_server_proto_system_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_server_proto_system_proto_goTypes = []interface{}{ (*GetTraceRequest)(nil), // 0: v1.GetTraceRequest (*GetTraceResponse)(nil), // 1: v1.GetTraceResponse @@ -977,40 +953,36 @@ var file_server_proto_system_proto_goTypes = []interface{}{ (*BlockResponse)(nil), // 10: v1.BlockResponse (*ExportRequest)(nil), // 11: v1.ExportRequest (*ExportEvent)(nil), // 12: v1.ExportEvent - nil, // 13: v1.GetTraceResponse.AccountTraceEntry - nil, // 14: v1.GetTraceResponse.StorageTraceEntry - (*BlockchainEvent_Header)(nil), // 15: v1.BlockchainEvent.Header - (*ServerStatus_Block)(nil), // 16: v1.ServerStatus.Block - (*empty.Empty)(nil), // 17: google.protobuf.Empty + (*BlockchainEvent_Header)(nil), // 13: v1.BlockchainEvent.Header + (*ServerStatus_Block)(nil), // 14: v1.ServerStatus.Block + (*empty.Empty)(nil), // 15: google.protobuf.Empty } var file_server_proto_system_proto_depIdxs = []int32{ - 13, // 0: v1.GetTraceResponse.accountTrace:type_name -> v1.GetTraceResponse.AccountTraceEntry - 14, // 1: v1.GetTraceResponse.storageTrace:type_name -> v1.GetTraceResponse.StorageTraceEntry - 15, // 2: v1.BlockchainEvent.added:type_name -> v1.BlockchainEvent.Header - 15, // 3: v1.BlockchainEvent.removed:type_name -> v1.BlockchainEvent.Header - 16, // 4: v1.ServerStatus.current:type_name -> v1.ServerStatus.Block - 4, // 5: v1.PeersListResponse.peers:type_name -> v1.Peer - 17, // 6: v1.System.GetStatus:input_type -> google.protobuf.Empty - 0, // 7: v1.System.GetTrace:input_type -> v1.GetTraceRequest - 5, // 8: v1.System.PeersAdd:input_type -> v1.PeersAddRequest - 17, // 9: v1.System.PeersList:input_type -> google.protobuf.Empty - 7, // 10: v1.System.PeersStatus:input_type -> v1.PeersStatusRequest - 17, // 11: v1.System.Subscribe:input_type -> google.protobuf.Empty - 9, // 12: v1.System.BlockByNumber:input_type -> v1.BlockByNumberRequest - 11, // 13: v1.System.Export:input_type -> v1.ExportRequest - 3, // 14: v1.System.GetStatus:output_type -> v1.ServerStatus - 1, // 15: v1.System.GetTrace:output_type -> v1.GetTraceResponse - 6, // 16: v1.System.PeersAdd:output_type -> v1.PeersAddResponse - 8, // 17: v1.System.PeersList:output_type -> v1.PeersListResponse - 4, // 18: v1.System.PeersStatus:output_type -> v1.Peer - 2, // 19: v1.System.Subscribe:output_type -> v1.BlockchainEvent - 10, // 20: v1.System.BlockByNumber:output_type -> v1.BlockResponse - 12, // 21: v1.System.Export:output_type -> v1.ExportEvent - 14, // [14:22] is the sub-list for method output_type - 6, // [6:14] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 13, // 0: v1.BlockchainEvent.added:type_name -> v1.BlockchainEvent.Header + 13, // 1: v1.BlockchainEvent.removed:type_name -> v1.BlockchainEvent.Header + 14, // 2: v1.ServerStatus.current:type_name -> v1.ServerStatus.Block + 4, // 3: v1.PeersListResponse.peers:type_name -> v1.Peer + 15, // 4: v1.System.GetStatus:input_type -> google.protobuf.Empty + 0, // 5: v1.System.GetTrace:input_type -> v1.GetTraceRequest + 5, // 6: v1.System.PeersAdd:input_type -> v1.PeersAddRequest + 15, // 7: v1.System.PeersList:input_type -> google.protobuf.Empty + 7, // 8: v1.System.PeersStatus:input_type -> v1.PeersStatusRequest + 15, // 9: v1.System.Subscribe:input_type -> google.protobuf.Empty + 9, // 10: v1.System.BlockByNumber:input_type -> v1.BlockByNumberRequest + 11, // 11: v1.System.Export:input_type -> v1.ExportRequest + 3, // 12: v1.System.GetStatus:output_type -> v1.ServerStatus + 1, // 13: v1.System.GetTrace:output_type -> v1.GetTraceResponse + 6, // 14: v1.System.PeersAdd:output_type -> v1.PeersAddResponse + 8, // 15: v1.System.PeersList:output_type -> v1.PeersListResponse + 4, // 16: v1.System.PeersStatus:output_type -> v1.Peer + 2, // 17: v1.System.Subscribe:output_type -> v1.BlockchainEvent + 10, // 18: v1.System.BlockByNumber:output_type -> v1.BlockResponse + 12, // 19: v1.System.Export:output_type -> v1.ExportEvent + 12, // [12:20] is the sub-list for method output_type + 4, // [4:12] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_server_proto_system_proto_init() } @@ -1175,7 +1147,7 @@ func file_server_proto_system_proto_init() { return nil } } - file_server_proto_system_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BlockchainEvent_Header); i { case 0: return &v.state @@ -1187,7 +1159,7 @@ func file_server_proto_system_proto_init() { return nil } } - file_server_proto_system_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_server_proto_system_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServerStatus_Block); i { case 0: return &v.state @@ -1206,7 +1178,7 @@ func file_server_proto_system_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_server_proto_system_proto_rawDesc, NumEnums: 0, - NumMessages: 17, + NumMessages: 15, NumExtensions: 0, NumServices: 1, }, diff --git a/server/proto/system.proto b/server/proto/system.proto index ca73293343..a9022a254f 100644 --- a/server/proto/system.proto +++ b/server/proto/system.proto @@ -36,8 +36,7 @@ message GetTraceRequest { } message GetTraceResponse { - map accountTrace = 1; - map storageTrace = 2; + bytes trace = 1; } message BlockchainEvent { diff --git a/server/system_service.go b/server/system_service.go index 130f6911ad..faefb61f88 100644 --- a/server/system_service.go +++ b/server/system_service.go @@ -3,7 +3,6 @@ package server import ( "bytes" "context" - "encoding/json" "errors" "fmt" "io/ioutil" @@ -31,14 +30,8 @@ func (s *systemService) GetTrace(ctx context.Context, req *proto.GetTraceRequest return nil, err } - var trace *types.Trace - if err := json.Unmarshal(data, &trace); err != nil { - return nil, err - } - resp := &proto.GetTraceResponse{ - AccountTrace: trace.AccountTrie, - StorageTrace: trace.StorageTrie, + Trace: data, } return resp, nil diff --git a/state/executor.go b/state/executor.go index 8a56dafc14..9329ca5407 100644 --- a/state/executor.go +++ b/state/executor.go @@ -189,6 +189,8 @@ type Transition struct { PostHook func(t *Transition) + trace *types.Trace + // runtimes evm *evm.EVM precompiles *precompiled.Precompiled @@ -201,6 +203,9 @@ func NewTransition(config chain.ForksInTime, snap Snapshot, radix *Txn) *Transit snap: snap, evm: evm.NewEVM(), precompiles: precompiled.NewPrecompiled(), + trace: &types.Trace{ + TxnTraces: []*types.TxnTrace{}, + }, } } @@ -296,6 +301,11 @@ func (t *Transition) Write(txn *types.Transaction) error { receipt.LogsBloom = types.CreateBloom([]*types.Receipt{receipt}) t.receipts = append(t.receipts, receipt) + t.trace.TxnTraces = append(t.trace.TxnTraces, &types.TxnTrace{ + Transaction: txn.MarshalRLP(), + Delta: t.Txn().getCompactJournal(), + }) + return nil } @@ -308,9 +318,12 @@ func (t *Transition) Commit() (Snapshot, *types.Trace, types.Hash) { t.state.AddBalance(targetAddr, big.NewInt(10)) objs := t.state.Commit(t.config.EIP155) - s2, traces, root := t.snap.Commit(objs) + s2, snapTrace, root := t.snap.Commit(objs) + + t.trace.AccountTrie = snapTrace.AccountTrie + t.trace.StorageTrie = snapTrace.StorageTrie - return s2, traces, types.BytesToHash(root) + return s2, t.trace, types.BytesToHash(root) } func (t *Transition) subGasPool(amount uint64) error { diff --git a/state/txn.go b/state/txn.go index 3c5fc0426f..c3e165d914 100644 --- a/state/txn.go +++ b/state/txn.go @@ -1,7 +1,6 @@ package state import ( - "bytes" "fmt" "math/big" @@ -38,7 +37,7 @@ type Txn struct { codeCache *lru.Cache // tracing - journal []*journalEntry + journal []*types.JournalEntry } func NewTxn(snapshot Snapshot) *Txn { @@ -59,7 +58,7 @@ func newTxn(snapshot readSnapshot) *Txn { snapshots: []*iradix.Tree{}, txn: i.Txn(), codeCache: codeCache, - journal: []*journalEntry{}, + journal: []*types.JournalEntry{}, } } @@ -83,20 +82,20 @@ func (txn *Txn) RevertToSnapshot(id int) { txn.txn = tree.Txn() } -func (txn *Txn) getCompactJournal() map[types.Address]*journalEntry { +func (txn *Txn) getCompactJournal() map[types.Address]*types.JournalEntry { // Instead of creating a new object to represent the aggregate on how // an account has changed during the compaction, we piggyback the same // journalEntry object for now. - res := map[types.Address]*journalEntry{} + res := map[types.Address]*types.JournalEntry{} for _, entry := range txn.journal { obj, ok := res[entry.Addr] if !ok { - obj = &journalEntry{} + obj = &types.JournalEntry{} res[entry.Addr] = obj } - obj.merge(entry) + obj.Merge(entry) } // reset the journal @@ -105,7 +104,7 @@ func (txn *Txn) getCompactJournal() map[types.Address]*journalEntry { return res } -func (txn *Txn) addJournalEntry(j *journalEntry) { +func (txn *Txn) addJournalEntry(j *types.JournalEntry) { txn.journal = append(txn.journal, j) } @@ -116,7 +115,7 @@ const ( ) func (txn *Txn) trackAccountChange(addr types.Address, changeType string, object *StateObject) { - entry := &journalEntry{ + entry := &types.JournalEntry{ Addr: addr, } @@ -385,7 +384,7 @@ func (txn *Txn) SetState( object.Txn.Insert(key.Bytes(), value.Bytes()) } - txn.addJournalEntry(&journalEntry{ + txn.addJournalEntry(&types.JournalEntry{ Addr: addr, Storage: map[types.Hash]types.Hash{ key: value, @@ -513,7 +512,7 @@ func (txn *Txn) Suicide(addr types.Address) bool { suicided = true object.Suicide = true - txn.addJournalEntry(&journalEntry{ + txn.addJournalEntry(&types.JournalEntry{ Addr: addr, Suicide: boolTruePtr(), }) @@ -577,7 +576,7 @@ func (txn *Txn) GetCommittedState(addr types.Address, key types.Hash) types.Hash func (txn *Txn) TouchAccount(addr types.Address) { txn.upsertAccount(addr, true, func(obj *StateObject) { - txn.addJournalEntry(&journalEntry{ + txn.addJournalEntry(&types.JournalEntry{ Addr: addr, Touched: boolTruePtr(), }) @@ -713,59 +712,3 @@ func (txn *Txn) Commit(deleteEmptyObjects bool) []*Object { return objs } - -type journalEntry struct { - // Addr is the address of the account affected by the - // journal change - Addr types.Address `json:"address"` - - // Balance tracks changes in the account Balance - Balance *big.Int `json:"balance,omitempty"` - - // Nonce tracks changes in the account Nonce - Nonce *uint64 `json:"nonce,omitempty"` - - // Storage track changes in the storage - Storage map[types.Hash]types.Hash `json:"storage,omitempty"` - - // Code tracks the initialization of the contract Code - Code []byte `json:"code,omitempty"` - - // Suicide tracks whether the contract has been self destructed - Suicide *bool `json:"suicide,omitempty"` - - // Touched tracks whether the account has been touched/created - Touched *bool `json:"touched,omitempty"` -} - -func (j *journalEntry) merge(jj *journalEntry) { - if jj.Nonce != nil && jj.Nonce != j.Nonce { - j.Nonce = jj.Nonce - } - - if jj.Balance != nil && jj.Balance != j.Balance { - j.Balance = jj.Balance - } - - if jj.Storage != nil { - if j.Storage == nil { - j.Storage = map[types.Hash]types.Hash{} - } - - for k, v := range jj.Storage { - j.Storage[k] = v - } - } - - if jj.Code != nil && !bytes.Equal(jj.Code, j.Code) { - j.Code = jj.Code - } - - if jj.Suicide != nil && jj.Suicide != j.Suicide { - j.Suicide = jj.Suicide - } - - if jj.Touched != nil && jj.Touched != j.Touched { - j.Touched = jj.Touched - } -} diff --git a/state/txn_test.go b/state/txn_test.go index df8a6659b8..1acf53e964 100644 --- a/state/txn_test.go +++ b/state/txn_test.go @@ -93,7 +93,7 @@ func TestTxn_TracesCompaction(t *testing.T) { nonce := uint64(2) - require.Equal(t, trace[addr], &journalEntry{ + require.Equal(t, trace[addr], &types.JournalEntry{ Balance: big.NewInt(2), Nonce: &nonce, Storage: map[types.Hash]types.Hash{ @@ -107,11 +107,11 @@ func TestTxn_TracesCompaction(t *testing.T) { func TestJournalEntry_Merge(t *testing.T) { one := uint64(1) - entryAllSet := func() *journalEntry { + entryAllSet := func() *types.JournalEntry { // use a function because the merge function // modifies the caller and the test would // have side effects. - return &journalEntry{ + return &types.JournalEntry{ Nonce: &one, Balance: big.NewInt(1), Storage: map[types.Hash]types.Hash{ @@ -124,22 +124,22 @@ func TestJournalEntry_Merge(t *testing.T) { } cases := []struct { - a, b, c *journalEntry // a.merge(b) = c + a, b, c *types.JournalEntry // a.merge(b) = c }{ { - &journalEntry{}, + &types.JournalEntry{}, entryAllSet(), entryAllSet(), }, { entryAllSet(), - &journalEntry{}, + &types.JournalEntry{}, entryAllSet(), }, } for _, c := range cases { - c.a.merge(c.b) + c.a.Merge(c.b) require.Equal(t, c.c, c.a) } } diff --git a/types/types.go b/types/types.go index b1f25d6d51..c5765c7b3c 100644 --- a/types/types.go +++ b/types/types.go @@ -1,7 +1,9 @@ package types import ( + "bytes" "fmt" + "math/big" "strings" "unicode" @@ -155,6 +157,79 @@ var ( ) type Trace struct { + // AccountTrie is the partial trie for the account merkle trie touched during the block AccountTrie map[string]string `json:"accountTrie"` + + // StorageTrie is the partial trie for the storage tries touched during the block StorageTrie map[string]string `json:"storageTrie"` + + // ParentStateRoot is the parent state root for this block + ParentStateRoot Hash `json:"parentStateRoot"` + + // TxnTraces is the list of traces per transaction in the block + TxnTraces []*TxnTrace `json:"transactionTraces"` +} + +type TxnTrace struct { + // Transaction is the RLP encoding of the transaction + Transaction []byte `json:"txn"` + + // Delta is the list of updates per account during this transaction + Delta map[Address]*JournalEntry `json:"delta"` +} + +type JournalEntry struct { + // Addr is the address of the account affected by the + // journal change + Addr Address `json:"address"` + + // Balance tracks changes in the account Balance + Balance *big.Int `json:"balance,omitempty"` + + // Nonce tracks changes in the account Nonce + Nonce *uint64 `json:"nonce,omitempty"` + + // Storage track changes in the storage + Storage map[Hash]Hash `json:"storage,omitempty"` + + // Code tracks the initialization of the contract Code + Code []byte `json:"code,omitempty"` + + // Suicide tracks whether the contract has been self destructed + Suicide *bool `json:"suicide,omitempty"` + + // Touched tracks whether the account has been touched/created + Touched *bool `json:"touched,omitempty"` +} + +func (j *JournalEntry) Merge(jj *JournalEntry) { + if jj.Nonce != nil && jj.Nonce != j.Nonce { + j.Nonce = jj.Nonce + } + + if jj.Balance != nil && jj.Balance != j.Balance { + j.Balance = jj.Balance + } + + if jj.Storage != nil { + if j.Storage == nil { + j.Storage = map[Hash]Hash{} + } + + for k, v := range jj.Storage { + j.Storage[k] = v + } + } + + if jj.Code != nil && !bytes.Equal(jj.Code, j.Code) { + j.Code = jj.Code + } + + if jj.Suicide != nil && jj.Suicide != j.Suicide { + j.Suicide = jj.Suicide + } + + if jj.Touched != nil && jj.Touched != j.Touched { + j.Touched = jj.Touched + } } From aca96737a31c363d77c8bc24c86bec3ca005002a Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Wed, 8 Mar 2023 11:18:35 +0100 Subject: [PATCH 12/24] Fix stuff --- state/executor.go | 9 +++------ types/types.go | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/state/executor.go b/state/executor.go index 9329ca5407..3e1ae384d2 100644 --- a/state/executor.go +++ b/state/executor.go @@ -165,6 +165,9 @@ func (e *Executor) BeginTxn( evm: evm.NewEVM(), precompiles: precompiled.NewPrecompiled(), PostHook: e.PostHook, + trace: &types.Trace{ + TxnTraces: []*types.TxnTrace{}, + }, } return txn, nil @@ -311,12 +314,6 @@ func (t *Transition) Write(txn *types.Transaction) error { // Commit commits the final result func (t *Transition) Commit() (Snapshot, *types.Trace, types.Hash) { - - // pre-commit op (TODO: Remove, only for zero tests) - targetAddr := types.Address{} - targetAddr[t.ctx.Number/20] = 1 - t.state.AddBalance(targetAddr, big.NewInt(10)) - objs := t.state.Commit(t.config.EIP155) s2, snapTrace, root := t.snap.Commit(objs) diff --git a/types/types.go b/types/types.go index c5765c7b3c..72e332a0ba 100644 --- a/types/types.go +++ b/types/types.go @@ -148,6 +148,48 @@ func (a Address) MarshalText() ([]byte, error) { return []byte(a.String()), nil } +// TODO: Replace jsonrpc/types/argByte with this? +// Still unsure if the codification will be done on protobuf side more +// than marshaling in json and if this will become necessary. +type ArgBytes []byte + +func (b ArgBytes) MarshalText() ([]byte, error) { + return encodeToHex(b), nil +} + +func (b *ArgBytes) UnmarshalText(input []byte) error { + hh, err := decodeToHex(input) + if err != nil { + return nil + } + + aux := make([]byte, len(hh)) + copy(aux[:], hh[:]) + *b = aux + + return nil +} + +func decodeToHex(b []byte) ([]byte, error) { + str := string(b) + str = strings.TrimPrefix(str, "0x") + + if len(str)%2 != 0 { + str = "0" + str + } + + return hex.DecodeString(str) +} + +func encodeToHex(b []byte) []byte { + str := hex.EncodeToString(b) + if len(str)%2 != 0 { + str = "0" + str + } + + return []byte("0x" + str) +} + var ( // EmptyRootHash is the root when there are no transactions EmptyRootHash = StringToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") @@ -172,7 +214,7 @@ type Trace struct { type TxnTrace struct { // Transaction is the RLP encoding of the transaction - Transaction []byte `json:"txn"` + Transaction ArgBytes `json:"txn"` // Delta is the list of updates per account during this transaction Delta map[Address]*JournalEntry `json:"delta"` From aaba5d1be5ea9771e535c67886f769f8c6e2e306 Mon Sep 17 00:00:00 2001 From: Ferran Borreguero Date: Mon, 13 Mar 2023 17:25:44 +0100 Subject: [PATCH 13/24] Add read ops to trace --- state/txn.go | 12 ++++++++++++ state/txn_test.go | 7 ++++++- types/types.go | 20 ++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/state/txn.go b/state/txn.go index c3e165d914..e65d387ca6 100644 --- a/state/txn.go +++ b/state/txn.go @@ -147,6 +147,11 @@ func (txn *Txn) GetAccount(addr types.Address) (*Account, bool) { } func (txn *Txn) getStateObject(addr types.Address) (*StateObject, bool) { + txn.addJournalEntry(&types.JournalEntry{ + Addr: addr, + Read: boolTruePtr(), + }) + // Try to get state from radix tree which holds transient states during block processing first val, exists := txn.txn.Get(addr.Bytes()) if exists { @@ -400,6 +405,13 @@ func (txn *Txn) GetState(addr types.Address, key types.Hash) types.Hash { return types.Hash{} } + txn.addJournalEntry(&types.JournalEntry{ + Addr: addr, + StorageRead: map[types.Hash]struct{}{ + key: {}, + }, + }) + // Try to get account state from radix tree first // Because the latest account state should be in in-memory radix tree // if account state update happened in previous transactions of same block diff --git a/state/txn_test.go b/state/txn_test.go index 1acf53e964..37cba6bf2f 100644 --- a/state/txn_test.go +++ b/state/txn_test.go @@ -86,7 +86,7 @@ func TestTxn_TracesCompaction(t *testing.T) { txn.SetState(addr, oneHash, types.ZeroHash) txn.TouchAccount(addr) - require.Len(t, txn.journal, 8) + require.Len(t, txn.journal, 16) trace := txn.getCompactJournal() require.Len(t, trace, 1) @@ -101,6 +101,7 @@ func TestTxn_TracesCompaction(t *testing.T) { oneHash: types.ZeroHash, }, Touched: boolTruePtr(), + Read: boolTruePtr(), }) } @@ -120,6 +121,10 @@ func TestJournalEntry_Merge(t *testing.T) { Code: []byte{0x1}, Suicide: boolTruePtr(), Touched: boolTruePtr(), + Read: boolTruePtr(), + StorageRead: map[types.Hash]struct{}{ + types.ZeroHash: {}, + }, } } diff --git a/types/types.go b/types/types.go index 72e332a0ba..4937ea3831 100644 --- a/types/types.go +++ b/types/types.go @@ -234,6 +234,9 @@ type JournalEntry struct { // Storage track changes in the storage Storage map[Hash]Hash `json:"storage,omitempty"` + // StorageRead is the list of storage slots read + StorageRead map[Hash]struct{} `json:"storage_read,omitempty"` + // Code tracks the initialization of the contract Code Code []byte `json:"code,omitempty"` @@ -242,6 +245,9 @@ type JournalEntry struct { // Touched tracks whether the account has been touched/created Touched *bool `json:"touched,omitempty"` + + // Read signals whether the account was read + Read *bool `json:"read,omitempty"` } func (j *JournalEntry) Merge(jj *JournalEntry) { @@ -274,4 +280,18 @@ func (j *JournalEntry) Merge(jj *JournalEntry) { if jj.Touched != nil && jj.Touched != j.Touched { j.Touched = jj.Touched } + + if jj.Read != nil && jj.Read != j.Read { + j.Read = jj.Read + } + + if jj.StorageRead != nil { + if j.StorageRead == nil { + j.StorageRead = map[Hash]struct{}{} + } + + for k := range jj.StorageRead { + j.StorageRead[k] = struct{}{} + } + } } From 113667ee3ffee71c202d9f959a142460c7b0e165 Mon Sep 17 00:00:00 2001 From: Stana Miric <94966829+stana-miric@users.noreply.github.com> Date: Tue, 18 Apr 2023 13:03:39 +0200 Subject: [PATCH 14/24] Info about code access is added to the trace (#1385) * Info about code access is added to the trace * test fix - init snapshot with empty trace --- state/immutable-trie/snapshot.go | 2 +- state/txn.go | 17 ++++++++++++++++- state/txn_test.go | 20 ++++++++++++-------- types/types.go | 7 +++++++ 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/state/immutable-trie/snapshot.go b/state/immutable-trie/snapshot.go index 0383d5b0af..b6fb9b3e8f 100644 --- a/state/immutable-trie/snapshot.go +++ b/state/immutable-trie/snapshot.go @@ -100,7 +100,7 @@ func (s *Snapshot) Commit(objs []*state.Object) (state.Snapshot, *types.Trace, [ t.Proof() } - return &Snapshot{trie: trie, state: s.state}, s.trace, root + return &Snapshot{trie: trie, state: s.state, trace: &types.Trace{}}, s.trace, root } type tracer struct { diff --git a/state/txn.go b/state/txn.go index e65d387ca6..bf9516e907 100644 --- a/state/txn.go +++ b/state/txn.go @@ -136,6 +136,15 @@ func (txn *Txn) trackAccountChange(addr types.Address, changeType string, object txn.addJournalEntry(entry) } +func (txn *Txn) trackCodeRead(addr types.Address, code []byte) { + entry := &types.JournalEntry{ + Addr: addr, + CodeRead: code, + } + + txn.addJournalEntry(entry) +} + // GetAccount returns an account func (txn *Txn) GetAccount(addr types.Address) (*Account, bool) { object, exists := txn.getStateObject(addr) @@ -478,6 +487,8 @@ func (txn *Txn) GetCode(addr types.Address) []byte { } if object.DirtyCode { + txn.trackCodeRead(addr, object.Code) + return object.Code } // TODO; Should we move this to state? @@ -485,11 +496,15 @@ func (txn *Txn) GetCode(addr types.Address) []byte { if ok { //nolint:forcetypeassert - return v.([]byte) + code := v.([]byte) + txn.trackCodeRead(addr, code) + + return code } code, _ := txn.snapshot.GetCode(types.BytesToHash(object.Account.CodeHash)) txn.codeCache.Add(addr, code) + txn.trackCodeRead(addr, code) return code } diff --git a/state/txn_test.go b/state/txn_test.go index 37cba6bf2f..2cc9272814 100644 --- a/state/txn_test.go +++ b/state/txn_test.go @@ -43,7 +43,7 @@ func (m *mockSnapshot) GetAccount(addr types.Address) (*Account, error) { } func (m *mockSnapshot) GetCode(hash types.Hash) ([]byte, bool) { - return nil, false + return []byte{0x1}, true } func newStateWithPreState(preState map[types.Address]*PreState) readSnapshot { @@ -85,8 +85,10 @@ func TestTxn_TracesCompaction(t *testing.T) { txn.SetState(addr, types.ZeroHash, oneHash) // updates txn.SetState(addr, oneHash, types.ZeroHash) + txn.GetCode(addr) + txn.TouchAccount(addr) - require.Len(t, txn.journal, 16) + require.Len(t, txn.journal, 18) trace := txn.getCompactJournal() require.Len(t, trace, 1) @@ -100,8 +102,9 @@ func TestTxn_TracesCompaction(t *testing.T) { types.ZeroHash: oneHash, oneHash: types.ZeroHash, }, - Touched: boolTruePtr(), - Read: boolTruePtr(), + CodeRead: []byte{0x1}, + Touched: boolTruePtr(), + Read: boolTruePtr(), }) } @@ -118,10 +121,11 @@ func TestJournalEntry_Merge(t *testing.T) { Storage: map[types.Hash]types.Hash{ types.ZeroHash: types.ZeroHash, }, - Code: []byte{0x1}, - Suicide: boolTruePtr(), - Touched: boolTruePtr(), - Read: boolTruePtr(), + Code: []byte{0x1}, + CodeRead: []byte{0x1}, + Suicide: boolTruePtr(), + Touched: boolTruePtr(), + Read: boolTruePtr(), StorageRead: map[types.Hash]struct{}{ types.ZeroHash: {}, }, diff --git a/types/types.go b/types/types.go index 4937ea3831..ea03e6f34e 100644 --- a/types/types.go +++ b/types/types.go @@ -240,6 +240,9 @@ type JournalEntry struct { // Code tracks the initialization of the contract Code Code []byte `json:"code,omitempty"` + // CodeRead tracks whether the contract Code was read + CodeRead []byte `json:"code_read,omitempty"` + // Suicide tracks whether the contract has been self destructed Suicide *bool `json:"suicide,omitempty"` @@ -273,6 +276,10 @@ func (j *JournalEntry) Merge(jj *JournalEntry) { j.Code = jj.Code } + if jj.CodeRead != nil && !bytes.Equal(jj.CodeRead, j.CodeRead) { + j.CodeRead = jj.CodeRead + } + if jj.Suicide != nil && jj.Suicide != j.Suicide { j.Suicide = jj.Suicide } From fde7d4a7b2ebda326e6aad83632888d9857a85b9 Mon Sep 17 00:00:00 2001 From: Stana Miric <94966829+stana-miric@users.noreply.github.com> Date: Thu, 4 May 2023 11:00:05 +0200 Subject: [PATCH 15/24] Polybft adaptation for writing traces on all validators (#1463) * Add trace to the polybft --- blockchain/blockchain.go | 58 ++++++++++++----- blockchain/blockchain_test.go | 2 +- blockchain/config.go | 9 +++ blockchain/testing.go | 8 +-- consensus/polybft/block_builder.go | 6 +- consensus/polybft/blockchain_wrapper.go | 5 +- e2e-polybft/e2e/consensus_test.go | 84 +++++++++++++++++++++++++ server/server.go | 4 +- types/header.go | 1 + 9 files changed, 148 insertions(+), 29 deletions(-) create mode 100644 blockchain/config.go diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index c8ccd3cf3d..cf68266baa 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -1,9 +1,12 @@ package blockchain import ( + "encoding/json" "errors" "fmt" + "io/ioutil" "math/big" + "path/filepath" "sync" "sync/atomic" @@ -46,8 +49,8 @@ type Blockchain struct { executor Executor txSigner TxSigner - config *chain.Chain // Config containing chain information - genesis types.Hash // The hash of the genesis block + config *Config // Config containing chain information + genesis types.Hash // The hash of the genesis block headersCache *lru.Cache // LRU cache for the headers difficultyCache *lru.Cache // LRU cache for the difficulty @@ -101,6 +104,7 @@ type BlockResult struct { Root types.Hash Receipts []*types.Receipt TotalGas uint64 + Trace *types.Trace } // updateGasPriceAvg updates the rolling average value of the gas price @@ -185,7 +189,7 @@ func (b *Blockchain) GetAvgGasPrice() *big.Int { func NewBlockchain( logger hclog.Logger, db storage.Storage, - config *chain.Chain, + config *Config, consensus Verifier, executor Executor, txSigner TxSigner, @@ -249,7 +253,7 @@ func (b *Blockchain) ComputeGenesis() error { } // validate that the genesis file in storage matches the chain.Genesis - if b.genesis != b.config.Genesis.Hash() { + if b.genesis != b.config.Chain.Genesis.Hash() { return fmt.Errorf("genesis file does not match current genesis") } @@ -274,12 +278,12 @@ func (b *Blockchain) ComputeGenesis() error { b.setCurrentHeader(header, diff) } else { // empty storage, write the genesis - if err := b.writeGenesis(b.config.Genesis); err != nil { + if err := b.writeGenesis(b.config.Chain.Genesis); err != nil { return err } } - b.logger.Info("genesis", "hash", b.config.Genesis.Hash()) + b.logger.Info("genesis", "hash", b.config.Chain.Genesis.Hash()) return nil } @@ -326,7 +330,7 @@ func (b *Blockchain) CurrentTD() *big.Int { // Config returns the blockchain configuration func (b *Blockchain) Config() *chain.Params { - return b.config.Params + return b.config.Chain.Params } // GetHeader returns the block header using the hash @@ -671,17 +675,17 @@ func (b *Blockchain) VerifyFinalizedBlock(block *types.Block) (*types.FullBlock, } // Do the initial block verification - receipts, err := b.verifyBlock(block) + blockResult, err := b.verifyBlock(block) if err != nil { return nil, err } - return &types.FullBlock{Block: block, Receipts: receipts}, nil + return &types.FullBlock{Block: block, Receipts: blockResult.Receipts, Trace: blockResult.Trace}, nil } // verifyBlock does the base (common) block verification steps by // verifying the block body as well as the parent information -func (b *Blockchain) verifyBlock(block *types.Block) ([]*types.Receipt, error) { +func (b *Blockchain) verifyBlock(block *types.Block) (*BlockResult, error) { // Make sure the block is present if block == nil { return nil, ErrNoBlock @@ -693,12 +697,12 @@ func (b *Blockchain) verifyBlock(block *types.Block) ([]*types.Receipt, error) { } // Make sure the block body data is valid - receipts, err := b.verifyBlockBody(block) + blockResult, err := b.verifyBlockBody(block) if err != nil { return nil, err } - return receipts, nil + return blockResult, nil } // verifyBlockParent makes sure that the child block is in line @@ -756,7 +760,7 @@ func (b *Blockchain) verifyBlockParent(childBlock *types.Block) error { // - The trie roots match up (state, transactions, receipts, uncles) // - The receipts match up // - The execution result matches up -func (b *Blockchain) verifyBlockBody(block *types.Block) ([]*types.Receipt, error) { +func (b *Blockchain) verifyBlockBody(block *types.Block) (*BlockResult, error) { // Make sure the Uncles root matches up if hash := buildroot.CalculateUncleRoot(block.Uncles); hash != block.Header.Sha3Uncles { b.logger.Error(fmt.Sprintf( @@ -790,7 +794,7 @@ func (b *Blockchain) verifyBlockBody(block *types.Block) ([]*types.Receipt, erro return nil, fmt.Errorf("unable to verify block execution result, %w", err) } - return blockResult.Receipts, nil + return blockResult, nil } // verifyBlockResult verifies that the block transaction execution result @@ -844,9 +848,7 @@ func (b *Blockchain) executeBlockTransactions(block *types.Block) (*BlockResult, return nil, err } - //nolint:godox - // TODO write trace ? - _, _, root := txn.Commit() + _, trace, root := txn.Commit() // Append the receipts to the receipts cache b.receiptsCache.Add(header.Hash, txn.Receipts()) @@ -855,6 +857,7 @@ func (b *Blockchain) executeBlockTransactions(block *types.Block) (*BlockResult, Root: root, Receipts: txn.Receipts(), TotalGas: txn.TotalGas(), + Trace: trace, }, nil } @@ -893,6 +896,11 @@ func (b *Blockchain) WriteFullBlock(fblock *types.FullBlock, source string) erro return err } + // write the trace + if err := b.writeTrace(fblock.Trace, header.Number); err != nil { + return err + } + // update snapshot if err := b.consensus.ProcessHeaders([]*types.Header{header}); err != nil { return err @@ -1282,6 +1290,22 @@ func (b *Blockchain) writeFork(header *types.Header) error { return nil } +// writeTrace writes the block trace to the file +func (b *Blockchain) writeTrace(trace *types.Trace, blockNumber uint64) error { + raw, err := json.Marshal(trace) + if err != nil { + return err + } + + consensusDir := filepath.Join(b.config.DataDir, "consensus") + if err := ioutil.WriteFile( + filepath.Join(consensusDir, fmt.Sprintf("trace_%d.json", blockNumber)), raw, 0600); err != nil { + return err + } + + return nil +} + // handleReorg handles a reorganization event func (b *Blockchain) handleReorg( evnt *Event, diff --git a/blockchain/blockchain_test.go b/blockchain/blockchain_test.go index 1646c49660..baea42f6ee 100644 --- a/blockchain/blockchain_test.go +++ b/blockchain/blockchain_test.go @@ -955,7 +955,7 @@ func TestCalculateGasLimit(t *testing.T) { t.Fatalf("unable to construct the blockchain, %v", blockchainErr) } - b.config.Params = &chain.Params{ + b.config.Chain.Params = &chain.Params{ BlockGasTarget: tt.blockGasTarget, } diff --git a/blockchain/config.go b/blockchain/config.go new file mode 100644 index 0000000000..66f7a0d78c --- /dev/null +++ b/blockchain/config.go @@ -0,0 +1,9 @@ +package blockchain + +import "github.com/0xPolygon/polygon-edge/chain" + +// Config is the configuration for the blockchain +type Config struct { + Chain *chain.Chain // the reference to the chain configuration + DataDir string // the base data directory for the client +} diff --git a/blockchain/testing.go b/blockchain/testing.go index 2f3b510cd0..77457d662f 100644 --- a/blockchain/testing.go +++ b/blockchain/testing.go @@ -144,7 +144,7 @@ func NewMockBlockchain( var ( mockVerifier = &MockVerifier{} executor = &mockExecutor{} - config = &chain.Chain{ + chainConfig = &chain.Chain{ Genesis: &chain.Genesis{ Number: 0, GasLimit: 0, @@ -185,7 +185,7 @@ func NewMockBlockchain( return nil, errInvalidTypeAssertion } - callback(config) + callback(chainConfig) } // Execute the storage callback @@ -204,7 +204,7 @@ func NewMockBlockchain( db: mockStorage, consensus: mockVerifier, executor: executor, - config: config, + config: &Config{Chain: chainConfig}, stream: &eventStream{}, gpAverage: &gasPriceAverage{ price: big.NewInt(0), @@ -347,7 +347,7 @@ func newBlockChain(config *chain.Chain, executor Executor) (*Blockchain, error) return nil, err } - b, err := NewBlockchain(hclog.NewNullLogger(), db, config, &MockVerifier{}, executor, &mockSigner{}) + b, err := NewBlockchain(hclog.NewNullLogger(), db, &Config{Chain: config}, &MockVerifier{}, executor, &mockSigner{}) if err != nil { return nil, err } diff --git a/consensus/polybft/block_builder.go b/consensus/polybft/block_builder.go index 441c40d306..ba48f0a763 100644 --- a/consensus/polybft/block_builder.go +++ b/consensus/polybft/block_builder.go @@ -108,9 +108,8 @@ func (b *BlockBuilder) Build(handler func(h *types.Header)) (*types.FullBlock, e handler(b.header) } - //nolint:godox - // TODO write trace - _, _, b.header.StateRoot = b.state.Commit() + _, trace, root := b.state.Commit() + b.header.StateRoot = root b.header.GasUsed = b.state.TotalGas() // build the block @@ -125,6 +124,7 @@ func (b *BlockBuilder) Build(handler func(h *types.Header)) (*types.FullBlock, e return &types.FullBlock{ Block: b.block, Receipts: b.state.Receipts(), + Trace: trace, }, nil } diff --git a/consensus/polybft/blockchain_wrapper.go b/consensus/polybft/blockchain_wrapper.go index 8d2dd38424..002140e9aa 100644 --- a/consensus/polybft/blockchain_wrapper.go +++ b/consensus/polybft/blockchain_wrapper.go @@ -106,9 +106,7 @@ func (p *blockchainWrapper) ProcessBlock(parent *types.Header, block *types.Bloc } } - //nolint:godox - // TODO write trace - _, _, root := transition.Commit() + _, trace, root := transition.Commit() if root != block.Header.StateRoot { return nil, fmt.Errorf("incorrect state root: (%s, %s)", root, block.Header.StateRoot) @@ -124,6 +122,7 @@ func (p *blockchainWrapper) ProcessBlock(parent *types.Header, block *types.Bloc return &types.FullBlock{ Block: builtBlock, Receipts: transition.Receipts(), + Trace: trace, }, nil } diff --git a/e2e-polybft/e2e/consensus_test.go b/e2e-polybft/e2e/consensus_test.go index 79f5912399..8c7c1e207c 100644 --- a/e2e-polybft/e2e/consensus_test.go +++ b/e2e-polybft/e2e/consensus_test.go @@ -1,6 +1,8 @@ package e2e import ( + "context" + "encoding/json" "fmt" "math/big" "path" @@ -13,6 +15,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" + "github.com/0xPolygon/polygon-edge/server/proto" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/require" @@ -699,3 +702,84 @@ func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) { require.NoError(t, err) require.Equal(t, uint64(types.ReceiptFailed), receipt.Status) } + +func TestE2E_Consensus_Trace(t *testing.T) { + const ( + validatorSecrets = "test-chain-1" + newAccSecrets = "test-chain-newAcc" + epochSize = 5 + validatorCount = 5 + ) + + cluster := framework.NewTestCluster(t, validatorCount, + framework.WithEpochReward(100000), + framework.WithEpochSize(epochSize)) + defer cluster.Stop() + + // init new account + _, err := cluster.InitSecrets(newAccSecrets, 1) + require.NoError(t, err) + + cluster.WaitForReady(t) + + // extract new acc secrets + newAccSecretsPath := path.Join(cluster.Config.TmpDir, newAccSecrets) + newAcc, err := sidechain.GetAccountFromDir(newAccSecretsPath) + require.NoError(t, err) + + newAccAddr := newAcc.Ecdsa.Address() + + // extract validator's secrets + validatorSecretsPath := path.Join(cluster.Config.TmpDir, validatorSecrets) + + validatorAcc, err := sidechain.GetAccountFromDir(validatorSecretsPath) + require.NoError(t, err) + + validatorAddr := validatorAcc.Ecdsa.Address() + + // transfer funds to the new account + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Servers[0].JSONRPCAddr())) + require.NoError(t, err) + + receipt, err := txRelayer.SendTransaction(ðgo.Transaction{ + From: validatorAddr, + To: &newAccAddr, + Value: ethgo.Ether(2), + }, validatorAcc.Ecdsa) + require.NoError(t, err) + require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) + require.NotNil(t, receipt.TransactionHash) + + // verify trace existence on all validators + for i := 0; i < validatorCount; i++ { + ethEndpoint := cluster.Servers[i].JSONRPC().Eth() + + blockResponse, err := ethEndpoint.GetBlockByNumber(ethgo.BlockNumber(receipt.BlockNumber), false) + require.NoError(t, err) + require.NotEqual(t, blockResponse.Miner, ethgo.ZeroAddress) + + sysClient := cluster.Servers[i].Conn() + traceResp, err := sysClient.GetTrace(context.Background(), &proto.GetTraceRequest{Number: receipt.BlockNumber}) + require.NoError(t, err) + + var trace *types.Trace + err = json.Unmarshal(traceResp.Trace, &trace) + require.NoError(t, err) + + containsCoinbaseAddr, containsSenderAddr, containsReceiverAddr := false, false, false + + var journalEntry *types.JournalEntry + + for _, tr := range trace.TxnTraces { + _, containsCoinbaseAddr = tr.Delta[types.Address(blockResponse.Miner)] + _, containsSenderAddr = tr.Delta[types.Address(validatorAddr)] + + journalEntry, containsReceiverAddr = tr.Delta[types.Address(newAccAddr)] + require.True(t, journalEntry.Balance.Cmp(ethgo.Ether(2)) == 0) + } + + require.True(t, containsCoinbaseAddr) + require.True(t, containsSenderAddr) + require.True(t, containsReceiverAddr) + } +} diff --git a/server/server.go b/server/server.go index 3d8338e208..5bdb641040 100644 --- a/server/server.go +++ b/server/server.go @@ -267,7 +267,9 @@ func NewServer(config *Config) (*Server, error) { } // blockchain object - m.blockchain, err = blockchain.NewBlockchain(logger, db, config.Chain, nil, m.executor, signer) + blockchainConfig := &blockchain.Config{Chain: config.Chain, DataDir: config.DataDir} + m.blockchain, err = blockchain.NewBlockchain(logger, db, blockchainConfig, nil, m.executor, signer) + if err != nil { return nil, err } diff --git a/types/header.go b/types/header.go index bf2750f05b..5406bee8d4 100644 --- a/types/header.go +++ b/types/header.go @@ -94,6 +94,7 @@ type Body struct { type FullBlock struct { Block *Block Receipts []*Receipt + Trace *Trace } type Block struct { From bf51a0b4e11b3d3bfeb01d6854981c039c09479c Mon Sep 17 00:00:00 2001 From: Stana Miric <94966829+stana-miric@users.noreply.github.com> Date: Tue, 16 May 2023 16:26:23 +0200 Subject: [PATCH 16/24] Set parent state root to the trace (#1513) * Setting parent state root in the trace --- blockchain/blockchain.go | 1 + consensus/polybft/block_builder.go | 1 + consensus/polybft/blockchain_wrapper.go | 1 + e2e-polybft/e2e/consensus_test.go | 4 ++++ 4 files changed, 7 insertions(+) diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index cf68266baa..67931d6642 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -849,6 +849,7 @@ func (b *Blockchain) executeBlockTransactions(block *types.Block) (*BlockResult, } _, trace, root := txn.Commit() + trace.ParentStateRoot = parent.StateRoot // Append the receipts to the receipts cache b.receiptsCache.Add(header.Hash, txn.Receipts()) diff --git a/consensus/polybft/block_builder.go b/consensus/polybft/block_builder.go index ba48f0a763..e6f3cd6d17 100644 --- a/consensus/polybft/block_builder.go +++ b/consensus/polybft/block_builder.go @@ -109,6 +109,7 @@ func (b *BlockBuilder) Build(handler func(h *types.Header)) (*types.FullBlock, e } _, trace, root := b.state.Commit() + trace.ParentStateRoot = b.params.Parent.StateRoot b.header.StateRoot = root b.header.GasUsed = b.state.TotalGas() diff --git a/consensus/polybft/blockchain_wrapper.go b/consensus/polybft/blockchain_wrapper.go index 002140e9aa..1d6e4dd3d4 100644 --- a/consensus/polybft/blockchain_wrapper.go +++ b/consensus/polybft/blockchain_wrapper.go @@ -107,6 +107,7 @@ func (p *blockchainWrapper) ProcessBlock(parent *types.Header, block *types.Bloc } _, trace, root := transition.Commit() + trace.ParentStateRoot = parent.StateRoot if root != block.Header.StateRoot { return nil, fmt.Errorf("incorrect state root: (%s, %s)", root, block.Header.StateRoot) diff --git a/e2e-polybft/e2e/consensus_test.go b/e2e-polybft/e2e/consensus_test.go index 8c7c1e207c..51979d7e30 100644 --- a/e2e-polybft/e2e/consensus_test.go +++ b/e2e-polybft/e2e/consensus_test.go @@ -758,6 +758,9 @@ func TestE2E_Consensus_Trace(t *testing.T) { require.NoError(t, err) require.NotEqual(t, blockResponse.Miner, ethgo.ZeroAddress) + parentBlock, err := ethEndpoint.GetBlockByHash(blockResponse.ParentHash, false) + require.NoError(t, err) + sysClient := cluster.Servers[i].Conn() traceResp, err := sysClient.GetTrace(context.Background(), &proto.GetTraceRequest{Number: receipt.BlockNumber}) require.NoError(t, err) @@ -765,6 +768,7 @@ func TestE2E_Consensus_Trace(t *testing.T) { var trace *types.Trace err = json.Unmarshal(traceResp.Trace, &trace) require.NoError(t, err) + require.Equal(t, parentBlock.StateRoot.Bytes(), trace.ParentStateRoot.Bytes()) containsCoinbaseAddr, containsSenderAddr, containsReceiverAddr := false, false, false From 4b3c78c9ab45a46783139544f327233f6e9d17b6 Mon Sep 17 00:00:00 2001 From: Stana Miric <94966829+stana-miric@users.noreply.github.com> Date: Mon, 3 Jul 2023 09:04:09 +0200 Subject: [PATCH 17/24] Set journal address (#1690) --- state/txn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/state/txn.go b/state/txn.go index f5a3b79e40..a8891299f4 100644 --- a/state/txn.go +++ b/state/txn.go @@ -91,7 +91,7 @@ func (txn *Txn) getCompactJournal() map[types.Address]*types.JournalEntry { for _, entry := range txn.journal { obj, ok := res[entry.Addr] if !ok { - obj = &types.JournalEntry{} + obj = &types.JournalEntry{Addr: entry.Addr} res[entry.Addr] = obj } From 575d1ed95375e7a91f2e5316ca99ee79bf81c05d Mon Sep 17 00:00:00 2001 From: Stana Miric <94966829+stana-miric@users.noreply.github.com> Date: Tue, 4 Jul 2023 16:21:02 +0200 Subject: [PATCH 18/24] Merge v1.0.0 into zero (#1697) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix minor punctuation mistakes (#1343) * EVM-533 Nightly slack notificatinos (#1341) * Add e2e test for allowlist proxy (#1338) * Add docs/sequences.md with deposit, withdraw, and exit sequences (#1354) * Add docs/sequences.md with deposit, withdraw, and exit sequences * Add more detail to exit sequence * Fix StateSyncResult Event typo Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Fix arrow typo Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Rm imx reference Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Rename NativeERC20.sol to ChildERC20.sol Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Move sequences.md to docs/bridge * Rephrase sequence explanation sentences * Rename Client to User * Fix deposit sequence and specifer spender in approve() * Add mapToken() flow * Add DEPOSIT_SIG flow Co-authored-by: Goran Rojovic <100121253+goran-ethernal@users.noreply.github.com> * Rm duplicate rows in deposit --------- Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> Co-authored-by: Goran Rojovic <100121253+goran-ethernal@users.noreply.github.com> * Deploy NFT contracts (#1322) * Deploy NFT contracts * Provide flags for existing tokens on the root chain * Linters fix * Transactions allow list (#1349) * Implement transactions allow list * Evm 505: fuzz tests in nightly build (#1353) add slack notification for fuzz tests Co-authored-by: Victor Castell * Add receivers to sync state actions (#1358) * Use buffered channel (#1361) * EVM-584 Panic -> send on closed channel inside syncer (#1364) * Obsolete block time flag from server command (#1365) * refactor(server): remove block time configuration from raw config and server params (#1363) The block time configuration was removed from the raw config and server params. The initBlockTime function was also removed from the server params. * Resolve block time from consensus engine parameters * Provide zero value for block time for dummy and dev consensuses * Move DefaultBlockTime to IBFT E2E tests * Make sure that block time is not less than 1 second --------- Co-authored-by: Flavor Town <117117716+flavor-town@users.noreply.github.com> * Deprecate L2 to L1 e2e tests (#1369) * Update TestIntegratoin_PerformExit * deposit + widthdraw signature * Add minting and approval steps in TestIntegratoin_PerformExit * Obsolete TestL1StateReceiver SC and L2 to L1 E2E tests which were using it * some comments added * lint fix * deployer address --------- Co-authored-by: Igor Crevar Co-authored-by: Nemanja0x * Shorten execution time of E2E tests (#1360) * Provide epoch size to consensus tests * Fix failing tests * Rename tests * Fix comment * Rely on epoch sizes in TestE2E_Bridge_ChangeVotingPower * Move getCheckpointBlockNumber to helpers_test * Introduce waitForRootchainEpoch helper fn * Consolidate deposit and withdrawal erc20 with multiple commitments per epoch tests * Consolidate deposit and withdrawals transactions and multiple commitments into single test * Minor improvements to documentation * Rootchain fund command minor change * Try to stabilize ERC 20 deposit and withdrawal test * Test hardening cont. * Consolidate basic consensus and sync tests into the one * Stop timer and create single ticker instance for recurrent checking * Add eth_call override (#1337) * Add eth_call override * Pass lint * Apply feedback --------- Co-authored-by: Victor Castell * Eth_call override unit test lint fix (#1374) * Change folders hierarchy for property tests logs (#1371) * Change folders hierarchy for property tests logs * Remove unnecessary env variable * Update yml and Make files * Comments fix * Add logging of test parameters * Comments fix * Lint fix * SLACK_TEST_WEBHOOK_URL -> SLACK_EDGE_GITHUB_URL (#1380) * Move IBFT E2E tests to nighly builds (#1382) * Support non-validator nodes in e2e tests (#1378) * Support non-validator nodes in e2e tests * Comments fix * Comments fix * Fix * Remove validator-set-size from cluster script (#1384) * "native-token-config" flag added to genesis command (#1376) "native-token-config" flag added to genesis command Co-authored-by: Stefan Negovanović * Remove unused `Seal` field from the extra data (#1379) * Remove unused Seal field from the extra data * Fix tests * Update field comments * Typo in e2e workflow file name (#1387) * Provide correct state sync event logs filter in `TestE2E_Bridge_Transfers` (#1381) * Fix TestE2E_Bridge_Transfers * Extract finalBlockNum variable * Harden TestPeerConnectionUpdateEventCh * Inline WriteTx invocation * `eth_getBlockByHash` and `eth_getBlockByNumber` JSON RPC endpoints should omit `Committed` field (#1383) * Filter extra Committed field in jsonRPC endpoints * UT * Fix UTs * Lint fix * Comments fix * Comments fix * Append `ExtraVanity` to the beginning of the marshaled `ExtraData` (#1391) * Append ExtraVanity to the beginning of the marshaled extra data * Build unit tests fix * Fix test * Fix by not adding ExtraVanity twice * Bump github.com/prometheus/client_golang from 1.13.1 to 1.15.0 (#1395) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.13.1 to 1.15.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.13.1...v1.15.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/hashicorp/go-hclog from 1.3.1 to 1.5.0 (#1393) Bumps [github.com/hashicorp/go-hclog](https://github.com/hashicorp/go-hclog) from 1.3.1 to 1.5.0. - [Release notes](https://github.com/hashicorp/go-hclog/releases) - [Commits](https://github.com/hashicorp/go-hclog/compare/v1.3.1...v1.5.0) --- updated-dependencies: - dependency-name: github.com/hashicorp/go-hclog dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [EVM-586]: Paralelize fund transactions sending (#1399) * Parallelize execution of fund commands on root * Use errgroup * Bump gopkg.in/DataDog/dd-trace-go.v1 from 1.43.1 to 1.49.1 (#1398) Bumps gopkg.in/DataDog/dd-trace-go.v1 from 1.43.1 to 1.49.1. --- updated-dependencies: - dependency-name: gopkg.in/DataDog/dd-trace-go.v1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/libp2p/go-libp2p-pubsub from 0.8.1 to 0.9.3 (#1397) * Bump github.com/libp2p/go-libp2p-pubsub from 0.8.1 to 0.9.3 Bumps [github.com/libp2p/go-libp2p-pubsub](https://github.com/libp2p/go-libp2p-pubsub) from 0.8.1 to 0.9.3. - [Release notes](https://github.com/libp2p/go-libp2p-pubsub/releases) - [Commits](https://github.com/libp2p/go-libp2p-pubsub/compare/v0.8.1...v0.9.3) --- updated-dependencies: - dependency-name: github.com/libp2p/go-libp2p-pubsub dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * Small adaptation due to dependency change --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Negovanović * Bump google.golang.org/grpc from 1.50.1 to 1.54.0 (#1396) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.50.1 to 1.54.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.50.1...v1.54.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/multiformats/go-multiaddr from 0.7.0 to 0.9.0 (#1394) Bumps [github.com/multiformats/go-multiaddr](https://github.com/multiformats/go-multiaddr) from 0.7.0 to 0.9.0. - [Release notes](https://github.com/multiformats/go-multiaddr/releases) - [Commits](https://github.com/multiformats/go-multiaddr/compare/v0.7.0...v0.9.0) --- updated-dependencies: - dependency-name: github.com/multiformats/go-multiaddr dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Remove manifest init step from network bootstrap workflow (#1389) * Remove manifest init step from bootstraping * Merge premine-validators with premine flag in genesis command * Remove event tracker start blocks flag from genesis cmd * Premine validators fix * Add comment * Rename initcontracts to deploy * Print JSON RPC address to rootchain deployment * Remove manifest command from cluster script * Remove leftover manifest flag and update docs * Fix MD violations in the Regenesis procedure doc * Merge logical conditions * Address comments * Address comment * Handle all errors when validating genesis path in the rootchain deploy cmd * Allowlist package refactor and blocklist implementation (#1388) * Allowlist package refactor and blocklist implementation This is a refactor of the allowlist package to make it more generic as it's now used for both allowlist and blocklist. It also adds the blocklist implementation. * Bump golang version to 1.19 (#1402) * Bump golang version to 1.19 * Update docs, Dockerfile and goreleaser version * Bump github.com/hashicorp/vault/api from 1.8.2 to 1.9.1 (#1405) Bumps [github.com/hashicorp/vault/api](https://github.com/hashicorp/vault) from 1.8.2 to 1.9.1. - [Release notes](https://github.com/hashicorp/vault/releases) - [Changelog](https://github.com/hashicorp/vault/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/vault/compare/v1.8.2...v1.9.1) --- updated-dependencies: - dependency-name: github.com/hashicorp/vault/api dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump go.etcd.io/bbolt from 1.3.6 to 1.3.7 (#1197) Bumps [go.etcd.io/bbolt](https://github.com/etcd-io/bbolt) from 1.3.6 to 1.3.7. - [Release notes](https://github.com/etcd-io/bbolt/releases) - [Commits](https://github.com/etcd-io/bbolt/compare/v1.3.6...v1.3.7) --- updated-dependencies: - dependency-name: go.etcd.io/bbolt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * ERC 1155 tokens bridge integration (#1332) * Generate ERC1155 bindings * Initialize contracts * Deposit ERC1155 tokens * Withdraw ERC1155 tokens * ERC1155 E2E test * Rename withdraw result * Provide corret child predicate address to the root predicate * Pass E2E test * Refactor commands and E2E test a bit * Simplifications * Simplify ERC 20 bridge commands * Address comment * Comment * Move disabled root predicate dummy address to a const * Update SC spec * Fix ERC-1155 bridge e2e test * Regenerate SC without logs * Allow usage of localstack AWS SSM Parameter Store (#1327) * allow aws localstack connection * fix linter * ERC 721 tokens bridge integration (#1348) * Integrate ERC 721 * Simplify ERC721 parameters * Fix initialization of ChildERC721Predicate contract * Minor fixes * More fixes... * Pass e2e test * Sanitize smart contracts from debug logs * Add owner of assertions for rootchain ERC 721 * Use constants for default JSON RPC addresses * Rebase fix * WriteFailedReceipt removed (#1403) * WriteFailedReceipt removed Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Bump cloud.google.com/go/secretmanager from 1.8.0 to 1.10.0 (#1102) Bumps [cloud.google.com/go/secretmanager](https://github.com/googleapis/google-cloud-go) from 1.8.0 to 1.10.0. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/dlp/v1.8.0...asset/v1.10.0) --- updated-dependencies: - dependency-name: cloud.google.com/go/secretmanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#1419) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.1 to 1.8.2. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.1...v1.8.2) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/spf13/cobra from 1.6.1 to 1.7.0 (#1416) Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.6.1 to 1.7.0. - [Release notes](https://github.com/spf13/cobra/releases) - [Commits](https://github.com/spf13/cobra/compare/v1.6.1...v1.7.0) --- updated-dependencies: - dependency-name: github.com/spf13/cobra dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Resolve todo comments in json rpc test (#1400) * Resolve todo comments in json rpc test * Bump golang.org/x/tools from 0.6.0 to 0.8.0 (#1414) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.6.0 to 0.8.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.6.0...v0.8.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * enabling nightly builds - nightly devnets & loadtests (#1359) * DVT-561 Add nightly build loadtest workflow * keep state for now * add loadtest to the nightly flow * trigger with PR * fix input runner situation * add some comments * rename * added output of load test to the nightly build notification * changes to the nightly flow for new edge version * more changes for the new template * fix to work with the latest version of edge * change branch to develop * do not build manual PR * Bump github.com/umbracle/fastrlp (#1413) Bumps [github.com/umbracle/fastrlp](https://github.com/umbracle/fastrlp) from 0.0.0-20220527094140-59d5dd30e722 to 0.1.0. - [Release notes](https://github.com/umbracle/fastrlp/releases) - [Commits](https://github.com/umbracle/fastrlp/commits/v0.1.0) --- updated-dependencies: - dependency-name: github.com/umbracle/fastrlp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump golang.org/x/crypto from 0.6.0 to 0.8.0 (#1415) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.6.0 to 0.8.0. - [Release notes](https://github.com/golang/crypto/releases) - [Commits](https://github.com/golang/crypto/compare/v0.6.0...v0.8.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Implement EIP-1559 feature (#1120) * Utilize typed atomics (#1407) * Utilize atomic.Bool * Use atomic.Pointer * Address comments * Cleanup `build` and `fuzz-test` GH workflows (#1410) * Remove redundant steps and add names to steps which were missing it * Add workflow_dispatch to E2E tests and property tests * Remove helper scripts from git index * fix for nightly load test - unit test not working (#1430) * remove manual flow for nightly load test * output fix * fix nightly.yml merge error * Fix txpool unit tests (#1429) * Enable all forks at genesis and add unit test which checks that dynamic fee tx gets rejected if london hardfork is not enabled * Minor change * Fix * Add precompiles for Bridge Allow/Block lists (#1422) * Bump github.com/envoyproxy/protoc-gen-validate from 0.9.1 to 1.0.0 (#1428) Bumps [github.com/envoyproxy/protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate) from 0.9.1 to 1.0.0. - [Release notes](https://github.com/envoyproxy/protoc-gen-validate/releases) - [Changelog](https://github.com/bufbuild/protoc-gen-validate/blob/main/.goreleaser.yaml) - [Commits](https://github.com/envoyproxy/protoc-gen-validate/compare/v0.9.1...v1.0.0) --- updated-dependencies: - dependency-name: github.com/envoyproxy/protoc-gen-validate dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/dave/jennifer from 1.6.0 to 1.6.1 (#1420) Bumps [github.com/dave/jennifer](https://github.com/dave/jennifer) from 1.6.0 to 1.6.1. - [Release notes](https://github.com/dave/jennifer/releases) - [Commits](https://github.com/dave/jennifer/compare/v1.6.0...v1.6.1) --- updated-dependencies: - dependency-name: github.com/dave/jennifer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add burn contract address in the cluster script (#1441) * fix broken unit test due to changed loadtest inputs (#1432) * revert loadtest argument variables * fix: rpc_url.txt file name * --burn-contract * keep manual flow in for the time being * final test on manual flow * block out manual flow * Update .github/workflows/manual.deploy.nightly.devnet.yml Co-authored-by: Victor Castell --------- Co-authored-by: Victor Castell * fix the unit test (#1444) * add runner name * add back runner workflow call input * disable manual flow and fix nightly.yml * Bump google.golang.org/grpc from 1.53.0-dev to 1.56.0-dev (#1437) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.53.0-dev to 1.56.0-dev. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.53.0-dev...v1.56.0-dev) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pgregory.net/rapid from 0.5.5 to 0.5.7 (#1451) Bumps [pgregory.net/rapid](https://github.com/flyingmutant/rapid) from 0.5.5 to 0.5.7. - [Release notes](https://github.com/flyingmutant/rapid/releases) - [Commits](https://github.com/flyingmutant/rapid/compare/v0.5.5...v0.5.7) --- updated-dependencies: - dependency-name: pgregory.net/rapid dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Disable london hardfork if burn contract address is not provided (#1454) * Fix test timeout related to min connected peers (#1443) * TxnType is not returned in JSON-RPC response (#1440) * bug: returning txn.Type in rpc response * tests: TxType being read as argUint64 * formatting: linting fixes * tests: dyanamic tx * [RFC-201/205] Staking and validator storage rework (#1442) * Use rework branch on core-contracts * EVM-578: Deploy new contracts for staking and supernets (#1368) * Deploy root contracts * New child contracts deployment * Lint fix * nil reference exception fix * Comments fix * Rebase fix * [RFC-201/205]: EVM-596-Change whitelist and register commands (#1404) * Change whitelist and register commands * Build fix * Lint fix * Include submodule fix * Remove leftover const * Minor change * Minor updates * Check error before checking doesMatch flag * Add private key flag to whitelist command * two new GetXYZFromSecret methods * Change whitelist command for secrets * Lint fix --------- Co-authored-by: Stefan Negovanović Co-authored-by: Igor Crevar * [RFC-201/205]: EVM-603-Register supernet and child chain (#1406) * Register child chain to StakeManager * Lint fix * Small fix * Comments fix * [RFC-201/205]: EVM-606-Change stake command (#1408) * Change stake command * Build fix * Bring commands back to polybft command * Validate jsonRPC address * Comments fix * Build fix * Lint fix * [RFC-201/205]: EVM-608-Supernet command (#1409) * Supernet command * Use GetECDSAKey in whitelist command * Validate jsonRPC address * Comments fix * Comments fix * Rebase fix * [RFC201/205]: EVM-613-Change validator info command (#1421) * Change validator info command * Lint fix * [RFC-201/205]: EVM-582-Validate validator set delta (#1423) * Validate validator set delta * Lint fix * Remove comment * Add test * [RFC-201/205]: EVM-580-Update validator set in stake manager (#1431) * Initial changes * Lint fix * Comments fix * Comments fix * Remove comment * Comments fix * Improve sorted map * Comments fix * Lint fix * Add comments in code * Comments fix * New UT * Lint fix * Call stakeManager in consensus runtime * Testing deterministic behavior of sort by stake * simple changes * even simplier things * different stakeMap and some refactoring * lower number of execution times for test * fix --------- Co-authored-by: Igor Crevar * [RFC-201/205]: EVM-619-Commit-epoch-on-new-ValidatorSet-contract (#1436) * Initial changes * Change withdraw command * Unstake command change * Remove ChildValidatorSet * Deploy MockRewardContract * Deploy contract fix * Lint fix * Fix sc_integration_test * Separate unstake and withdraw * Comments fix * [RFC-201/205]: EVM-622-Save full validator set in db (#1445) * Save full validator set in db * Lint fix * Fix * Test fix * validatorStakeMap refactor * lint fix --------- Co-authored-by: Igor Crevar * [RFC-201/205]: EVM-579-Change deployment steps in e2e tests (#1446) * Add whitelist and register validator steps to e2e tests * Initial staking on genesis * Finalize genesis set on supernet manager * Parallelize register and stake commands * Lint fix * Small optimization * Comments fix * Return negative case MakeKOSKSignature test * Lint fix * [RFC-201/205]: Reward token configuration (#1453) * New init of contracts * Reward token configuration * Rebase fix * Lint fix * Validate wallet amount in genesis * Comments fix * Comments fix * Comments fix * Return chainId in KOSK signature * Fix KOSK signature * [RFC-201/205] E2E test fixing (#1452) * WithoutBridge * fix fund command test * Remove WithBridge invocation * Rename error message * Rename to initializeNew (unblock whitelist) * kosk refactor * Kosk key fix * Lint fix * Kosk signature print * Remove chainID from register command * Remove leftovers and lint fixes * Remove chain-id flag from register validator command * Remove feat-polybft-release for core-contracts submodule * Remove delegation e2e test * GetValidatorInfo refactor * Remove comments * Latest SC spec * Leftover and comment * Fix Test_MakeKOSKSignature * Fix GetValidatorInfo, partially fix stake function * RewardPool updates * Withdraw child and withdraw root functions, obsolete e2e test with delegate * Increase timeout to 1.5h * Lint fix * Register and white list validators * Fix typo * ChangeVotingPower test fix * Lint fix * Fund per validator * Unstake test fix * amount should be big.Int * Update SCs and lint fix * Fix TestE2E_Consensus_MintableERC20NativeToken * Fix TestE2E_Consensus_Validator_Unstake * Unstake test fix * Fix RegisterValidator test * Lint fix * ChangeVotingPower test modification * TestIntegration_CommitEpoch fix * Fix TestE2E_Bridge_ChangeVotingPower * Minor fixes * Fix TestE2E_Bridge_ChangeVotingPower (part 2) * Update smart contracts * Remove commented code * RFC-201-205 Stake manager db fix (#1457) * stake manager db fix * bls key * Fix with Data field error on logs * Fix timeout * Fix test timeout * Copy data array * Remove log copying from bindings generator * Wait for epoch ending block in ChangeVotingPower e2e test * Persist initial validator set as epoch id 0 --------- Co-authored-by: Goran Rojovic Co-authored-by: Stefan Negovanović * Update README --------- Co-authored-by: Stefan Negovanović Co-authored-by: Goran Rojovic * Update stake in genesis based on finalized stake on StakeManager * Lint fix * Remove init function from consensus_test.go * Small code cleanup * Reward config fix * E2E test for custom reward token * Lint fix * New stake manager UTs --------- Co-authored-by: Stefan Negovanović Co-authored-by: Igor Crevar Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Remove AddLog function and add comments (#1465) * Integrate bridge access list contracts (#1456) * Integrate AccessLists predicates In the same address as the alternative ERC20/721/1155 Predicates * New docker login for release * Relase action * Fix secrets * Fix release * Fix release * Global DOCKER_CONFIG * Parallelize bootstrap rootchain CLI commands (#1468) * Paralelize fund command * Paralelize rootchain contract deployment * Parallelize rootchain contracts initialization * Decrease timeout to 1h * Rootchain CLI commands parallelization follow up (#1473) * Small refactor of IsValidAddress * Output successful results even in case of errors for rootchain fund and rootchain deploy commands * Misspelling fix * Remove leftover * Filter out nil results * Make error msg more verbose * Fix timeout in register validator e2e test * Provide mintable parameter as a part of native token config (#1472) * Provide mintable parameter as a part of native token config * Change mintable flag to boolean and make it mandatory * Minor change * Remove check for zerohash (#1481) * Remove bridge allow/block list admin vars (#1482) * Specific error for bridge test * Remove BridgeAllowListAdmin BridgeBlockListAdmin param It's redundant as we already have all necessary data in chain config. * Update core-contracts branch * Bump golang.org/x/sync from 0.1.0 to 0.2.0 (#1480) Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.1.0 to 0.2.0. - [Commits](https://github.com/golang/sync/compare/v0.1.0...v0.2.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * nightly with v0.9 (#1484) * nightly with v0.9 * add the premine wallet * back to main branch * remove manual flow * Explicitly notify about chain id usage (#1494) Include comment in flag help and verify it when building genesis for Polybft * update README for Edge v0.9.0 (#1498) * Bump github.com/prometheus/client_golang from 1.15.0 to 1.15.1 (#1478) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.15.0 to 1.15.1. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.15.0...v1.15.1) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump gopkg.in/DataDog/dd-trace-go.v1 from 1.49.1 to 1.50.1 (#1479) Bumps gopkg.in/DataDog/dd-trace-go.v1 from 1.49.1 to 1.50.1. --- updated-dependencies: - dependency-name: gopkg.in/DataDog/dd-trace-go.v1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump golang.org/x/tools from 0.8.0 to 0.9.1 (#1486) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.8.0 to 0.9.1. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.8.0...v0.9.1) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix RLP marshal byte array and enhancements to stake manager (#1461) * different stake in stake manager handling + marshal fix + additional logs * cr fixes * additional * cr fix * Fix timeout in test * new fastrlp * Use NewBytes instead of NewCopyBytes as it is wrapper around NewCopyBytes * Use NewCopyBytes in rlp_marshal.go --------- Co-authored-by: Igor Crevar Co-authored-by: Goran Rojovic Co-authored-by: Stefan Negovanović * Bump cloud.google.com/go/secretmanager from 1.10.0 to 1.10.1 (#1490) Bumps [cloud.google.com/go/secretmanager](https://github.com/googleapis/google-cloud-go) from 1.10.0 to 1.10.1. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/kms/v1.10.0...kms/v1.10.1) --- updated-dependencies: - dependency-name: cloud.google.com/go/secretmanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/envoyproxy/protoc-gen-validate from 1.0.0 to 1.0.1 (#1488) Bumps [github.com/envoyproxy/protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate) from 1.0.0 to 1.0.1. - [Release notes](https://github.com/envoyproxy/protoc-gen-validate/releases) - [Changelog](https://github.com/bufbuild/protoc-gen-validate/blob/main/.goreleaser.yaml) - [Commits](https://github.com/envoyproxy/protoc-gen-validate/compare/v1.0.0...v1.0.1) --- updated-dependencies: - dependency-name: github.com/envoyproxy/protoc-gen-validate dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump golang.org/x/crypto from 0.8.0 to 0.9.0 (#1489) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.8.0 to 0.9.0. - [Commits](https://github.com/golang/crypto/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Extracted validator related structures into consensus/polybft/validator package (#1493) * Extracted validator related structures into consensus/polybft/validator package * Extracted ValidatorSetDelta tests into separate file * Restore running edge in local (#1502) * Restore cluster script * Additional header validations (#1508) Additional header validations Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Fix `TestProperty_DifferentVotingPower` by providing randomized stake amounts (#1507) * Fix test by providing randomized stake amount to different validators * Provide count flag instead of timeout * Provide rapid.checks flag * Fix `eth_getCode` for non-empty accounts without code (#1474) * Fix eth_getCode for non-empty accounts without code (#1238) * Fix and debugging logs * remove debugging logs * Move to types.EmptyCodeHash * nit --------- Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Lint fix * Test get code for empty code hash Foo * Cleanups * Simplify * Add comment in test * Add test for SetCode and GetCode functions --------- Co-authored-by: Trevor Porter * Fix Lint GH workflow (#1512) * Remove ignored branches and increase timeout * Broader triggers * Add verbose output * Bump cloud.google.com/go/secretmanager from 1.10.0 to 1.10.1 (#1505) Bumps [cloud.google.com/go/secretmanager](https://github.com/googleapis/google-cloud-go) from 1.10.0 to 1.10.1. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/kms/v1.10.0...kms/v1.10.1) --- updated-dependencies: - dependency-name: cloud.google.com/go/secretmanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Differentiate `chain-id` and `supernet-id` (#1521) * Differentiate chain id and supernet id * Small change * De-clutter devnet/testnet deployment workflows (#1514) * Remove build and push container from devnet deployment workflow * Remove build and publish docker container from devnets deployment workflows * Remove unit test execution from devnets deployment workflows * Fix indentation and add events to pull request trigger (#1526) * Update Ethereum tests spec to v10.4 (#1466) * Add common.RetryForever() and use for concurrent sync operations (#1503) * Add common.RetryForever() and use for concurrent block/event synchronisation operations that can take a long time and fail at any point. * EVM-666: Fix `eth_getLogs` index issue (#1533) * Fix logIndex value setting * Comments fix * Exclude ethereum tests folder from sonar * Change chain ID to supernet ID (#1536) * Move dispatcher failed dispatch method from ERROR to WARN log severity (#1525) * fix benchmarking results (#1522) * manual deploy nightly * set up test devnet * run load test * run ansible * one-liner * final run with properly premined test account * delete the test state and do final run * remove 1559 stuff that is not needed for nightly * Bump github.com/stretchr/testify from 1.8.2 to 1.8.3 (#1532) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.3. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.3) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix cluster script (#1539) * EVM-525 Write load test for adding peers (#1537) * Allow min commitment of single state sync event (#1475) * Allow min commitment of single state sync event * Fix assertion in checkStateSyncResultLogs * Change assertions so that multiple deposit batches test can be run independently * Remove unnecesary cast * Add UT * Reorganize files * Fix UT * Remove constant * Fix --------- Co-authored-by: Goran Rojovic * Renamed base fee json field (#1538) * Add a flag to `deploy` command for stake manager address (#1520) * Do not deploy stake manager if already deployed * Command for deploying stake manager * Parallel deployment in stake-manager-deploy command * Comments fix * Added Stake Manager fuzz tests (#1500) * Added Stake Manager fuzz tests * Changed helper functions to receive interface common to T, B, and F * Use json.Unmarshal instead of go_fuzz_utils. Added seed corpus * CR changes * Introduce BASEFEE opcode (#1469) * Modify rootchain command to use the provided private key to fund validators (#1540) * Modified rootchain command to use the provided private key to fund validators * EVM-665 No Log Bloom (#1550) * EVM-671 Fix block tracker WithBlockMaxBacklog for state_sync_relayer (#1543) * Reject future blocks (#1509) * Additional header validations * blocks from the future forbidden * lint fix * log improved * ut fixed * ut fixed * UT fixes * Added block time drift in the genesis command * CR changes --------- Co-authored-by: Stefan Negovanović Co-authored-by: Marko Jelaca * Fix Subnet Genesis Finalize (#1545) * Revert to previous Umbracle to fix eth_call. Attempt to make finalize gensis idempotent so it can be re-run. * Pull in fix from ethgo. * Update cluster script for new stake manager deploy flow (#1553) * Fix `eth_getStorageAt` always returning 0 (#1558) * fix eth_getStorageAt always returning 0 (#1546) * Fix failing unit tests --------- Co-authored-by: typestring <23285275+typestring@users.noreply.github.com> * Return hex encoded number in eth_getBlockTransactionCountByNumber endpoint (#1559) * Write minValidatorCount to genesis.json (#1547) * Write the value from the genesis '--min-validator-count' flag to the genesis.json output * Update comment on MinValidatorSetSize Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> --------- Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> * Deploy child chain mintable predicates (#1516) * Introduce mintable predicates * Introduce new contracts and deploy rootchain ones * Simplify and unify all initializers to use initContract function * Update SC spec * Initialize child chain mintable predicates * Rebase fix * Remove dead code * Bump github.com/hashicorp/vault/api from 1.9.1 to 1.9.2 (#1562) Bumps [github.com/hashicorp/vault/api](https://github.com/hashicorp/vault) from 1.9.1 to 1.9.2. - [Release notes](https://github.com/hashicorp/vault/releases) - [Changelog](https://github.com/hashicorp/vault/blob/main/CHANGELOG.md) - [Commits](https://github.com/hashicorp/vault/compare/v1.9.1...v1.9.2) --- updated-dependencies: - dependency-name: github.com/hashicorp/vault/api dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Introduce access list child chain mintable predicates (#1549) * Introduce ACL mintable predicates * Deploy and initialize ACL miintable predicates * Fix e2e tests * Fix dependabot PRs reviewers (#1563) * Bump gopkg.in/DataDog/dd-trace-go.v1 from 1.50.1 to 1.51.0 (#1555) Bumps gopkg.in/DataDog/dd-trace-go.v1 from 1.50.1 to 1.51.0. --- updated-dependencies: - dependency-name: gopkg.in/DataDog/dd-trace-go.v1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Restore logs output functionality in cluster script (#1561) * Remove legacy contract deployment whitelisting mechanism (#1556) * Remove legacy contract deployment whitelisting mechanism * Lint fix * Rename unit test * Additional EIP-1559 transaction unit tests * Introduce a new version of go ibft (#1392) introduce a new version of go-ibft (HasQuorum is a part of go-ibft) Co-authored-by: Stefan Negovanović * Bump golang.org/x/tools from 0.9.1 to 0.9.2 (#1575) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.9.1 to 0.9.2. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.9.1...v0.9.2) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/stretchr/testify from 1.8.3 to 1.8.4 (#1574) Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.3 to 1.8.4. - [Release notes](https://github.com/stretchr/testify/releases) - [Commits](https://github.com/stretchr/testify/compare/v1.8.3...v1.8.4) --- updated-dependencies: - dependency-name: github.com/stretchr/testify dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump pgregory.net/rapid from 0.5.7 to 0.6.1 (#1573) Bumps [pgregory.net/rapid](https://github.com/flyingmutant/rapid) from 0.5.7 to 0.6.1. - [Commits](https://github.com/flyingmutant/rapid/compare/v0.5.7...v0.6.1) --- updated-dependencies: - dependency-name: pgregory.net/rapid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump cloud.google.com/go/secretmanager from 1.10.1 to 1.11.0 (#1572) Bumps [cloud.google.com/go/secretmanager](https://github.com/googleapis/google-cloud-go) from 1.10.1 to 1.11.0. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/kms/v1.10.1...kms/v1.11.0) --- updated-dependencies: - dependency-name: cloud.google.com/go/secretmanager dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * EVM-677: Fix log index issue on `eth_getTransactionReceipt` (#1576) * Fix log index issue * Comments fix * jesse/fix-nightly-latest (#1570) * jesse/fix-nightly-latest * fix nightly script * enhance script * Revise and fix cluster script when ran in docker mode (#1571) * Return Revert result as Data (#1566) * Return Revet result as Data This allows returning custom revert errors from solidity, they are ABI encoded functions that can represent rich and gas efficient revert messages. * EVM-607 Hard-forking PoC (#1544) * EVM-519 Resolve slashing related TODOs in the code (#1581) * Prevent ACL admins to remove themselves (#1578) * As an admin I can not change my own role * EVM-523 Fix race condition in gas estimation (#1583) * Bump pgregory.net/rapid from 0.6.1 to 0.6.2 (#1586) Bumps [pgregory.net/rapid](https://github.com/flyingmutant/rapid) from 0.6.1 to 0.6.2. - [Commits](https://github.com/flyingmutant/rapid/compare/v0.6.1...v0.6.2) --- updated-dependencies: - dependency-name: pgregory.net/rapid dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Child chain mintable predicates E2E tests (#1560) * Simplify helper bridge commands * Prevent mapping childchain mintable native token on non-mintable predicate * Provide stake token address to rootchain deploy command * WIP * Revert not needed changes * Mintable native token bridge transfer E2E test * Wrap up bridge native erc20 mintable e2e test * Update smart contracts spec * Register bridge common flags at once * Provide stake token address where missing * Fix E2E tests * Remove isExitEventProcessed helper function * E2E tests for access list mintable predicates * ERC-721 tokens bridging E2E test WIP * Fix warnings * Decouple minter and sender key in deposit commands * Update README * ERC-721 owner of helper function * Fix deposit commands * Update to the latest SC spec and remove not needed bindings * Wrap up ERC721 tokens bridging E2E test * Fix unit test * Comment * Comments * Change exit event ids from string to big int in deposit and withdraw results * Update to the latest SC spec * Fix race condition * Introduce buffered channel * Consolidate bridge transaction result structs (#1584) * Consolidate bridge transaction result into single struct * Update SC to the latest spec * Fix * Add json tag to title field * fixed error handling for op code CREATE2 (#1587) * EVM-675 Implement additional metrics (#1564) * Consensus metrics * P2P and Syncer metrics * TxPool metrics * JsonRpc metrics * Small fix * Lint fix * Comments fix * Comments fix * Comments fix * Transaction relayer fetching gas price from current eth client instead of using hardcoded value (#1589) * modified txRelayer to fetch gasprice from current eth client instead of hardcoded one * fetch gas price only if default is 0 * Don't set gas price explicitly when using tx relayer * unexported defaultGasPrice constant --------- Co-authored-by: adirola * EVM-437 Batch calls over websockets not working properly (#1588) * Extract reward token approve transaction to a separate function (#1594) * Remove Prometheus metrics expiration time (#1592) * Remove Prometheus metrics expiration time * Minor param related fixes (#1596) * tx pool debug level logging optimizations (#1609) * Update smart contracts (#1602) * Update smart contracts * Generate SC bindings * [EVM-528]: Resolve TODOs in state code (#1597) * Resolve TODOs * Try to reuse single arena pool instance * Get rid of some panics in state/txn.go * Fix block builder UT --------- Co-authored-by: Stefan Negovanović * Improve TestStateSyncerManager_EventTracker_Sync (#1608) * jesse/fix-nightly-v1.0.0-rc1 (#1600) * jesse/fix-nightly-v1.0.0-rc1 * add back wallet creation * setup node * install node * remove node and npm stuff * Allow providing mintable native token owner account (#1603) * Allow providing mintable native token owner account * Fix test * Fix * Add extractNativeTokenMetadata unit test * Introduce new version of go-ibft (#1611) * Fix (#1612) * [EVM-685]: Remove premining of validator balances on L2 for non-mintable tokens (#1598) * Remove premining of balance of validators on L2 * Don't allow premine if native token is non-mintable * E2E tests fix * Rebase fix * Lint fix * Fix (#1614) * remove unnecessary flags (#1615) * remove unnecessary flags * add back native token config as its required for staking * EVM-689 The impact of database saving failures on Stake Manager functionality (#1607) * Print child token address as part of deposit commands (#1616) * fix deposit_erc20 send with channel * Extract child token address and print it in the bridge deposit command * Filter nil exit event ids * Remove Event interface --------- Co-authored-by: Igor Crevar * Bump pgregory.net/rapid from 0.6.2 to 1.0.0 (#1613) Bumps [pgregory.net/rapid](https://github.com/flyingmutant/rapid) from 0.6.2 to 1.0.0. - [Release notes](https://github.com/flyingmutant/rapid/releases) - [Commits](https://github.com/flyingmutant/rapid/compare/v0.6.2...v1.0.0) --- updated-dependencies: - dependency-name: pgregory.net/rapid dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Validate commitment bridge transactions for finalized blocks (#1599) * Cluster script fix (#1622) * [EVM-706]: Provide native token initial total supply (#1623) * Add initial total supply to native erc20 tokens * Comments fix * UT fix * allow bridge ACLs to be updated without checking if sender has permission to send other txs (#1625) * feat: match runtime errors with geth (#1619) * feat: match runtime errors with geth * chore: linting fixes * Bump google.golang.org/grpc from 1.55.0 to 1.56.0 (#1635) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.55.0 to 1.56.0. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.55.0...v1.56.0) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/prometheus/client_golang from 1.15.1 to 1.16.0 (#1634) Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.15.1 to 1.16.0. - [Release notes](https://github.com/prometheus/client_golang/releases) - [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md) - [Commits](https://github.com/prometheus/client_golang/compare/v1.15.1...v1.16.0) --- updated-dependencies: - dependency-name: github.com/prometheus/client_golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump golang.org/x/sync from 0.2.0 to 0.3.0 (#1632) Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.2.0 to 0.3.0. - [Commits](https://github.com/golang/sync/compare/v0.2.0...v0.3.0) --- updated-dependencies: - dependency-name: golang.org/x/sync dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/libp2p/go-libp2p-kbucket from 0.5.0 to 0.6.3 (#1633) Bumps [github.com/libp2p/go-libp2p-kbucket](https://github.com/libp2p/go-libp2p-kbucket) from 0.5.0 to 0.6.3. - [Release notes](https://github.com/libp2p/go-libp2p-kbucket/releases) - [Commits](https://github.com/libp2p/go-libp2p-kbucket/compare/v0.5.0...v0.6.3) --- updated-dependencies: - dependency-name: github.com/libp2p/go-libp2p-kbucket dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump golang.org/x/tools from 0.9.2 to 0.10.0 (#1631) Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.9.2 to 0.10.0. - [Release notes](https://github.com/golang/tools/releases) - [Commits](https://github.com/golang/tools/compare/v0.9.2...v0.10.0) --- updated-dependencies: - dependency-name: golang.org/x/tools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [EVM-701]: Validate `ExitRootHash` in `CheckpointData` (#1638) * Initial changes * Comments fix * Modified the cluster script to log message when jq is not installed (#1626) * EVM-709 Log contract deployment transaction details (#1627) * Log contract deployment transaction details * Changed log message * Changed log message * Log transaction used gas * Bump Go version to 1.20 (#1636) * Bump Go version to 1.20 * refernece the latest ethgo (#1641) * [EVM-697]: Implement `eth_maxPriorityFeePerGas` (#1629) * Initial change * UTs * Small fix * Small fix * Comments fix * Comments fix * Comments fix * Comments fix * Fix (#1646) * e2e fixed (#1639) * Execute nightlies on demand (#1650) * Reference latest ethgo (#1653) * set latest ethgo * Remove default mock tokens deployment from rootchain deploy command (#1642) * Remove default mock tokens deployment from rootchain deploy command * Fix E2E tests * Remove unused flag names * EVM-713 Fork manager params (#1645) * go.mod fix (#1658) * TestPeerConnectionUpdateEventCh (#1662) * Ensure that the same child token addresses are calculated on both chains (#1621) * Provide correct addresses for child token templates to predicates * Assert that rootTokenToChildToken exists in the provided predicate ABI * Bump google.golang.org/grpc from 1.56.0 to 1.56.1 (#1655) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.0 to 1.56.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.56.0...v1.56.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump gopkg.in/DataDog/dd-trace-go.v1 from 1.51.0 to 1.52.0 (#1659) Bumps gopkg.in/DataDog/dd-trace-go.v1 from 1.51.0 to 1.52.0. --- updated-dependencies: - dependency-name: gopkg.in/DataDog/dd-trace-go.v1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump cloud.google.com/go/secretmanager from 1.11.0 to 1.11.1 (#1643) Bumps [cloud.google.com/go/secretmanager](https://github.com/googleapis/google-cloud-go) from 1.11.0 to 1.11.1. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/documentai/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/kms/v1.11.0...asset/v1.11.1) --- updated-dependencies: - dependency-name: cloud.google.com/go/secretmanager dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * added jq dependency (#1666) * Print additional fields in the withdraw CLI command (#1663) * Deploy burn contract by default on EIP-1559 enabled (#1648) * Update README for release (#1644) * Apply trace patch for CALL trace issue (#1654) * Bump google.golang.org/protobuf from 1.30.0 to 1.31.0 (#1665) Bumps google.golang.org/protobuf from 1.30.0 to 1.31.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump github.com/envoyproxy/protoc-gen-validate from 1.0.1 to 1.0.2 (#1670) Bumps [github.com/envoyproxy/protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate) from 1.0.1 to 1.0.2. - [Release notes](https://github.com/envoyproxy/protoc-gen-validate/releases) - [Changelog](https://github.com/bufbuild/protoc-gen-validate/blob/main/.goreleaser.yaml) - [Commits](https://github.com/envoyproxy/protoc-gen-validate/compare/v1.0.1...v1.0.2) --- updated-dependencies: - dependency-name: github.com/envoyproxy/protoc-gen-validate dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Added DEBUG logs to executor in order to track allow and block lists (#1664) * Added DEBUG level log lines when the transaction or deployment allowlists are applied to reject a transaction * Added blank lines for linting * Fix flaky ERC721 and ERC1155 bridge tests (#1671) * Invoke estimate gas limit if gas limit not already provided (#1582) * Invoke estimate gas limit if gas limit not already provided * Added sender address in txn. Needed for estimateGasLimit * Fixed failing e2e tests * Provide fix gas limit for exit transaction (pass child chain mintable e2e test) * Fix failing E2E tests * uint64 to big.int change --------- Co-authored-by: Stefan Negovanović Co-authored-by: Igor Crevar * Upgraded script to check both dependencies and display all missing ones at the same time (#1667) --------- Signed-off-by: dependabot[bot] Co-authored-by: Sebastian Supreme <106926150+SebastianSupreme@users.noreply.github.com> Co-authored-by: Nemanja Nedic <93836814+Nemanja0x@users.noreply.github.com> Co-authored-by: Ferran Borreguero Co-authored-by: Serge Radinovich <47865535+sergerad@users.noreply.github.com> Co-authored-by: Stefan Negovanović <93934272+Stefan-Ethernal@users.noreply.github.com> Co-authored-by: Goran Rojovic <100121253+goran-ethernal@users.noreply.github.com> Co-authored-by: Victor Castell Co-authored-by: Igor Crevar Co-authored-by: Flavor Town <117117716+flavor-town@users.noreply.github.com> Co-authored-by: Nemanja0x Co-authored-by: Victor Castell Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Stefan Negovanović Co-authored-by: Kamil Paśko Co-authored-by: Jesse Lee Co-authored-by: Roman Behma <13855864+begmaroman@users.noreply.github.com> Co-authored-by: jhkimqd <125336262+jhkimqd@users.noreply.github.com> Co-authored-by: Rachit Sonthalia <54906134+rachit77@users.noreply.github.com> Co-authored-by: Goran Rojovic Co-authored-by: dusan-maksimovic <94966669+dusan-maksimovic@users.noreply.github.com> Co-authored-by: Trevor Porter Co-authored-by: Marko Jelača Co-authored-by: Paul O'Leary Co-authored-by: typestring <23285275+typestring@users.noreply.github.com> Co-authored-by: jp-imx <109574657+jp-imx@users.noreply.github.com> Co-authored-by: adirola Co-authored-by: Sameer C <2431304+lolchocotaco@users.noreply.github.com> Co-authored-by: Alejandro Criado-Pérez --- .github/dependabot.yml | 4 +- .github/workflows/build.yml | 21 +- .github/workflows/deploy.devnet.eph.yml | 49 - .github/workflows/deploy.devnet.yml | 49 - .github/workflows/deploy.nightly.devnet.yml | 278 +++ .github/workflows/deploy.testnet.yml | 49 - .github/workflows/e2e-polybft.yml | 21 +- .github/workflows/e2e.yaml | 26 +- .github/workflows/fuzz-test.yml | 38 + .github/workflows/lint.yml | 15 +- .github/workflows/loadtest.yml | 311 ++-- .../manual.deploy.nightly.devnet.yml | 31 + .github/workflows/nightly.yml | 134 +- .github/workflows/property-polybft.yml | 21 +- .github/workflows/release.yml | 21 +- .github/workflows/test.yml | 17 +- .gitmodules | 2 - .golangci.yml | 2 + Makefile | 26 +- README.md | 4 +- blockchain/blockchain.go | 85 +- blockchain/blockchain_test.go | 53 + blockchain/subscription.go | 25 +- blockchain/subscription_test.go | 58 + blockchain/testing.go | 15 +- chain/chain.go | 68 +- chain/chain_test.go | 47 - chain/params.go | 171 +- chain/params_test.go | 76 +- command/bridge/README.md | 9 +- command/bridge/bridge.go | 24 +- command/bridge/common/bridge_erc20_params.go | 29 - command/bridge/common/params.go | 264 +++ command/bridge/deposit/deposit_erc20.go | 327 ---- .../bridge/deposit/erc1155/deposit_erc1155.go | 312 ++++ command/bridge/deposit/erc20/deposit_erc20.go | 284 +++ .../bridge/deposit/erc721/deposit_erc721.go | 280 +++ command/bridge/exit/exit.go | 5 +- .../withdraw/erc1155/withdraw_erc1155.go | 193 +++ .../bridge/withdraw/erc20/withdraw_erc20.go | 171 ++ .../bridge/withdraw/erc721/withdraw_erc721.go | 171 ++ command/bridge/withdraw/withdraw_erc20.go | 253 --- command/default.go | 18 +- command/genesis/genesis.go | 172 +- command/genesis/params.go | 246 ++- command/genesis/params_test.go | 118 ++ command/genesis/polybft_params.go | 486 ++++-- command/genesis/utils.go | 85 +- command/helper/helper.go | 10 + command/ibft/switch/params.go | 1 + command/polybft/polybft_command.go | 32 +- command/polybftmanifest/manifest_init.go | 268 --- command/polybftsecrets/params.go | 29 - command/polybftsecrets/params_test.go | 12 +- command/polybftsecrets/result.go | 8 - command/polybftsecrets/utils.go | 9 +- command/regenesis/howtotest.md | 344 ++-- command/root/root.go | 4 - command/rootchain/README.md | 16 +- command/rootchain/deploy/deploy.go | 687 ++++++++ command/rootchain/deploy/deploy_test.go | 66 + command/rootchain/deploy/params.go | 53 + .../{initcontracts => deploy}/result.go | 24 +- command/rootchain/fund/fund.go | 198 ++- command/rootchain/fund/params.go | 87 +- command/rootchain/fund/result.go | 4 +- command/rootchain/helper/metadata.go | 202 ++- .../rootchain/initcontracts/init_contracts.go | 442 ----- .../initcontracts/init_contracts_test.go | 42 - command/rootchain/initcontracts/params.go | 32 - command/rootchain/registration/params.go | 45 + .../registration/register_validator.go | 121 +- command/rootchain/rootchain.go | 20 +- command/rootchain/staking/params.go | 57 + .../{sidechain => rootchain}/staking/stake.go | 111 +- command/rootchain/supernet/params.go | 69 + .../rootchain/supernet/stakemanager/params.go | 34 + .../stakemanager/stake_manager_deploy.go | 266 +++ command/rootchain/supernet/supernet.go | 332 ++++ command/rootchain/validators/params.go | 46 + .../validators/validator_info.go | 38 +- command/rootchain/whitelist/params.go | 62 + .../whitelist/whitelist_validators.go | 156 ++ command/rootchain/withdraw/params.go | 55 + .../withdraw/withdraw.go} | 81 +- command/server/config/config.go | 6 +- command/server/init.go | 13 - command/server/params.go | 6 +- command/server/server.go | 11 +- command/sidechain/helper.go | 63 +- command/sidechain/registration/params.go | 62 - command/sidechain/rewards/params.go | 39 + command/sidechain/rewards/rewards.go | 120 ++ command/sidechain/staking/params.go | 59 - command/sidechain/unstaking/params.go | 40 +- command/sidechain/unstaking/unstake.go | 80 +- command/sidechain/validators/params.go | 47 - command/sidechain/whitelist/params.go | 43 - command/sidechain/withdraw/params.go | 28 +- command/sidechain/withdraw/withdraw.go | 66 +- command/whitelist/deployment/deployment.go | 66 - command/whitelist/deployment/params.go | 162 -- command/whitelist/deployment/result.go | 32 - command/whitelist/show/params.go | 72 - command/whitelist/show/result.go | 20 - command/whitelist/show/show.go | 41 - command/whitelist/whitelist.go | 25 - consensus/consensus.go | 5 +- consensus/dev/dev.go | 23 +- consensus/dummy/dummy.go | 6 +- consensus/ibft/consensus_backend.go | 68 +- consensus/ibft/fork/fork.go | 26 +- consensus/ibft/fork/fork_test.go | 6 +- consensus/ibft/fork/hooks_test.go | 3 + consensus/ibft/ibft.go | 24 +- consensus/polybft/README.md | 122 +- consensus/polybft/block_builder.go | 26 +- consensus/polybft/block_builder_test.go | 160 ++ consensus/polybft/blockchain_wrapper.go | 33 +- consensus/polybft/checkpoint_manager.go | 5 +- consensus/polybft/checkpoint_manager_test.go | 35 +- consensus/polybft/consensus_metrics.go | 7 + consensus/polybft/consensus_runtime.go | 191 +- consensus/polybft/consensus_runtime_test.go | 252 +-- consensus/polybft/contracts_initializer.go | 282 ++- .../contractsapi/artifacts-gen/main.go | 126 +- .../polybft/contractsapi/bindings-gen/main.go | 359 +++- .../polybft/contractsapi/contractsapi.go | 1532 +++++++++++++---- .../polybft/contractsapi/contractsapi_test.go | 20 +- consensus/polybft/contractsapi/gen_sc_data.go | 56 +- consensus/polybft/contractsapi/helper.go | 23 +- consensus/polybft/contractsapi/init.go | 187 +- .../test-contracts/TestL1StateReceiver.json | 86 - .../test-contracts/TestL1StateReceiver.sol | 20 - .../test-contracts/TestRewardToken.json | 330 ++++ .../test-contracts/TestSimple.json | 39 + .../test-contracts/TestSimple.sol | 14 + .../test-contracts/TestWriteBlockMetadata.sol | 2 +- consensus/polybft/extra.go | 272 +-- consensus/polybft/extra_test.go | 478 ++--- consensus/polybft/fsm.go | 279 +-- consensus/polybft/fsm_test.go | 677 +++++--- consensus/polybft/handlers.go | 7 +- consensus/polybft/hash_test.go | 9 +- consensus/polybft/helpers_test.go | 80 +- consensus/polybft/mocks_test.go | 213 +-- consensus/polybft/polybft.go | 348 +++- consensus/polybft/polybft_config.go | 321 ++-- consensus/polybft/polybft_test.go | 102 +- consensus/polybft/proposer_calculator.go | 9 +- consensus/polybft/proposer_calculator_test.go | 122 +- consensus/polybft/runtime_helpers_test.go | 19 +- consensus/polybft/sc_integration_test.go | 359 ++-- consensus/polybft/signer/common.go | 15 +- consensus/polybft/signer/utils.go | 34 + consensus/polybft/signer/utils_test.go | 31 + consensus/polybft/stake_manager.go | 437 +++++ consensus/polybft/stake_manager_fuzz_test.go | 286 +++ consensus/polybft/stake_manager_test.go | 559 ++++++ consensus/polybft/state.go | 8 +- consensus/polybft/state_store_checkpoint.go | 12 +- consensus/polybft/state_store_epoch.go | 21 + consensus/polybft/state_store_epoch_test.go | 21 +- consensus/polybft/state_store_stake.go | 58 + consensus/polybft/state_store_stake_test.go | 51 + consensus/polybft/state_store_state_sync.go | 25 +- consensus/polybft/state_sync_commitment.go | 202 +++ .../polybft/state_sync_commitment_test.go | 178 ++ consensus/polybft/state_sync_manager.go | 34 +- consensus/polybft/state_sync_manager_test.go | 144 +- consensus/polybft/state_transaction.go | 203 +-- consensus/polybft/state_transaction_test.go | 176 +- .../statesyncrelayer/state_sync_relayer.go | 11 +- .../state_sync_relayer_test.go | 12 +- consensus/polybft/system_state.go | 96 +- consensus/polybft/system_state_test.go | 137 +- .../polybft/validator/genesis_validator.go | 97 ++ consensus/polybft/validator/test_helpers.go | 244 +++ .../{ => validator}/validator_metadata.go | 2 +- .../validator_metadata_test.go | 36 +- .../polybft/{ => validator}/validator_set.go | 21 +- .../polybft/validator/validator_set_delta.go | 144 ++ .../validator/validator_set_delta_test.go | 237 +++ .../{ => validator}/validator_set_test.go | 10 +- consensus/polybft/validators_snapshot.go | 14 +- consensus/polybft/validators_snapshot_test.go | 27 +- consensus/polybft/wallet/account.go | 50 +- contracts/system_addresses.go | 30 + core-contracts | 2 +- crypto/crypto.go | 4 - crypto/crypto_test.go | 7 - crypto/txsigner.go | 239 +-- crypto/txsigner_eip155.go | 99 ++ ...signer_test.go => txsigner_eip155_test.go} | 43 +- crypto/txsigner_frontier.go | 82 + crypto/txsigner_frontier_test.go | 29 + crypto/txsigner_london.go | 79 + crypto/txsigner_london_test.go | 145 ++ docker/README.md | 6 +- docker/local/Dockerfile | 2 +- docker/local/docker-compose.yml | 84 +- docker/local/polygon-edge.sh | 116 +- docs/bridge/sequences.md | 64 + e2e-polybft/e2e/acls_test.go | 415 +++++ e2e-polybft/e2e/allowlist_test.go | 109 -- e2e-polybft/e2e/bridge_test.go | 1418 +++++++++++---- e2e-polybft/e2e/burn_contract_test.go | 37 + e2e-polybft/e2e/consensus_test.go | 784 ++++----- e2e-polybft/e2e/helpers_test.go | 268 ++- e2e-polybft/e2e/jsonrpc_test.go | 308 ++++ e2e-polybft/e2e/migration_test.go | 20 +- e2e-polybft/e2e/network_test.go | 3 +- e2e-polybft/e2e/txpool_test.go | 187 +- e2e-polybft/framework/node.go | 6 +- e2e-polybft/framework/test-bridge.go | 416 ++++- e2e-polybft/framework/test-cluster.go | 420 +++-- e2e-polybft/framework/test-server.go | 165 +- e2e-polybft/property/property_test.go | 32 +- e2e/framework/config.go | 15 +- e2e/framework/testserver.go | 68 +- e2e/ibft_test.go | 7 +- e2e/jsonrpc_test.go | 115 +- e2e/pos_poa_switch_test.go | 8 +- e2e/pos_test.go | 135 +- e2e/transaction_test.go | 42 +- e2e/txpool_test.go | 111 +- forkmanager/fork.go | 87 + forkmanager/fork_manager.go | 301 ++++ forkmanager/fork_manager_test.go | 228 +++ gasprice/gasprice.go | 254 +++ gasprice/gasprice_test.go | 266 +++ go.mod | 227 ++- go.sum | 784 +++------ helper/common/common.go | 91 +- helper/common/common_test.go | 72 + helper/config/config.go | 25 - helper/keccak/pool.go | 10 + helper/predeployment/predeployment.go | 42 +- helper/tests/testing.go | 3 +- jsonrpc/codec.go | 27 +- jsonrpc/debug_endpoint_test.go | 52 +- jsonrpc/dispatcher.go | 153 +- jsonrpc/dispatcher_test.go | 106 +- jsonrpc/eth_blockchain_test.go | 88 +- jsonrpc/eth_endpoint.go | 146 +- jsonrpc/eth_endpoint_test.go | 149 +- jsonrpc/eth_state_test.go | 20 +- jsonrpc/filter_manager.go | 5 +- jsonrpc/filter_manager_test.go | 77 + jsonrpc/helper.go | 29 +- jsonrpc/helper_test.go | 98 +- jsonrpc/mocks_test.go | 4 + jsonrpc/testsuite/block-empty.json | 5 +- jsonrpc/testsuite/block-with-no-basefee.json | 22 + jsonrpc/testsuite/block-with-txn-bodies.json | 8 +- jsonrpc/testsuite/block-with-txn-hashes.json | 5 +- jsonrpc/testsuite/transaction-eip1559.json | 19 + jsonrpc/testsuite/transaction-pending.json | 3 +- jsonrpc/testsuite/transaction-sealed.json | 3 +- jsonrpc/txpool_endpoint.go | 16 + jsonrpc/types.go | 37 +- jsonrpc/types_test.go | 94 +- network/gossip.go | 32 +- network/gossip_test.go | 1 - network/server.go | 9 +- network/server_discovery.go | 7 +- network/server_identity.go | 2 - network/server_test.go | 9 +- scripts/README.md | 8 +- scripts/cluster | 235 ++- scripts/fuzzAll | 18 + secrets/awsssm/aws_ssm.go | 17 +- secrets/helper/helper.go | 63 +- secrets/helper/helper_test.go | 39 - secrets/local/local.go | 7 - secrets/secrets.go | 10 +- server/builtin.go | 14 +- server/config.go | 1 - server/server.go | 158 +- server/server_metrics.go | 5 +- sonar-project.properties | 4 +- state/executor.go | 420 ++++- state/executor_test.go | 156 ++ state/immutable-trie/snapshot.go | 9 +- state/immutable-trie/state.go | 4 + state/immutable-trie/state_test.go | 3 +- state/immutable-trie/trie.go | 9 +- .../addresslist.go} | 46 +- .../addresslist_test.go} | 60 +- .../{allowlist => addresslist}/genesis.go | 8 +- .../genesis_test.go | 4 +- state/runtime/evm/dispatch_table.go | 1 + state/runtime/evm/evm_fuzz_test.go | 193 +++ state/runtime/evm/evm_test.go | 4 +- state/runtime/evm/instructions.go | 20 +- state/runtime/evm/instructions_test.go | 51 + state/runtime/evm/opcodes.go | 4 + state/runtime/evm/state.go | 6 +- state/runtime/evm/state_test.go | 7 +- state/runtime/precompiled/precompiled.go | 2 - state/runtime/runtime.go | 49 +- state/runtime/tracer/structtracer/tracer.go | 89 +- .../tracer/structtracer/tracer_test.go | 154 +- state/state.go | 12 +- state/testing.go | 210 ++- state/txn.go | 89 +- state/txn_test.go | 14 +- syncer/client.go | 38 +- syncer/client_test.go | 6 +- syncer/service.go | 2 + syncer/syncer.go | 12 + syncer/types.go | 2 + tests/evm_test.go | 193 --- tests/state_test.go | 71 +- tests/testing.go | 391 +++-- tracker/event_tracker.go | 67 +- txpool/query.go | 11 +- txpool/{queue.go => queue_account.go} | 100 +- txpool/queue_priced.go | 149 ++ txpool/queue_priced_test.go | 326 ++++ txpool/slot_gauge.go | 7 +- txpool/txpool.go | 219 ++- txpool/txpool_test.go | 194 ++- txrelayer/txrelayer.go | 67 +- types/encoding.go | 10 +- types/header.go | 13 +- types/receipt.go | 32 +- types/rlp_encoding_test.go | 165 +- types/rlp_marshal.go | 59 +- types/rlp_unmarshal.go | 94 +- types/state_transaction.go | 135 ++ types/transaction.go | 129 +- types/types.go | 65 +- types/types_test.go | 46 +- validators/store/contract/contract_test.go | 10 +- 335 files changed, 24836 insertions(+), 11040 deletions(-) create mode 100644 .github/workflows/deploy.nightly.devnet.yml create mode 100644 .github/workflows/fuzz-test.yml create mode 100644 .github/workflows/manual.deploy.nightly.devnet.yml delete mode 100644 command/bridge/common/bridge_erc20_params.go create mode 100644 command/bridge/common/params.go delete mode 100644 command/bridge/deposit/deposit_erc20.go create mode 100644 command/bridge/deposit/erc1155/deposit_erc1155.go create mode 100644 command/bridge/deposit/erc20/deposit_erc20.go create mode 100644 command/bridge/deposit/erc721/deposit_erc721.go create mode 100644 command/bridge/withdraw/erc1155/withdraw_erc1155.go create mode 100644 command/bridge/withdraw/erc20/withdraw_erc20.go create mode 100644 command/bridge/withdraw/erc721/withdraw_erc721.go delete mode 100644 command/bridge/withdraw/withdraw_erc20.go create mode 100644 command/genesis/params_test.go delete mode 100644 command/polybftmanifest/manifest_init.go create mode 100644 command/rootchain/deploy/deploy.go create mode 100644 command/rootchain/deploy/deploy_test.go create mode 100644 command/rootchain/deploy/params.go rename command/rootchain/{initcontracts => deploy}/result.go (69%) delete mode 100644 command/rootchain/initcontracts/init_contracts.go delete mode 100644 command/rootchain/initcontracts/init_contracts_test.go delete mode 100644 command/rootchain/initcontracts/params.go create mode 100644 command/rootchain/registration/params.go rename command/{sidechain => rootchain}/registration/register_validator.go (55%) create mode 100644 command/rootchain/staking/params.go rename command/{sidechain => rootchain}/staking/stake.go (56%) create mode 100644 command/rootchain/supernet/params.go create mode 100644 command/rootchain/supernet/stakemanager/params.go create mode 100644 command/rootchain/supernet/stakemanager/stake_manager_deploy.go create mode 100644 command/rootchain/supernet/supernet.go create mode 100644 command/rootchain/validators/params.go rename command/{sidechain => rootchain}/validators/validator_info.go (65%) create mode 100644 command/rootchain/whitelist/params.go create mode 100644 command/rootchain/whitelist/whitelist_validators.go create mode 100644 command/rootchain/withdraw/params.go rename command/{sidechain/whitelist/whitelist_validator.go => rootchain/withdraw/withdraw.go} (53%) delete mode 100644 command/sidechain/registration/params.go create mode 100644 command/sidechain/rewards/params.go create mode 100644 command/sidechain/rewards/rewards.go delete mode 100644 command/sidechain/staking/params.go delete mode 100644 command/sidechain/validators/params.go delete mode 100644 command/sidechain/whitelist/params.go delete mode 100644 command/whitelist/deployment/deployment.go delete mode 100644 command/whitelist/deployment/params.go delete mode 100644 command/whitelist/deployment/result.go delete mode 100644 command/whitelist/show/params.go delete mode 100644 command/whitelist/show/result.go delete mode 100644 command/whitelist/show/show.go delete mode 100644 command/whitelist/whitelist.go create mode 100644 consensus/polybft/block_builder_test.go delete mode 100644 consensus/polybft/contractsapi/test-contracts/TestL1StateReceiver.json delete mode 100644 consensus/polybft/contractsapi/test-contracts/TestL1StateReceiver.sol create mode 100644 consensus/polybft/contractsapi/test-contracts/TestRewardToken.json create mode 100644 consensus/polybft/contractsapi/test-contracts/TestSimple.json create mode 100644 consensus/polybft/contractsapi/test-contracts/TestSimple.sol create mode 100644 consensus/polybft/stake_manager.go create mode 100644 consensus/polybft/stake_manager_fuzz_test.go create mode 100644 consensus/polybft/stake_manager_test.go create mode 100644 consensus/polybft/state_store_stake.go create mode 100644 consensus/polybft/state_store_stake_test.go create mode 100644 consensus/polybft/state_sync_commitment.go create mode 100644 consensus/polybft/state_sync_commitment_test.go create mode 100644 consensus/polybft/validator/genesis_validator.go create mode 100644 consensus/polybft/validator/test_helpers.go rename consensus/polybft/{ => validator}/validator_metadata.go (99%) rename consensus/polybft/{ => validator}/validator_metadata_test.go (87%) rename consensus/polybft/{ => validator}/validator_set.go (84%) create mode 100644 consensus/polybft/validator/validator_set_delta.go create mode 100644 consensus/polybft/validator/validator_set_delta_test.go rename consensus/polybft/{ => validator}/validator_set_test.go (79%) create mode 100644 crypto/txsigner_eip155.go rename crypto/{txsigner_test.go => txsigner_eip155_test.go} (74%) create mode 100644 crypto/txsigner_frontier.go create mode 100644 crypto/txsigner_frontier_test.go create mode 100644 crypto/txsigner_london.go create mode 100644 crypto/txsigner_london_test.go create mode 100644 docs/bridge/sequences.md create mode 100644 e2e-polybft/e2e/acls_test.go delete mode 100644 e2e-polybft/e2e/allowlist_test.go create mode 100644 e2e-polybft/e2e/burn_contract_test.go create mode 100644 e2e-polybft/e2e/jsonrpc_test.go create mode 100644 forkmanager/fork.go create mode 100644 forkmanager/fork_manager.go create mode 100644 forkmanager/fork_manager_test.go create mode 100644 gasprice/gasprice.go create mode 100644 gasprice/gasprice_test.go delete mode 100644 helper/config/config.go create mode 100644 jsonrpc/testsuite/block-with-no-basefee.json create mode 100644 jsonrpc/testsuite/transaction-eip1559.json create mode 100755 scripts/fuzzAll delete mode 100644 secrets/helper/helper_test.go create mode 100644 state/executor_test.go rename state/runtime/{allowlist/allowlist.go => addresslist/addresslist.go} (69%) rename state/runtime/{allowlist/allowlist_test.go => addresslist/addresslist_test.go} (71%) rename state/runtime/{allowlist => addresslist}/genesis.go (85%) rename state/runtime/{allowlist => addresslist}/genesis_test.go (94%) create mode 100644 state/runtime/evm/evm_fuzz_test.go delete mode 100644 tests/evm_test.go rename txpool/{queue.go => queue_account.go} (60%) create mode 100644 txpool/queue_priced.go create mode 100644 txpool/queue_priced_test.go create mode 100644 types/state_transaction.go diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2adb8c4897..055dc5e277 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -12,6 +12,4 @@ updates: pull-request-branch-name: separator: "-" reviewers: - - "lazartravica" - - "Kourin1996" - - "zivkovicmilos" + - "0xPolygon/core-edge" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 10ef3db673..73592d30a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,21 +3,26 @@ name: Build on: # yamllint disable-line rule:truthy workflow_dispatch: workflow_call: + # Map the workflow outputs to job outputs + outputs: + workflow_output: + description: "Build output" + value: ${{ jobs.go_build.outputs.build_output_failure }} jobs: go_build: name: Polygon Edge runs-on: ubuntu-latest + outputs: + build_output_failure: ${{ steps.edge_build_failure.outputs.build_output }} steps: - name: Checkout code uses: actions/checkout@v3 - with: - submodules: recursive - + - name: Setup Go environment uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.20.x - name: Build Polygon Edge run: go build -tags netgo -ldflags="-s -w -linkmode external -extldflags "-static" -X \"github.com/0xPolygon/polygon-edge/versioning.Version=${GITHUB_REF_NAME}\" -X \"github.com/0xPolygon/polygon-edge/versioning.Commit=${GITHUB_SHA}\"" && tar -czvf polygon-edge.tar.gz polygon-edge @@ -27,6 +32,11 @@ jobs: GOARC: amd64 GOOS: linux + - name: Build Polygon Edge Failed + if: failure() + id: edge_build_failure + run: echo "build_output=false" >> $GITHUB_OUTPUT + - name: 'Upload Artifact' uses: actions/upload-artifact@v3 with: @@ -41,10 +51,11 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v3 + - name: Setup Go environment uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.20.x - name: 'Reproduce builds' continue-on-error: true diff --git a/.github/workflows/deploy.devnet.eph.yml b/.github/workflows/deploy.devnet.eph.yml index a218d072e7..6c42348402 100644 --- a/.github/workflows/deploy.devnet.eph.yml +++ b/.github/workflows/deploy.devnet.eph.yml @@ -24,55 +24,6 @@ jobs: name: Build uses: ./.github/workflows/build.yml - test: - name: Test - uses: ./.github/workflows/test.yml - needs: build - secrets: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - - container_image_build: - name: Build/Push Container Image - runs-on: ubuntu-latest - environment: devnet-ephemeral - needs: build - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Download Polygon Edge Artifact - uses: actions/download-artifact@v3 - with: - name: polygon-edge - - run: tar -xvzf polygon-edge.tar.gz - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v1-node16 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN }} - aws-region: ${{ secrets.AWS_REGION }} - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v1 - - - name: Build, tag, and push docker image to Amazon ECR - env: - REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: library/polygon-edge - IMAGE_TAG: ${{ github.sha }} - run: | - docker build -t $REGISTRY/$REPOSITORY:devnet-ephemeral -t $REGISTRY/$REPOSITORY:$IMAGE_TAG -f Dockerfile.release . - docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG - docker push $REGISTRY/$REPOSITORY:devnet-ephemeral - deploy_eph_devnet: name: Deploy Ephemeral DevNet needs: build diff --git a/.github/workflows/deploy.devnet.yml b/.github/workflows/deploy.devnet.yml index b2ed712b92..22ca89706b 100644 --- a/.github/workflows/deploy.devnet.yml +++ b/.github/workflows/deploy.devnet.yml @@ -24,55 +24,6 @@ jobs: name: Build uses: ./.github/workflows/build.yml - test: - name: Test - uses: ./.github/workflows/test.yml - needs: build - secrets: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - - container_image_build: - name: Build/Push Container Image - runs-on: ubuntu-latest - environment: devnet - needs: build - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Download Polygon Edge Artifact - uses: actions/download-artifact@v3 - with: - name: polygon-edge - - run: tar -xvzf polygon-edge.tar.gz - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v1-node16 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN }} - aws-region: ${{ secrets.AWS_REGION }} - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v1 - - - name: Build, tag, and push docker image to Amazon ECR - env: - REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: library/polygon-edge - IMAGE_TAG: ${{ github.sha }} - run: | - docker build -t $REGISTRY/$REPOSITORY:devnet -t $REGISTRY/$REPOSITORY:$IMAGE_TAG -f Dockerfile.release . - docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG - docker push $REGISTRY/$REPOSITORY:devnet - deploy_devnet: name: Deploy DevNet needs: build diff --git a/.github/workflows/deploy.nightly.devnet.yml b/.github/workflows/deploy.nightly.devnet.yml new file mode 100644 index 0000000000..18faf0b469 --- /dev/null +++ b/.github/workflows/deploy.nightly.devnet.yml @@ -0,0 +1,278 @@ +--- + +name: Build Devnet +on: # yamllint disable-line rule:truthy + workflow_dispatch: + inputs: + environment: + description: The environment to run against + required: false + type: environment + workflow_call: + inputs: + environment: + description: The environment to run against + type: string + required: true + outputs: + workflow_output_loadtest1: + description: "Loadtest output" + value: ${{ jobs.loadtest1.outputs.loadtest_output_failure }} + workflow_output_loadtest2: + description: "Loadtest output" + value: ${{ jobs.loadtest2.outputs.loadtest_output_failure }} + secrets: + AWS_ROLE_ARN: + required: true + AWS_REGION: + required: true + TF_VAR_DEPLOYMENT_NAME: + required: true + TF_VAR_OWNER: + required: true + SLACK_PERFORMANCE_WEBHOOK_URL: + required: true + DD_API_KEY: + required: true + LOADTEST_MNEMONIC: + required: true + VAULT_PASSWORD_FILE: + required: true + +jobs: + build: + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + repository: maticnetwork/terraform-polygon-supernets + ref: main + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: ${{ secrets.AWS_REGION }} + - name: Install Terraform + uses: hashicorp/setup-terraform@v2.0.3 + with: + terraform_version: 1.4.5 + - name: Configure terraform for nightly build + run: | + sed 's/# backend "s3" {}/backend "s3" {}/' main.tf > main.tf.tmp && mv main.tf.tmp main.tf + - name: Terraform Init + id: init + run: terraform init -backend-config="bucket=polygon-edge-devnet-tf-states" -backend-config="key=state/${{ secrets.TF_VAR_DEPLOYMENT_NAME }}" -backend-config="region=${{ secrets.AWS_REGION }}" + - name: Terraform Validate + id: validate + run: terraform validate -no-color + continue-on-error: true + - name: Terraform Plan + id: plan + run: terraform plan -out=tfplan -no-color + env: + TF_VAR_deployment_name: ${{ secrets.TF_VAR_DEPLOYMENT_NAME }} + TF_VAR_owner: ${{ secrets.TF_VAR_OWNER }} + - name: Terraform Apply + id: apply + run: terraform apply -auto-approve tfplan + env: + TF_VAR_deployment_name: ${{ secrets.TF_VAR_DEPLOYMENT_NAME }} + TF_VAR_owner: ${{ secrets.TF_VAR_OWNER }} + - name: Retrieve state file from s3 + run: aws s3 cp s3://polygon-edge-devnet-tf-states/state/${{ secrets.TF_VAR_DEPLOYMENT_NAME }} state.json + - name: Configure private keys + run: | + terraform output pk_ansible > ~/devnet_private.key + chmod 600 ~/devnet_private.key + eval "$(ssh-agent)" + ssh-add ~/devnet_private.key + - name: Install ansible / botocore / boto3 + run: | + python3 -m pip install --user ansible + python3 -m pip install boto3 botocore + - name: Configure ansible for nightly build + working-directory: ansible + run: | + echo "${{ secrets.VAULT_PASSWORD_FILE }}" > password.txt + sed 's/devnet13/${{ secrets.TF_VAR_DEPLOYMENT_NAME }}/g' inventory/aws_ec2.yml > inventory/aws_ec2.yml.tmp && mv inventory/aws_ec2.yml.tmp inventory/aws_ec2.yml + sed 's/devnet13/${{ secrets.TF_VAR_DEPLOYMENT_NAME }}/g' local-extra-vars.yml > local-extra-vars.yml.tmp && mv local-extra-vars.yml.tmp local-extra-vars.yml + sed 's/edge_tag: .*/edge_tag: HEAD/g' local-extra-vars.yml > local-extra-vars.yml.tmp && mv local-extra-vars.yml.tmp local-extra-vars.yml + - name: Create script file + working-directory: ansible + run: | + cat > roles/edge/templates/bootstrap.sh <<'EOF' + #!/bin/bash -x + + main() { + mkdir /var/lib/bootstrap + pushd /var/lib/bootstrap + + {% for item in hostvars %} + {% if (hostvars[item].tags.Role == "fullnode" or hostvars[item].tags.Role == "validator") %} + polygon-edge polybft-secrets --data-dir {{ hostvars[item].tags["Name"] }} --json --insecure > {{ hostvars[item].tags["Name"] }}.json + {% endif %} + {% endfor %} + + BURN_CONTRACT_ADDRESS=0x0000000000000000000000000000000000000000 + + polygon-edge genesis \ + --consensus polybft \ + {% for item in hostvars %}{% if (hostvars[item].tags.Role == "fullnode" or hostvars[item].tags.Role == "validator") %} --bootnode /dns4/{{ hostvars[item].tags["Name"] }}/tcp/{{ edge_p2p_port }}/p2p/$(cat {{ hostvars[item].tags["Name"] }}.json | jq -r '.[0].node_id') {% endif %}{% endfor %} \ + {% for item in hostvars %}{% if (hostvars[item].tags.Role == "fullnode" or hostvars[item].tags.Role == "validator") %} --premine $(cat {{ hostvars[item].tags["Name"] }}.json | jq -r '.[0].address'):1000000000000000000000000 {% endif %}{% endfor %} \ + --premine {{ loadtest_account }}:1000000000000000000000000000 \ + --premine $BURN_CONTRACT_ADDRESS \ + --reward-wallet 0x0101010101010101010101010101010101010101:1000000000000000000000000000 \ + --premine 0xA39Fed214820cF843E2Bcd6cA1759257a530894B:1000000000000000000000000000 \ + --premine 0x181d9fEc79EC674DD3cB30dd9dd4188E737939FE:1000000000000000000000000000 \ + --premine 0x1AB8C3df809b85012a009c0264eb92dB04eD6EFa:1000000000000000000000000000 \ + --block-gas-limit {{ block_gas_limit }} \ + --block-time {{ block_time }}s \ + {% for item in hostvars %}{% if (hostvars[item].tags.Role == "validator") %} --validators /dns4/{{ hostvars[item].tags["Name"] }}/tcp/{{ edge_p2p_port }}/p2p/$(cat {{ hostvars[item].tags["Name"] }}.json | jq -r '.[0].node_id'):$(cat {{ hostvars[item].tags["Name"] }}.json | jq -r '.[0].address' | sed 's/^0x//'):$(cat {{ hostvars[item].tags["Name"] }}.json | jq -r '.[0].bls_pubkey') {% endif %}{% endfor %} \ + --epoch-size 10 \ + --native-token-config MyToken:MTK:18:true:0x0000000000000000000000000000000000001010 + + polygon-edge polybft stake-manager-deploy \ + --jsonrpc {{ rootchain_json_rpc }} \ + --test + + polygon-edge rootchain deploy \ + --stake-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeManagerAddr') \ + --stake-token $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeTokenAddr') \ + --json-rpc {{ rootchain_json_rpc }} \ + --test + + polygon-edge rootchain fund \ + --stake-token $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeTokenAddr') \ + --mint \ + --addresses $(cat validator-*.json | jq -r ".[].address" | paste -sd "," - | tr -d '\n') \ + --amounts $(for f in validator-*.json; do echo -n "1000000000000000000000000,"; done | sed 's/,$//') \ + --json-rpc {{ rootchain_json_rpc }} + + polygon-edge polybft whitelist-validators \ + --private-key aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d \ + --addresses $(cat validator-*.json | jq -r ".[].address" | paste -sd "," - | tr -d '\n') \ + --supernet-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.customSupernetManagerAddr') \ + --jsonrpc {{ rootchain_json_rpc }} + + counter=1 + {% for item in hostvars %} + {% if (hostvars[item].tags.Role == "validator") %} + echo "Registering validator: ${counter}" + + polygon-edge polybft register-validator \ + --data-dir {{ hostvars[item].tags["Name"] }} \ + --supernet-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.customSupernetManagerAddr') \ + --jsonrpc {{ rootchain_json_rpc }} + + polygon-edge polybft stake \ + --data-dir {{ hostvars[item].tags["Name"] }} \ + --amount 1000000000000000000000000 \ + --supernet-id $(cat genesis.json | jq -r '.params.engine.polybft.supernetID') \ + --stake-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeManagerAddr') \ + --stake-token $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeTokenAddr') \ + --jsonrpc {{ rootchain_json_rpc }} + + ((counter++)) + {% endif %} + {% endfor %} + + {% for item in hostvars %} + {% if (hostvars[item].tags.Role == "validator") %} + {% endif %} + {% endfor %} + + polygon-edge polybft supernet \ + --private-key aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d \ + --supernet-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.customSupernetManagerAddr') \ + --stake-manager $(cat genesis.json | jq -r '.params.engine.polybft.bridge.stakeManagerAddr') \ + --finalize-genesis-set \ + --enable-staking \ + --jsonrpc {{ rootchain_json_rpc }} + + tar czf {{ base_dn }}.tar.gz *.json *.private + popd + } + + main + + EOF + - name: Run Ansible + working-directory: ansible + run: | + ansible-inventory --graph + ansible-galaxy install -r requirements.yml + ansible-playbook --inventory inventory/aws_ec2.yml --vault-password-file=password.txt --extra-vars "@local-extra-vars.yml" site.yml + - name: Set rpc url value + id: url + run: | + terraform output -raw aws_lb_ext_domain | grep -o -E '^ext[^:]*' > rpc_url.txt + - uses: actions/upload-artifact@v3 + with: + name: rpc_url + path: rpc_url.txt + + loadtest1: + needs: build + uses: ./.github/workflows/loadtest.yml + name: Load Test Nightly Build - multiple_EOA + secrets: + SLACK_PERFORMANCE_WEBHOOK_URL: ${{ secrets.SLACK_PERFORMANCE_WEBHOOK_URL }} + LOADTEST_RPC_URL: "" # this is a workaround because of actions bug in passing output to another job + DD_API_KEY: ${{ secrets.DD_API_KEY }} + LOADTEST_MNEMONIC: ${{ secrets.LOADTEST_MNEMONIC }} + with: + runner: devnet + environment: ${{ inputs.environment }} + scenario: multiple_EOA + + loadtest2: + needs: loadtest1 + uses: ./.github/workflows/loadtest.yml + name: Load Test Nightly Build - multiple_ERC20 + secrets: + SLACK_PERFORMANCE_WEBHOOK_URL: ${{ secrets.SLACK_PERFORMANCE_WEBHOOK_URL }} + LOADTEST_RPC_URL: "" # this is a workaround because of actions bug in passing output to another job + DD_API_KEY: ${{ secrets.DD_API_KEY }} + LOADTEST_MNEMONIC: ${{ secrets.LOADTEST_MNEMONIC }} + with: + runner: devnet + environment: ${{ inputs.environment }} + scenario: multiple_ERC20 + + destroy_devnet: + needs: [loadtest1, loadtest2] + if: always() + name: Destroy Nightly Build + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + repository: maticnetwork/terraform-polygon-supernets + ref: main + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + aws-region: ${{ secrets.AWS_REGION }} + - name: Install Terraform + uses: hashicorp/setup-terraform@v2.0.3 + with: + terraform_version: 1.4.5 + - name: Configure terraform for nightly build + run: | + sed 's/# backend "s3" {}/backend "s3" {}/' main.tf > main.tf.tmp && mv main.tf.tmp main.tf + - name: Terraform Init + id: init + run: terraform init -backend-config="bucket=polygon-edge-devnet-tf-states" -backend-config="key=state/${{ secrets.TF_VAR_DEPLOYMENT_NAME }}" -backend-config="region=${{ secrets.AWS_REGION }}" + - name: Retrieve state file from s3 + run: aws s3 cp s3://polygon-edge-devnet-tf-states/state/${{ secrets.TF_VAR_DEPLOYMENT_NAME }} state.json + - name: Terraform Destroy + id: destroy + run: terraform destroy -auto-approve -state=state.json + env: + TF_VAR_deployment_name: ${{ secrets.TF_VAR_DEPLOYMENT_NAME }} + TF_VAR_owner: ${{ secrets.TF_VAR_OWNER }} \ No newline at end of file diff --git a/.github/workflows/deploy.testnet.yml b/.github/workflows/deploy.testnet.yml index 09b31b715b..745776d196 100644 --- a/.github/workflows/deploy.testnet.yml +++ b/.github/workflows/deploy.testnet.yml @@ -23,55 +23,6 @@ jobs: uses: ./.github/workflows/build.yml name: Build - test: - uses: ./.github/workflows/test.yml - name: Test - needs: build - secrets: - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} - - container_image_build: - name: Build/Push Container Image - runs-on: ubuntu-latest - environment: testnet - needs: build - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Download Polygon Edge Artifact - uses: actions/download-artifact@v3 - with: - name: polygon-edge - - run: tar -xvzf polygon-edge.tar.gz - - - name: Set up QEMU - uses: docker/setup-qemu-action@v2 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@v1-node16 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN }} - aws-region: ${{ secrets.AWS_REGION }} - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v1 - - - name: Build, tag, and push docker image to Amazon ECR - env: - REGISTRY: ${{ steps.login-ecr.outputs.registry }} - REPOSITORY: library/polygon-edge - IMAGE_TAG: ${{ github.sha }} - run: | - docker build -t $REGISTRY/$REPOSITORY:testnet -t $REGISTRY/$REPOSITORY:$IMAGE_TAG -f Dockerfile.release . - docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG - docker push $REGISTRY/$REPOSITORY:testnet - deploy_testnet: name: Update TestNet needs: build diff --git a/.github/workflows/e2e-polybft.yml b/.github/workflows/e2e-polybft.yml index e1e7b1c41b..85e51b261d 100644 --- a/.github/workflows/e2e-polybft.yml +++ b/.github/workflows/e2e-polybft.yml @@ -6,7 +6,12 @@ on: # yamllint disable-line rule:truthy - main - develop pull_request: + workflow_dispatch: workflow_call: + outputs: + workflow_output: + description: "E2E output" + value: ${{ jobs.build.outputs.e2e_output_failure }} jobs: build: @@ -14,16 +19,26 @@ jobs: env: E2E_TESTS: true E2E_LOGS: true - E2E_TESTS_TYPE: 'integration' CI_VERBOSE: true + outputs: + e2e_output_failure: ${{ steps.run_e2e_failure.outputs.test_output }} steps: - - uses: actions/checkout@v3 + - name: Checkout code + uses: actions/checkout@v3 + - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.20.x + - name: Run tests run: make test-e2e-polybft + + - name: Run tests failed + if: failure() + id: run_e2e_failure + run: echo "test_output=false" >> $GITHUB_OUTPUT + - name: Archive test logs if: always() uses: actions/upload-artifact@v3 diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index e9b28f9401..d1db2650e8 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -1,11 +1,12 @@ --- name: E2E tests on: # yamllint disable-line rule:truthy - push: - branches: - - main - - develop - pull_request: + workflow_dispatch: + workflow_call: + outputs: + workflow_output: + description: "E2E IBFT output" + value: ${{ jobs.build.outputs.e2eibft_output_failure }} jobs: build: @@ -14,16 +15,27 @@ jobs: E2E_TESTS: true E2E_LOGS: true CI_VERBOSE: true + outputs: + e2eibft_output_failure: ${{ steps.run_e2eibft_failure.outputs.test_output }} steps: - - uses: actions/checkout@v3 + - name: Checkout code + uses: actions/checkout@v3 with: submodules: recursive + - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.20.x + - name: Run tests run: make test-e2e + + - name: Run tests failed + if: failure() + id: run_e2eibft_failure + run: echo "test_output=false" >> $GITHUB_OUTPUT + - name: Archive test logs if: always() uses: actions/upload-artifact@v3 diff --git a/.github/workflows/fuzz-test.yml b/.github/workflows/fuzz-test.yml new file mode 100644 index 0000000000..d7fabfaa70 --- /dev/null +++ b/.github/workflows/fuzz-test.yml @@ -0,0 +1,38 @@ +--- +name: Fuzz tests +on: # yamllint disable-line rule:truthy + push: + branches: + - main + - develop + workflow_dispatch: + workflow_call: + outputs: + workflow_output: + description: "Fuzz output" + value: ${{ jobs.build.outputs.fuzz_output_failure }} + + +jobs: + fuzz_test: + name: Polygon Edge + runs-on: ubuntu-latest + outputs: + fuzz_output_failure: ${{ steps.run_fuzz_failure.outputs.test_output }} + steps: + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: 1.20.x + + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Run Fuzz Test + run: make fuzz-test + + - name: Run fuzz tests failed + if: failure() + id: run_fuzz_failure + run: echo "test_output=false" >> $GITHUB_OUTPUT + diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9a1c351f25..292c1c19ec 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,13 +2,18 @@ name: Lint on: # yamllint disable-line rule:truthy push: - branches-ignore: - - 'develop' - - 'release/**' + branches: + - '*' tags-ignore: - 'v*' paths: - '**.go' + pull_request: + types: + - opened + - synchronize + - reopened + workflow_call: {} workflow_dispatch: {} @@ -19,10 +24,12 @@ jobs: - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.20.x - name: Checkout code uses: actions/checkout@v3 - name: Lint uses: golangci/golangci-lint-action@v3 + with: + args: --timeout 10m --verbose diff --git a/.github/workflows/loadtest.yml b/.github/workflows/loadtest.yml index ff42c72bd2..281b8a62bc 100644 --- a/.github/workflows/loadtest.yml +++ b/.github/workflows/loadtest.yml @@ -1,147 +1,170 @@ --- - name: Load Test - on: # yamllint disable-line rule:truthy - workflow_dispatch: - inputs: - runner: - description: The runner to execute on - default: 'ubuntu-latest' - type: choice - options: - - ubuntu-latest - - devnet - - testnet - environment: - description: The environment to run against - required: false - type: environment - scenario: - default: 'simple' - description: The scenario to run - type: string - duration: - default: '2m' - description: Duration of the test - required: false - type: string - workflow_call: - inputs: - environment: - description: The environment to run against - type: string - required: true - runner: - required: true - type: string - description: The runner label to use - scenario: - required: true - description: The mode for the stress test - type: string - duration: - default: '2m' - description: Duration of the test - required: false - type: string - secrets: - SLACK_PERFORMANCE_WEBHOOK_URL: - required: true - DD_API_KEY: - required: true - LOADTEST_RPC_URL: - required: true - LOADTEST_MNEMONIC: - required: true +name: Load Test +on: # yamllint disable-line rule:truthy + workflow_dispatch: + inputs: + runner: + description: The runner to execute on + default: 'ubuntu-latest' + type: choice + options: + - ubuntu-latest + - devnet + - testnet + environment: + description: The environment to run against + required: false + type: environment + scenario: + default: 'simple' + description: The scenario to run + type: string + duration: + default: '2m' + description: Duration of the test + required: false + type: string + workflow_call: + inputs: + environment: + description: The environment to run against + type: string + required: true + runner: + required: true + type: string + description: The runner label to use + scenario: + required: true + description: The mode for the stress test + type: string + duration: + default: '2m' + description: Duration of the test + required: false + type: string + secrets: + SLACK_PERFORMANCE_WEBHOOK_URL: + required: true + DD_API_KEY: + required: true + LOADTEST_RPC_URL: + required: true + LOADTEST_MNEMONIC: + required: true - - jobs: - run_k6: - environment: ${{ inputs.environment }} - runs-on: ubuntu-latest - steps: - - name: Install Go - uses: actions/setup-go@v3 - with: - go-version: 1.18.x - - - name: Checkout code - uses: actions/checkout@v3 - - - uses: datadog/agent-github-action@v1.3 - with: - api_key: ${{ secrets.DD_API_KEY }} - - - name: Install xk6 - run: | - go install go.k6.io/xk6/cmd/xk6@latest - xk6 build --with github.com/distribworks/xk6-ethereum@5c6e782669953f1e5d1f44509e610fb2e3d22238 - - - name: Install JQ - run: | - mkdir -p $HOME/.local/bin - curl -sLo $HOME/.local/bin/jq https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 && chmod +x $HOME/.local/bin/jq - echo "$HOME/.local/bin" >> $GITHUB_PATH +jobs: + run_k6: + environment: ${{ inputs.environment }} + runs-on: ubuntu-latest + outputs: + loadtest_output_failure: ${{ steps.run_k6_failure.outputs.test_output }} + steps: + - name: Install Go + uses: actions/setup-go@v3 + with: + go-version: 1.20.x - - id: k6 - name: Run scenario - run: | - ./k6 run --out statsd loadtest/scenarios/${{ inputs.scenario }}.js - echo "tps_avg=$(cat summary.json | jq -r '.metrics.ethereum_tps.values.avg')" >> $GITHUB_OUTPUT - echo "tps_max=$(cat summary.json | jq -r '.metrics.ethereum_tps.values.max')" >> $GITHUB_OUTPUT - echo "iterations=$(cat summary.json | jq -r '.metrics.iterations.values.count')" >> $GITHUB_OUTPUT - echo "block=$(cat summary.json | jq -r '.metrics.ethereum_block.values.count')" >> $GITHUB_OUTPUT - echo "ttm=$(cat summary.json | jq -r '.metrics.ethereum_time_to_mine.values.avg')" >> $GITHUB_OUTPUT - echo "gas_avg=$(cat summary.json | jq -r '.metrics.ethereum_gas_used.values.avg')" >> $GITHUB_OUTPUT - echo "gas_max=$(cat summary.json | jq -r '.metrics.ethereum_gas_used.values.max')" >> $GITHUB_OUTPUT - env: - K6_STATSD_ENABLE_TAGS: true - RPC_URL: ${{ secrets.LOADTEST_RPC_URL }} - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_PERFORMANCE_WEBHOOK_URL }} - LOADTEST_MNEMONIC: ${{ secrets.LOADTEST_MNEMONIC }} - LOADTEST_DURATION: ${{ inputs.duration }} - - - name: Notify Slack - uses: slackapi/slack-github-action@v1.23.0 - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_PERFORMANCE_WEBHOOK_URL }} - SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK - with: - payload: | - { - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "K6 Loadtest Results" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "*Scenario*: `${{ inputs.scenario }}`\n *Average TPS*: `${{ steps.k6.outputs.tps_avg }}`\n*Max TPS*: `${{ steps.k6.outputs.tps_max }}`\n*Transactions*: `${{ steps.k6.outputs.iterations }}`\n*Block Number*: `${{ steps.k6.outputs.block }}`\n*Time to Mine*: `${{ steps.k6.outputs.ttm }}`\n*Average Gas Used*: `${{ steps.k6.outputs.gas_avg }}`\n*Max Gas Used*: `${{ steps.k6.outputs.gas_max }}`" - } - }, - { - "type": "divider" - }, - { - "type": "context", - "elements": [ - { - "type": "mrkdwn", - "text": "Environment: `${{ inputs.environment }}`" - }, - { - "type": "mrkdwn", - "text": "JSON-RPC Endpoint: ${{ secrets.LOADTEST_RPC_URL }}" - }, - { - "type": "mrkdwn", - "text": "Workflow: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Results>" - } - ] - } - ] - } + - name: Checkout code + uses: actions/checkout@v3 + + - uses: datadog/agent-github-action@v1.3 + with: + api_key: ${{ secrets.DD_API_KEY }} + + - name: Install xk6 + run: | + go install go.k6.io/xk6/cmd/xk6@latest + xk6 build --with github.com/distribworks/xk6-ethereum@5c6e782669953f1e5d1f44509e610fb2e3d22238 + + - name: Install JQ + run: | + mkdir -p $HOME/.local/bin + curl -sLo $HOME/.local/bin/jq https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 && chmod +x $HOME/.local/bin/jq + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Download artifact to get rpc url + env: + url: ${{ secrets.LOADTEST_RPC_URL }} + if: ${{ env.url == '' }} + uses: actions/download-artifact@v3 + with: + name: rpc_url + + - name: Set rpc_url + id: set_rpc_url + run: | + if [[ -z "${{ secrets.LOADTEST_RPC_URL }}" ]]; then + echo "rpc_url=http://$(cat rpc_url.txt)" >> $GITHUB_OUTPUT + else + echo "rpc_url=${{ secrets.LOADTEST_RPC_URL }}" >> $GITHUB_OUTPUT + fi + + - id: k6 + name: Run scenario + run: | + ./k6 run --out statsd loadtest/scenarios/${{ inputs.scenario }}.js + echo "tps_avg=$(cat summary.json | jq -r '.metrics.ethereum_tps.values.avg')" >> $GITHUB_OUTPUT + echo "tps_max=$(cat summary.json | jq -r '.metrics.ethereum_tps.values.max')" >> $GITHUB_OUTPUT + echo "iterations=$(cat summary.json | jq -r '.metrics.iterations.values.count')" >> $GITHUB_OUTPUT + echo "block=$(cat summary.json | jq -r '.metrics.ethereum_block.values.count')" >> $GITHUB_OUTPUT + echo "ttm=$(cat summary.json | jq -r '.metrics.ethereum_time_to_mine.values.avg')" >> $GITHUB_OUTPUT + echo "gas_avg=$(cat summary.json | jq -r '.metrics.ethereum_gas_used.values.avg')" >> $GITHUB_OUTPUT + echo "gas_max=$(cat summary.json | jq -r '.metrics.ethereum_gas_used.values.max')" >> $GITHUB_OUTPUT + env: + K6_STATSD_ENABLE_TAGS: true + RPC_URL: ${{ steps.set_rpc_url.outputs.rpc_url }} + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_PERFORMANCE_WEBHOOK_URL }} + LOADTEST_MNEMONIC: ${{ secrets.LOADTEST_MNEMONIC }} + LOADTEST_DURATION: ${{ inputs.duration }} + + - name: Run tests failed + if: failure() + id: run_k6_failure + run: echo "test_output=false" >> $GITHUB_OUTPUT + + - name: Notify Slack + uses: slackapi/slack-github-action@v1.23.0 + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_PERFORMANCE_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + with: + payload: | + { + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "K6 Loadtest Results" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Scenario*: `${{ inputs.scenario }}`\n *Average TPS*: `${{ steps.k6.outputs.tps_avg }}`\n*Max TPS*: `${{ steps.k6.outputs.tps_max }}`\n*Transactions*: `${{ steps.k6.outputs.iterations }}`\n*Block Number*: `${{ steps.k6.outputs.block }}`\n*Time to Mine*: `${{ steps.k6.outputs.ttm }}`\n*Average Gas Used*: `${{ steps.k6.outputs.gas_avg }}`\n*Max Gas Used*: `${{ steps.k6.outputs.gas_max }}`" + } + }, + { + "type": "divider" + }, + { + "type": "context", + "elements": [ + { + "type": "mrkdwn", + "text": "Environment: `${{ inputs.environment }}`" + }, + { + "type": "mrkdwn", + "text": "JSON-RPC Endpoint: ${{ steps.set_rpc_url.outputs.rpc_url }}" + }, + { + "type": "mrkdwn", + "text": "Workflow: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Results>" + } + ] + } + ] + } diff --git a/.github/workflows/manual.deploy.nightly.devnet.yml b/.github/workflows/manual.deploy.nightly.devnet.yml new file mode 100644 index 0000000000..22dd7d9a71 --- /dev/null +++ b/.github/workflows/manual.deploy.nightly.devnet.yml @@ -0,0 +1,31 @@ +--- +### This manually triggers the edge nightly build loadtest when pushed to jesse/nightly-loadtest-workflow + +name: Nightly DevNet Workflow (Manual) +on: # yamllint disable-line rule:truthy + push: + branches: + - jesse/fix-* + workflow_call: {} + workflow_dispatch: {} + +permissions: + id-token: write + contents: read + security-events: write + +jobs: + devnet: + name: Build Devnet + uses: ./.github/workflows/deploy.nightly.devnet.yml + secrets: + AWS_REGION: ${{ secrets.AWS_REGION }} + AWS_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }} + TF_VAR_DEPLOYMENT_NAME: ${{ secrets.TF_VAR_DEPLOYMENT_NAME }} + TF_VAR_OWNER: ${{ secrets.TF_VAR_OWNER }} + SLACK_PERFORMANCE_WEBHOOK_URL: ${{ secrets.SLACK_PERFORMANCE_WEBHOOK_URL }} + DD_API_KEY: ${{ secrets.DD_API_KEY }} + LOADTEST_MNEMONIC: ${{ secrets.LOADTEST_MNEMONIC }} + VAULT_PASSWORD_FILE: ${{ secrets.VAULT_PASSWORD_FILE }} + with: + environment: devnet diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 6932902913..7117dc25cf 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,10 +1,16 @@ --- name: Nightly Build -on: # yamllint disable-line rule:truthy +on: #yamllint disable-line rule:truthy + workflow_dispatch: schedule: # * is a special character in YAML so you have to quote this string - cron: '0 0 * * *' +permissions: + id-token: write + contents: read + security-events: write + jobs: build: name: Build @@ -19,12 +25,134 @@ jobs: SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} e2e: - name: Polybft E2E Tests + name: PolyBFT E2E Tests uses: ./.github/workflows/e2e-polybft.yml needs: build + e2eibft: + name: IBFT E2E Tests + uses: ./.github/workflows/e2e.yaml + needs: build + property: name: Polybft Property Tests uses: ./.github/workflows/property-polybft.yml needs: build - \ No newline at end of file + + fuzz: + name: Fuzz Tests + uses: ./.github/workflows/fuzz-test.yml + needs: build + + loadtest: + name: Build Devnet + uses: ./.github/workflows/deploy.nightly.devnet.yml + secrets: + AWS_REGION: ${{ secrets.AWS_REGION }} + AWS_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }} + TF_VAR_DEPLOYMENT_NAME: ${{ secrets.TF_VAR_DEPLOYMENT_NAME }} + TF_VAR_OWNER: ${{ secrets.TF_VAR_OWNER }} + SLACK_PERFORMANCE_WEBHOOK_URL: ${{ secrets.SLACK_PERFORMANCE_WEBHOOK_URL }} + DD_API_KEY: ${{ secrets.DD_API_KEY }} + LOADTEST_MNEMONIC: ${{ secrets.LOADTEST_MNEMONIC }} + VAULT_PASSWORD_FILE: ${{ secrets.VAULT_PASSWORD_FILE }} + with: + environment: devnet + + notification: + name: Nightly Notifications + runs-on: ubuntu-latest + needs: [build, test, e2e, e2eibft, property, fuzz, loadtest] + if: success() || failure() + steps: + - name: Notify Slack + uses: slackapi/slack-github-action@v1.23.0 + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_EDGE_GITHUB_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + with: + payload: | + { + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "Nightly Build" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Status* ${{ needs.build.outputs.workflow_output == '' && needs.test.outputs.workflow_output == '' && needs.property.outputs.workflow_output == '' && needs.e2e.outputs.workflow_output == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Build ${{ needs.build.outputs.workflow_output == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Unit tests ${{ needs.test.outputs.workflow_output == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Property tests ${{ needs.property.outputs.workflow_output == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "E2E tests ${{ needs.e2e.outputs.workflow_output == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "E2E IBFT tests ${{ needs.e2eibft.outputs.workflow_output == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Fuzz tests ${{ needs.fuzz.outputs.workflow_output == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Load tests (multiple_EOA) ${{ needs.loadtest.outputs.workflow_output_loadtest1 == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Load tests (multiple_ERC20) ${{ needs.loadtest.outputs.workflow_output_loadtest2 == '' && ':white_check_mark:' || ':x: `failed`' }}" + } + }, + { + "type": "divider" + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "Workflow: <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Results>" + } + } + ] + } diff --git a/.github/workflows/property-polybft.yml b/.github/workflows/property-polybft.yml index 9c9e915829..fbb3706793 100644 --- a/.github/workflows/property-polybft.yml +++ b/.github/workflows/property-polybft.yml @@ -5,7 +5,12 @@ on: # yamllint disable-line rule:truthy branches: - main - develop + workflow_dispatch: workflow_call: + outputs: + workflow_output: + description: "Property output" + value: ${{ jobs.build.outputs.property_output_failure }} jobs: build: @@ -13,16 +18,26 @@ jobs: env: E2E_TESTS: true E2E_LOGS: true - E2E_TESTS_TYPE: 'property' CI_VERBOSE: true + outputs: + property_output_failure: ${{ steps.run_property_failure.outputs.test_output }} steps: - - uses: actions/checkout@v3 + - name: Checkout code + uses: actions/checkout@v3 + - name: Install Go uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.20.x + - name: Run tests run: make test-property-polybft + + - name: Run tests failed + if: failure() + id: run_property_failure + run: echo "test_output=false" >> $GITHUB_OUTPUT + - name: Archive test logs if: always() uses: actions/upload-artifact@v3 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d6097c8924..7d865dbfe6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,8 @@ on: # yamllint disable-line rule:truthy jobs: goreleaser: runs-on: ubuntu-latest + env: + DOCKER_CONFIG: $HOME/.docker steps: - name: Checkout uses: actions/checkout@v3 @@ -21,16 +23,23 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.20.x - name: Prepare id: prepare run: | TAG=${GITHUB_REF#refs/tags/} echo tag_name=${TAG} >> $GITHUB_OUTPUT + - name: Set up QEMU uses: docker/setup-qemu-action@v2 + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Run GoReleaser run: | docker run \ @@ -38,9 +47,8 @@ jobs: --privileged \ -e CGO_ENABLED=1 \ -e GITHUB_TOKEN \ - -e DOCKER_USERNAME \ - -e DOCKER_PASSWORD \ -e SLACK_WEBHOOK \ + -e DOCKER_CONFIG \ -v /var/run/docker.sock:/var/run/docker.sock \ -v `pwd`:/go/src/$(PACKAGE_NAME) \ -w /go/src/$(PACKAGE_NAME) \ @@ -48,10 +56,7 @@ jobs: --rm-dist --skip-validate env: PACKAGE_NAME: github.com/0xPolygon/polygon-edge - GOLANG_CROSS_VERSION: v1.18.3 + GOLANG_CROSS_VERSION: v1.20.5 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} VERSION: ${{ steps.prepare.outputs.tag_name }} - SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} - SLACK_CHANNEL: ${{ secrets.SLACK_CHANNEL }} - DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} - DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} + SLACK_WEBHOOK: ${{ secrets.SLACK_EDGE_GITHUB_URL }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d4973d7718..c592923467 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,16 +8,22 @@ on: # yamllint disable-line rule:truthy required: false SONAR_HOST_URL: required: false + outputs: + workflow_output: + description: "Unit tests output" + value: ${{ jobs.go_test.outputs.test_output_failure }} jobs: go_test: name: Polygon Edge runs-on: ubuntu-latest + outputs: + test_output_failure: ${{ steps.run_tests_failure.outputs.test_output }} steps: - name: Setup Go uses: actions/setup-go@v3 with: - go-version: 1.18.x + go-version: 1.20.x - name: Checkout Code uses: actions/checkout@v3 @@ -28,8 +34,13 @@ jobs: run: ./setup-ci.sh - name: Run Go Test - run: go test -coverprofile coverage.out -timeout 20m `go list ./... | grep -v e2e` - + run: make test + + - name: Run Go Test Failed + if: failure() + id: run_tests_failure + run: echo "test_output=false" >> $GITHUB_OUTPUT + # Triggering SonarQube analysis as results of it are required by Quality Gate check. - name: SonarQube Scan if: ${{ env.HAVE_SONAR_TOKEN == 'true' }} diff --git a/.gitmodules b/.gitmodules index 26a6e740c7..8315de1190 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,5 +5,3 @@ [submodule "core-contracts"] path = core-contracts url = https://github.com/0xPolygon/core-contracts - shallow = true - branch = feat-polybft-release diff --git a/.golangci.yml b/.golangci.yml index fe83dec3f4..d5cd6e9ba3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -6,6 +6,8 @@ run: # default is true. Enables skipping of directories: # vendor$, third_party$, testdata$, examples$, Godeps$, builtin$ skip-dirs-use-default: true + skip-dirs: + - tests service: golangci-lint-version: 1.49.0 diff --git a/Makefile b/Makefile index d19530d4e7..8e23754b50 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,11 @@ generate-bsd-licenses: .PHONY: test test: - go test -coverprofile coverage.out -timeout=20m `go list ./... | grep -v e2e` + go test -coverprofile coverage.out -timeout 20m `go list ./... | grep -v e2e` + +.PHONY: fuzz-test +fuzz-test: + ./scripts/fuzzAll .PHONY: test-e2e test-e2e: @@ -54,13 +58,15 @@ test-e2e: test-e2e-polybft: # We can not build with race because of a bug in boltdb dependency go build -o artifacts/polygon-edge . - env EDGE_BINARY=${PWD}/artifacts/polygon-edge E2E_TESTS=true E2E_LOGS=true E2E_TESTS_TYPE=integration \ - go test -v -timeout=45m ./e2e-polybft/e2e/... + env EDGE_BINARY=${PWD}/artifacts/polygon-edge E2E_TESTS=true E2E_LOGS=true \ + go test -v -timeout=1h10m ./e2e-polybft/e2e/... +.PHONY: test-property-polybft test-property-polybft: # We can not build with race because of a bug in boltdb dependency go build -o artifacts/polygon-edge . - env EDGE_BINARY=${PWD}/artifacts/polygon-edge E2E_TESTS=true E2E_LOGS=true E2E_TESTS_TYPE=property go test -v -timeout=30m ./e2e-polybft/property/... + env EDGE_BINARY=${PWD}/artifacts/polygon-edge E2E_TESTS=true E2E_LOGS=true go test -v -timeout=30m ./e2e-polybft/property/... \ + -rapid.checks=10 .PHONY: compile-core-contracts compile-core-contracts: @@ -71,3 +77,15 @@ compile-core-contracts: generate-smart-contract-bindings: go run ./consensus/polybft/contractsapi/artifacts-gen/main.go go run ./consensus/polybft/contractsapi/bindings-gen/main.go + +.PHONY: run-docker +run-docker: + ./scripts/cluster polybft --docker + +.PHONY: stop-docker +stop-docker: + ./scripts/cluster polybft --docker stop + +.PHONY: destroy-docker +destroy-docker: + ./scripts/cluster polybft --docker destroy \ No newline at end of file diff --git a/README.md b/README.md index 232ecc973c..6d5e4ddbf3 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ ![Banner](.github/banner.jpg) -## Update: Edge v0.8 is here! +## Update: Edge v1.0.0 is here! -Developers at Polygon Labs have been hard at work gathering and incorporating community feedback into the Edge client and a new version of Edge, v0.8, is here with several new features! Check out the Release Notes included with the release to find out more! +Developers at Polygon Labs have been hard at work gathering and incorporating community feedback into the Edge client and a new version of Edge, v1.0.0, is here with several new features! Check out the Release Notes included with the release to find out more! ## Polygon Edge diff --git a/blockchain/blockchain.go b/blockchain/blockchain.go index 67931d6642..b3c749c306 100644 --- a/blockchain/blockchain.go +++ b/blockchain/blockchain.go @@ -22,8 +22,14 @@ import ( ) const ( - BlockGasTargetDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations - defaultCacheSize int = 100 // The default size for Blockchain LRU cache structures + // defaultBaseFeeChangeDenom is the value to bound the amount the base fee can change between blocks. + defaultBaseFeeChangeDenom = 8 + + // blockGasTargetDivisor is the bound divisor of the gas limit, used in update calculations + blockGasTargetDivisor uint64 = 1024 + + // defaultCacheSize is the default size for Blockchain LRU cache structures + defaultCacheSize int = 100 ) var ( @@ -66,8 +72,8 @@ type Blockchain struct { // any new fields from being added receiptsCache *lru.Cache // LRU cache for the block receipts - currentHeader atomic.Value // The current header - currentDifficulty atomic.Value // The current difficulty of the chain (total difficulty) + currentHeader atomic.Pointer[types.Header] // The current header + currentDifficulty atomic.Pointer[big.Int] // The current difficulty of the chain (total difficulty) stream *eventStream // Event subscriptions @@ -88,7 +94,7 @@ type Verifier interface { VerifyHeader(header *types.Header) error ProcessHeaders(headers []*types.Header) error GetBlockCreator(header *types.Header) (types.Address, error) - PreCommitState(header *types.Header, txn *state.Transition) error + PreCommitState(block *types.Block, txn *state.Transition) error } type Executor interface { @@ -310,22 +316,12 @@ func (b *Blockchain) setCurrentHeader(h *types.Header, diff *big.Int) { // Header returns the current header (atomic) func (b *Blockchain) Header() *types.Header { - header, ok := b.currentHeader.Load().(*types.Header) - if !ok { - return nil - } - - return header + return b.currentHeader.Load() } // CurrentTD returns the current total difficulty (atomic) func (b *Blockchain) CurrentTD() *big.Int { - td, ok := b.currentDifficulty.Load().(*big.Int) - if !ok { - return nil - } - - return td + return b.currentDifficulty.Load() } // Config returns the blockchain configuration @@ -382,7 +378,7 @@ func (b *Blockchain) calculateGasLimit(parentGasLimit uint64) uint64 { return blockGasTarget } - delta := parentGasLimit * 1 / BlockGasTargetDivisor + delta := parentGasLimit * 1 / blockGasTargetDivisor if parentGasLimit < blockGasTarget { // The gas limit is lower than the gas target, so it should // increase towards the target @@ -697,12 +693,7 @@ func (b *Blockchain) verifyBlock(block *types.Block) (*BlockResult, error) { } // Make sure the block body data is valid - blockResult, err := b.verifyBlockBody(block) - if err != nil { - return nil, err - } - - return blockResult, nil + return b.verifyBlockBody(block) } // verifyBlockParent makes sure that the child block is in line @@ -844,13 +835,17 @@ func (b *Blockchain) executeBlockTransactions(block *types.Block) (*BlockResult, return nil, err } - if err := b.consensus.PreCommitState(header, txn); err != nil { + if err := b.consensus.PreCommitState(block, txn); err != nil { return nil, err } - _, trace, root := txn.Commit() + _, trace, root, err := txn.Commit() trace.ParentStateRoot = parent.StateRoot + if err != nil { + return nil, fmt.Errorf("failed to commit the state changes: %w", err) + } + // Append the receipts to the receipts cache b.receiptsCache.Add(header.Hash, txn.Receipts()) @@ -1044,7 +1039,7 @@ func (b *Blockchain) updateGasPriceAvgWithBlock(block *types.Block) { gasPrices := make([]*big.Int, len(block.Transactions)) for i, transaction := range block.Transactions { - gasPrices[i] = transaction.GasPrice + gasPrices[i] = transaction.GetGasPrice(block.Header.BaseFee) } b.updateGasPriceAvg(gasPrices) @@ -1146,7 +1141,7 @@ func (b *Blockchain) verifyGasLimit(header *types.Header, parentHeader *types.He diff *= -1 } - limit := parentHeader.GasLimit / BlockGasTargetDivisor + limit := parentHeader.GasLimit / blockGasTargetDivisor if uint64(diff) > limit { return fmt.Errorf( "invalid gas limit, limit = %d, want %d +- %d", @@ -1441,3 +1436,37 @@ func (b *Blockchain) GetBlockByNumber(blockNumber uint64, full bool) (*types.Blo func (b *Blockchain) Close() error { return b.db.Close() } + +// CalculateBaseFee calculates the basefee of the header. +func (b *Blockchain) CalculateBaseFee(parent *types.Header) uint64 { + if !b.config.Chain.Params.Forks.IsActive(chain.London, parent.Number) { + return chain.GenesisBaseFee + } + + parentGasTarget := parent.GasLimit / b.config.Chain.Genesis.BaseFeeEM + + // If the parent gasUsed is the same as the target, the baseFee remains unchanged. + if parent.GasUsed == parentGasTarget { + return parent.BaseFee + } + + // If the parent block used more gas than its target, the baseFee should increase. + if parent.GasUsed > parentGasTarget { + gasUsedDelta := parent.GasUsed - parentGasTarget + baseFeeDelta := calcBaseFeeDelta(gasUsedDelta, parentGasTarget, parent.BaseFee) + + return parent.BaseFee + common.Max(baseFeeDelta, 1) + } + + // Otherwise, if the parent block used less gas than its target, the baseFee should decrease. + gasUsedDelta := parentGasTarget - parent.GasUsed + baseFeeDelta := calcBaseFeeDelta(gasUsedDelta, parentGasTarget, parent.BaseFee) + + return common.Max(parent.BaseFee-baseFeeDelta, 0) +} + +func calcBaseFeeDelta(gasUsedDelta, parentGasTarget, baseFee uint64) uint64 { + y := baseFee * gasUsedDelta / parentGasTarget + + return y / defaultBaseFeeChangeDenom +} diff --git a/blockchain/blockchain_test.go b/blockchain/blockchain_test.go index baea42f6ee..50a99f1db1 100644 --- a/blockchain/blockchain_test.go +++ b/blockchain/blockchain_test.go @@ -1335,3 +1335,56 @@ func TestBlockchain_VerifyBlockBody(t *testing.T) { assert.ErrorIs(t, err, errUnableToExecute) }) } + +func TestBlockchain_CalculateBaseFee(t *testing.T) { + t.Parallel() + + tests := []struct { + blockNumber uint64 + parentBaseFee uint64 + parentGasLimit uint64 + parentGasUsed uint64 + expectedBaseFee uint64 + elasticityMultiplier uint64 + }{ + {6, chain.GenesisBaseFee, 20000000, 10000000, chain.GenesisBaseFee, 2}, // usage == target + {6, chain.GenesisBaseFee, 20000000, 10000000, 1125000000, 4}, // usage == target + {6, chain.GenesisBaseFee, 20000000, 9000000, 987500000, 2}, // usage below target + {6, chain.GenesisBaseFee, 20000000, 9000000, 1100000000, 4}, // usage below target + {6, chain.GenesisBaseFee, 20000000, 11000000, 1012500000, 2}, // usage above target + {6, chain.GenesisBaseFee, 20000000, 11000000, 1150000000, 4}, // usage above target + {6, chain.GenesisBaseFee, 20000000, 20000000, 1125000000, 2}, // usage full + {6, chain.GenesisBaseFee, 20000000, 20000000, 1375000000, 4}, // usage full + {6, chain.GenesisBaseFee, 20000000, 0, 875000000, 2}, // usage 0 + {6, chain.GenesisBaseFee, 20000000, 0, 875000000, 4}, // usage 0 + } + + for i, test := range tests { + test := test + + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + t.Parallel() + + blockchain := Blockchain{ + config: &Config{ + Chain: &chain.Chain{ + Params: &chain.Params{ + Forks: &chain.Forks{chain.London: chain.NewFork(5)}, + }, + Genesis: &chain.Genesis{BaseFeeEM: test.elasticityMultiplier}, + }, + }, + } + + parent := &types.Header{ + Number: test.blockNumber, + GasLimit: test.parentGasLimit, + GasUsed: test.parentGasUsed, + BaseFee: test.parentBaseFee, + } + + got := blockchain.CalculateBaseFee(parent) + assert.Equal(t, test.expectedBaseFee, got, fmt.Sprintf("expected %d, got %d", test.expectedBaseFee, got)) + }) + } +} diff --git a/blockchain/subscription.go b/blockchain/subscription.go index 34a147342f..145a727fa0 100644 --- a/blockchain/subscription.go +++ b/blockchain/subscription.go @@ -42,19 +42,7 @@ type subscription struct { // GetEventCh creates a new event channel, and returns it func (s *subscription) GetEventCh() chan *Event { - eventCh := make(chan *Event) - - go func() { - for { - evnt := s.GetEvent() - if evnt == nil { - return - } - eventCh <- evnt - } - }() - - return eventCh + return s.updateCh } // GetEvent returns the event from the subscription (BLOCKING) @@ -161,11 +149,7 @@ func (e *eventStream) newUpdateCh() chan *Event { e.Lock() defer e.Unlock() - ch := make(chan *Event, 1) - - if e.updateCh == nil { - e.updateCh = make([]chan *Event, 0) - } + ch := make(chan *Event, 5) e.updateCh = append(e.updateCh, ch) @@ -179,9 +163,6 @@ func (e *eventStream) push(event *Event) { // Notify the listeners for _, update := range e.updateCh { - select { - case update <- event: - default: - } + update <- event } } diff --git a/blockchain/subscription_test.go b/blockchain/subscription_test.go index 9e854a20a9..26acd59cf4 100644 --- a/blockchain/subscription_test.go +++ b/blockchain/subscription_test.go @@ -51,3 +51,61 @@ func TestSubscription(t *testing.T) { assert.Equal(t, event.NewChain[0].Number, caughtEventNum) } + +func TestSubscription_BufferedChannel_MultipleSubscriptions(t *testing.T) { + t.Parallel() + + var ( + e = &eventStream{} + wg sync.WaitGroup + numOfEvents = 100000 + numOfSubscriptions = 10 + ) + + subscriptions := make([]*subscription, numOfSubscriptions) + wg.Add(numOfSubscriptions) + + worker := func(id int, sub *subscription) { + updateCh := sub.GetEventCh() + caughtEvents := 0 + + defer wg.Done() + + for { + select { + case <-updateCh: + caughtEvents++ + if caughtEvents == numOfEvents { + return + } + case <-time.After(10 * time.Second): + t.Errorf("subscription %d did not caught all events", id) + } + } + } + + for i := 0; i < numOfSubscriptions; i++ { + sub := e.subscribe() + subscriptions[i] = sub + + go worker(i, sub) + } + + // Send the events to the channels + for i := 0; i < numOfEvents; i++ { + e.push(&Event{ + NewChain: []*types.Header{ + { + Number: uint64(i), + }, + }, + }) + } + + // Wait for the events to be processed + wg.Wait() + + for _, s := range subscriptions { + s.Close() + } +} diff --git a/blockchain/testing.go b/blockchain/testing.go index 77457d662f..c8935ba5bf 100644 --- a/blockchain/testing.go +++ b/blockchain/testing.go @@ -97,13 +97,14 @@ func NewTestBlockchain(t *testing.T, headers []*types.Header) *Blockchain { Number: 0, GasLimit: 0, } + forksAvail := &chain.Forks{ + chain.EIP155: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + } config := &chain.Chain{ Genesis: genesis, Params: &chain.Params{ - Forks: &chain.Forks{ - EIP155: chain.NewFork(0), - Homestead: chain.NewFork(0), - }, + Forks: forksAvail, BlockGasTarget: defaultBlockGasTarget, }, } @@ -224,7 +225,7 @@ func NewMockBlockchain( type verifyHeaderDelegate func(*types.Header) error type processHeadersDelegate func([]*types.Header) error type getBlockCreatorDelegate func(*types.Header) (types.Address, error) -type preStateCommitDelegate func(*types.Header, *state.Transition) error +type preStateCommitDelegate func(*types.Block, *state.Transition) error type MockVerifier struct { verifyHeaderFn verifyHeaderDelegate @@ -269,9 +270,9 @@ func (m *MockVerifier) HookGetBlockCreator(fn getBlockCreatorDelegate) { m.getBlockCreatorFn = fn } -func (m *MockVerifier) PreCommitState(header *types.Header, txn *state.Transition) error { +func (m *MockVerifier) PreCommitState(block *types.Block, txn *state.Transition) error { if m.preStateCommitFn != nil { - return m.preStateCommitFn(header, txn) + return m.preStateCommitFn(block, txn) } return nil diff --git a/chain/chain.go b/chain/chain.go index 50bf41e1bc..64bed7f1f5 100644 --- a/chain/chain.go +++ b/chain/chain.go @@ -7,17 +7,28 @@ import ( "math/big" "os" + "github.com/hashicorp/go-multierror" + "github.com/umbracle/ethgo" + + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/hex" "github.com/0xPolygon/polygon-edge/types" - "github.com/hashicorp/go-multierror" ) -var ( +const ( + // GenesisBaseFeeEM is the initial base fee elasticity multiplier for EIP-1559 blocks. + GenesisBaseFeeEM = 2 + // GenesisGasLimit is the default gas limit of the Genesis block. GenesisGasLimit uint64 = 4712388 // GenesisDifficulty is the default difficulty of the Genesis block. - GenesisDifficulty = big.NewInt(131072) + GenesisDifficulty uint64 = 131072 +) + +var ( + // GenesisBaseFee is the initial base fee for EIP-1559 blocks. + GenesisBaseFee = ethgo.Gwei(1).Uint64() ) // Chain is the blockchain chain configuration @@ -30,8 +41,6 @@ type Chain struct { // Genesis specifies the header fields, state of a genesis block type Genesis struct { - Config *Params `json:"config"` - Nonce [8]byte `json:"nonce"` Timestamp uint64 `json:"timestamp"` ExtraData []byte `json:"extraData,omitempty"` @@ -40,6 +49,8 @@ type Genesis struct { Mixhash types.Hash `json:"mixHash"` Coinbase types.Address `json:"coinbase"` Alloc map[types.Address]*GenesisAccount `json:"alloc,omitempty"` + BaseFee uint64 `json:"baseFee"` + BaseFeeEM uint64 `json:"baseFeeEM"` // Override StateRoot types.Hash @@ -66,6 +77,7 @@ func (g *Genesis) GenesisHeader() *types.Header { ExtraData: g.ExtraData, GasLimit: g.GasLimit, GasUsed: g.GasUsed, + BaseFee: g.BaseFee, Difficulty: g.Difficulty, MixHash: g.Mixhash, Miner: g.Coinbase.Bytes(), @@ -81,7 +93,11 @@ func (g *Genesis) GenesisHeader() *types.Header { } if g.Difficulty == 0 { - head.Difficulty = GenesisDifficulty.Uint64() + head.Difficulty = GenesisDifficulty + } + + if g.BaseFee == 0 { + head.BaseFee = GenesisBaseFee } return head @@ -109,6 +125,8 @@ func (g *Genesis) MarshalJSON() ([]byte, error) { Number *string `json:"number,omitempty"` GasUsed *string `json:"gasUsed,omitempty"` ParentHash types.Hash `json:"parentHash"` + BaseFee *string `json:"baseFee"` + BaseFeeEM *string `json:"baseFeeEM"` } var enc Genesis @@ -119,6 +137,8 @@ func (g *Genesis) MarshalJSON() ([]byte, error) { enc.GasLimit = types.EncodeUint64(g.GasLimit) enc.Difficulty = types.EncodeUint64(g.Difficulty) + enc.BaseFee = types.EncodeUint64(g.BaseFee) + enc.BaseFeeEM = types.EncodeUint64(g.BaseFeeEM) enc.Mixhash = g.Mixhash enc.Coinbase = g.Coinbase @@ -153,6 +173,8 @@ func (g *Genesis) UnmarshalJSON(data []byte) error { Number *string `json:"number"` GasUsed *string `json:"gasUsed"` ParentHash *types.Hash `json:"parentHash"` + BaseFee *string `json:"baseFee"` + BaseFeeEM *string `json:"baseFeeEM"` } var dec Genesis @@ -166,14 +188,14 @@ func (g *Genesis) UnmarshalJSON(data []byte) error { err = multierror.Append(err, fmt.Errorf("%s: %w", field, subErr)) } - nonce, subErr := types.ParseUint64orHex(dec.Nonce) + nonce, subErr := common.ParseUint64orHex(dec.Nonce) if subErr != nil { parseError("nonce", subErr) } binary.BigEndian.PutUint64(g.Nonce[:], nonce) - g.Timestamp, subErr = types.ParseUint64orHex(dec.Timestamp) + g.Timestamp, subErr = common.ParseUint64orHex(dec.Timestamp) if subErr != nil { parseError("timestamp", subErr) } @@ -189,16 +211,26 @@ func (g *Genesis) UnmarshalJSON(data []byte) error { return fmt.Errorf("field 'gaslimit' is required") } - g.GasLimit, subErr = types.ParseUint64orHex(dec.GasLimit) + g.GasLimit, subErr = common.ParseUint64orHex(dec.GasLimit) if subErr != nil { parseError("gaslimit", subErr) } - g.Difficulty, subErr = types.ParseUint64orHex(dec.Difficulty) + g.Difficulty, subErr = common.ParseUint64orHex(dec.Difficulty) if subErr != nil { parseError("difficulty", subErr) } + g.BaseFee, subErr = common.ParseUint64orHex(dec.BaseFee) + if subErr != nil { + parseError("baseFee", subErr) + } + + g.BaseFeeEM, subErr = common.ParseUint64orHex(dec.BaseFeeEM) + if subErr != nil { + parseError("baseFeeEM", subErr) + } + if dec.Mixhash != nil { g.Mixhash = *dec.Mixhash } @@ -214,12 +246,12 @@ func (g *Genesis) UnmarshalJSON(data []byte) error { } } - g.Number, subErr = types.ParseUint64orHex(dec.Number) + g.Number, subErr = common.ParseUint64orHex(dec.Number) if subErr != nil { parseError("number", subErr) } - g.GasUsed, subErr = types.ParseUint64orHex(dec.GasUsed) + g.GasUsed, subErr = common.ParseUint64orHex(dec.GasUsed) if subErr != nil { parseError("gasused", subErr) } @@ -318,7 +350,7 @@ func (g *GenesisAccount) UnmarshalJSON(data []byte) error { parseError("balance", subErr) } - g.Nonce, subErr = types.ParseUint64orHex(dec.Nonce) + g.Nonce, subErr = common.ParseUint64orHex(dec.Nonce) if subErr != nil { parseError("nonce", subErr) @@ -361,13 +393,3 @@ func importChain(content []byte) (*Chain, error) { return chain, nil } - -// GetGenesisAccountBalance returns balance for genesis account based on its address (expressed in weis). -// If not found in provided allocations map, 0 is returned. -func GetGenesisAccountBalance(address types.Address, allocations map[types.Address]*GenesisAccount) (*big.Int, error) { - if genesisAcc, ok := allocations[address]; ok { - return genesisAcc.Balance, nil - } - - return nil, fmt.Errorf("genesis account %s is not found among genesis allocations", address) -} diff --git a/chain/chain_test.go b/chain/chain_test.go index db88298784..88568a019c 100644 --- a/chain/chain_test.go +++ b/chain/chain_test.go @@ -2,13 +2,11 @@ package chain import ( "encoding/json" - "fmt" "math/big" "reflect" "testing" "github.com/0xPolygon/polygon-edge/types" - "github.com/stretchr/testify/require" ) var emptyAddr types.Address @@ -152,48 +150,3 @@ func TestGenesisX(t *testing.T) { }) } } - -func TestGetGenesisAccountBalance(t *testing.T) { - t.Parallel() - - testAddr := types.Address{0x2} - cases := []struct { - name string - address types.Address - allocs map[types.Address]*GenesisAccount - expectedBalance *big.Int - shouldFail bool - }{ - { - name: "Query existing account", - address: testAddr, - allocs: map[types.Address]*GenesisAccount{ - testAddr: {Balance: big.NewInt(50)}, - }, - expectedBalance: big.NewInt(50), - shouldFail: false, - }, - { - name: "Query non-existing account", - address: testAddr, - allocs: nil, - expectedBalance: nil, - shouldFail: true, - }, - } - - for _, c := range cases { - c := c - t.Run(c.name, func(t *testing.T) { - t.Parallel() - - actualBalance, err := GetGenesisAccountBalance(c.address, c.allocs) - if c.shouldFail { - require.Equal(t, err.Error(), fmt.Errorf("genesis account %s is not found among genesis allocations", c.address).Error()) - } else { - require.NoError(t, err) - } - require.Equal(t, c.expectedBalance, actualBalance) - }) - } -} diff --git a/chain/params.go b/chain/params.go index df1ad6273e..7db1071d59 100644 --- a/chain/params.go +++ b/chain/params.go @@ -1,24 +1,40 @@ package chain import ( - "math/big" + "errors" + "sort" + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/types" ) +var ( + // ErrBurnContractAddressMissing is the error when a contract address is not provided + ErrBurnContractAddressMissing = errors.New("burn contract address missing") +) + // Params are all the set of params for the chain type Params struct { Forks *Forks `json:"forks"` ChainID int64 `json:"chainID"` Engine map[string]interface{} `json:"engine"` - Whitelists *Whitelists `json:"whitelists,omitempty"` BlockGasTarget uint64 `json:"blockGasTarget"` - // AllowList configuration - ContractDeployerAllowList *AllowListConfig `json:"contractDeployerAllowListConfig,omitempty"` + // Access control configuration + ContractDeployerAllowList *AddressListConfig `json:"contractDeployerAllowList,omitempty"` + ContractDeployerBlockList *AddressListConfig `json:"contractDeployerBlockList,omitempty"` + TransactionsAllowList *AddressListConfig `json:"transactionsAllowList,omitempty"` + TransactionsBlockList *AddressListConfig `json:"transactionsBlockList,omitempty"` + BridgeAllowList *AddressListConfig `json:"bridgeAllowList,omitempty"` + BridgeBlockList *AddressListConfig `json:"bridgeBlockList,omitempty"` + + // Governance contract where the token will be sent to and burn in london fork + BurnContract map[uint64]types.Address `json:"burnContract"` + // Destination address to initialize default burn contract with + BurnContractDestinationAddress types.Address `json:"burnContractDestinationAddress,omitempty"` } -type AllowListConfig struct { +type AddressListConfig struct { // AdminAddresses is the list of the initial admin addresses AdminAddresses []types.Address `json:"adminAddresses,omitempty"` @@ -26,103 +42,119 @@ type AllowListConfig struct { EnabledAddresses []types.Address `json:"enabledAddresses,omitempty"` } -func (p *Params) GetEngine() string { - // We know there is already one - for k := range p.Engine { - return k - } +// CalculateBurnContract calculates burn contract address for the given block number +func (p *Params) CalculateBurnContract(block uint64) (types.Address, error) { + blocks := make([]uint64, 0, len(p.BurnContract)) - return "" -} + for startBlock := range p.BurnContract { + blocks = append(blocks, startBlock) + } -// Whitelists specifies supported whitelists -type Whitelists struct { - Deployment []types.Address `json:"deployment,omitempty"` -} + if len(blocks) == 0 { + return types.ZeroAddress, ErrBurnContractAddressMissing + } -// Forks specifies when each fork is activated -type Forks struct { - Homestead *Fork `json:"homestead,omitempty"` - Byzantium *Fork `json:"byzantium,omitempty"` - Constantinople *Fork `json:"constantinople,omitempty"` - Petersburg *Fork `json:"petersburg,omitempty"` - Istanbul *Fork `json:"istanbul,omitempty"` - London *Fork `json:"london,omitempty"` - EIP150 *Fork `json:"EIP150,omitempty"` - EIP158 *Fork `json:"EIP158,omitempty"` - EIP155 *Fork `json:"EIP155,omitempty"` -} + sort.Slice(blocks, func(i, j int) bool { + return blocks[i] < blocks[j] + }) -func (f *Forks) active(ff *Fork, block uint64) bool { - if ff == nil { - return false + for i := 0; i < len(blocks)-1; i++ { + if block >= blocks[i] && block < blocks[i+1] { + return p.BurnContract[blocks[i]], nil + } } - return ff.Active(block) + return p.BurnContract[blocks[len(blocks)-1]], nil } -func (f *Forks) IsHomestead(block uint64) bool { - return f.active(f.Homestead, block) -} +func (p *Params) GetEngine() string { + // We know there is already one + for k := range p.Engine { + return k + } -func (f *Forks) IsByzantium(block uint64) bool { - return f.active(f.Byzantium, block) + return "" } -func (f *Forks) IsConstantinople(block uint64) bool { - return f.active(f.Constantinople, block) -} +// predefined forks +const ( + Homestead = "homestead" + Byzantium = "byzantium" + Constantinople = "constantinople" + Petersburg = "petersburg" + Istanbul = "istanbul" + London = "london" + EIP150 = "EIP150" + EIP158 = "EIP158" + EIP155 = "EIP155" +) -func (f *Forks) IsPetersburg(block uint64) bool { - return f.active(f.Petersburg, block) -} +// Forks is map which contains all forks and their starting blocks from genesis +type Forks map[string]Fork -func (f *Forks) IsLondon(block uint64) bool { - return f.active(f.London, block) -} +// IsActive returns true if fork defined by name exists and defined for the block +func (f *Forks) IsActive(name string, block uint64) bool { + ff, exists := (*f)[name] -func (f *Forks) IsEIP150(block uint64) bool { - return f.active(f.EIP150, block) + return exists && ff.Active(block) } -func (f *Forks) IsEIP158(block uint64) bool { - return f.active(f.EIP158, block) +// SetFork adds/updates fork defined by name +func (f *Forks) SetFork(name string, value Fork) { + (*f)[name] = value } -func (f *Forks) IsEIP155(block uint64) bool { - return f.active(f.EIP155, block) +func (f *Forks) RemoveFork(name string) { + delete(*f, name) } +// At returns ForksInTime instance that shows which supported forks are enabled for the block func (f *Forks) At(block uint64) ForksInTime { return ForksInTime{ - Homestead: f.active(f.Homestead, block), - Byzantium: f.active(f.Byzantium, block), - Constantinople: f.active(f.Constantinople, block), - Petersburg: f.active(f.Petersburg, block), - Istanbul: f.active(f.Istanbul, block), - London: f.active(f.London, block), - EIP150: f.active(f.EIP150, block), - EIP158: f.active(f.EIP158, block), - EIP155: f.active(f.EIP155, block), + Homestead: f.IsActive(Homestead, block), + Byzantium: f.IsActive(Byzantium, block), + Constantinople: f.IsActive(Constantinople, block), + Petersburg: f.IsActive(Petersburg, block), + Istanbul: f.IsActive(Istanbul, block), + London: f.IsActive(London, block), + EIP150: f.IsActive(EIP150, block), + EIP158: f.IsActive(EIP158, block), + EIP155: f.IsActive(EIP155, block), } } -type Fork uint64 +// ForkParams hard-coded fork params +type ForkParams struct { + // MaxValidatorSetSize indicates the maximum size of validator set + MaxValidatorSetSize *uint64 `json:"maxValidatorSetSize,omitempty"` + + // EpochSize is size of epoch + EpochSize *uint64 `json:"epochSize,omitempty"` -func NewFork(n uint64) *Fork { - f := Fork(n) + // SprintSize is size of sprint + SprintSize *uint64 `json:"sprintSize,omitempty"` - return &f + // BlockTime is target frequency of blocks production + BlockTime *common.Duration `json:"blockTime,omitempty"` + + // BlockTimeDrift defines the time slot in which a new block can be created + BlockTimeDrift *uint64 `json:"blockTimeDrift,omitempty"` } -func (f Fork) Active(block uint64) bool { - return block >= uint64(f) +type Fork struct { + Block uint64 `json:"block"` + Params *ForkParams `json:"params,omitempty"` } -func (f Fork) Int() *big.Int { - return big.NewInt(int64(f)) +func NewFork(n uint64) Fork { + return Fork{Block: n} +} + +func (f Fork) Active(block uint64) bool { + return block >= f.Block } +// ForksInTime should contain all supported forks by current edge version type ForksInTime struct { Homestead, Byzantium, @@ -135,6 +167,7 @@ type ForksInTime struct { EIP155 bool } +// AllForksEnabled should contain all supported forks by current edge version var AllForksEnabled = &Forks{ Homestead: NewFork(0), EIP150: NewFork(0), diff --git a/chain/params_test.go b/chain/params_test.go index be27a2a4ad..775f5597f9 100644 --- a/chain/params_test.go +++ b/chain/params_test.go @@ -4,6 +4,10 @@ import ( "encoding/json" "reflect" "testing" + + "github.com/stretchr/testify/require" + + "github.com/0xPolygon/polygon-edge/types" ) func TestParamsForks(t *testing.T) { @@ -13,7 +17,7 @@ func TestParamsForks(t *testing.T) { }{ { input: `{ - "homestead": 1000 + "homestead": { "block": 1000 } }`, output: &Forks{ Homestead: NewFork(1000), @@ -54,3 +58,73 @@ func TestParamsForksInTime(t *testing.T) { expect("constantinople", ff.Constantinople, false) expect("eip150", ff.EIP150, false) } + +func TestParams_CalculateBurnContract(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + burnContract map[uint64]types.Address + block uint64 + want types.Address + wantErr bool + }{ + { + name: "no addresses in the list", + burnContract: map[uint64]types.Address{}, + block: 10, + want: types.ZeroAddress, + wantErr: true, + }, + { + name: "last address is used", + burnContract: map[uint64]types.Address{ + 15: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c9db1"), + }, + block: 10, + want: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c9db1"), + wantErr: false, + }, + { + name: "first address is used", + burnContract: map[uint64]types.Address{ + 5: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c9db2"), + 15: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c9db1"), + }, + block: 10, + want: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c9db2"), + wantErr: false, + }, + { + name: "same block as key", + burnContract: map[uint64]types.Address{ + 5: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c4db2"), + 10: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c5db1"), + 15: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c6db0"), + }, + block: 10, + want: types.StringToAddress("0x8888f1f195afa192cfee860698584c030f4c5db1"), + wantErr: false, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + p := &Params{ + BurnContract: tt.burnContract, + } + + got, err := p.CalculateBurnContract(tt.block) + if tt.wantErr { + require.Error(t, err, "CalculateBurnContract() error = %v, wantErr %v", err, tt.wantErr) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, got, "CalculateBurnContract() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/command/bridge/README.md b/command/bridge/README.md index b72e9037c2..db89ca9863 100644 --- a/command/bridge/README.md +++ b/command/bridge/README.md @@ -13,10 +13,11 @@ $ polygon-edge bridge deposit-erc20 \ --amounts \ --root-token \ --root-predicate \ - --json-rpc + --json-rpc + [--minter-key ] ``` -**Note:** for using test account provided by Geth dev instance, use `--test` flag. In that case `--sender-key` flag can be omitted and test account is used as a depositor. +**Note:** in case `minter-key` is provided, tokens are going to be minted to sender account. Note that provided minter private key must belong to the account which has minter role. ## Withdraw ERC20 @@ -27,9 +28,9 @@ $ polygon-edge bridge withdraw-erc20 \ --sender-key \ --receivers \ --amounts \ - --child-predicate \ + --child-predicate \ [--child-token ] \ - --json-rpc + --json-rpc ``` ## Exit diff --git a/command/bridge/bridge.go b/command/bridge/bridge.go index bf9d334f9d..2fd8ef2c30 100644 --- a/command/bridge/bridge.go +++ b/command/bridge/bridge.go @@ -3,9 +3,13 @@ package bridge import ( "github.com/spf13/cobra" - "github.com/0xPolygon/polygon-edge/command/bridge/deposit" + depositERC1155 "github.com/0xPolygon/polygon-edge/command/bridge/deposit/erc1155" + depositERC20 "github.com/0xPolygon/polygon-edge/command/bridge/deposit/erc20" + depositERC721 "github.com/0xPolygon/polygon-edge/command/bridge/deposit/erc721" "github.com/0xPolygon/polygon-edge/command/bridge/exit" - "github.com/0xPolygon/polygon-edge/command/bridge/withdraw" + withdrawERC1155 "github.com/0xPolygon/polygon-edge/command/bridge/withdraw/erc1155" + withdrawERC20 "github.com/0xPolygon/polygon-edge/command/bridge/withdraw/erc20" + withdrawERC721 "github.com/0xPolygon/polygon-edge/command/bridge/withdraw/erc721" ) // GetCommand creates "bridge" helper command @@ -22,10 +26,18 @@ func GetCommand() *cobra.Command { func registerSubcommands(baseCmd *cobra.Command) { baseCmd.AddCommand( - // bridge deposit - deposit.GetCommand(), - // bridge withdraw - withdraw.GetCommand(), + // bridge deposit-erc20 + depositERC20.GetCommand(), + // bridge deposit-erc721 + depositERC721.GetCommand(), + // bridge deposit-erc1155 + depositERC1155.GetCommand(), + // bridge withdraw-erc20 + withdrawERC20.GetCommand(), + // bridge withdraw-erc721 + withdrawERC721.GetCommand(), + // bridge withdraw-erc1155 + withdrawERC1155.GetCommand(), // bridge exit exit.GetCommand(), ) diff --git a/command/bridge/common/bridge_erc20_params.go b/command/bridge/common/bridge_erc20_params.go deleted file mode 100644 index 3840426f32..0000000000 --- a/command/bridge/common/bridge_erc20_params.go +++ /dev/null @@ -1,29 +0,0 @@ -package common - -import ( - "errors" -) - -const ( - SenderKeyFlag = "sender-key" - ReceiversFlag = "receivers" - AmountsFlag = "amounts" -) - -var ( - errInconsistentAccounts = errors.New("receivers and amounts must be equal length") -) - -type ERC20BridgeParams struct { - SenderKey string - Receivers []string - Amounts []string -} - -func (bp *ERC20BridgeParams) ValidateFlags() error { - if len(bp.Receivers) != len(bp.Amounts) { - return errInconsistentAccounts - } - - return nil -} diff --git a/command/bridge/common/params.go b/command/bridge/common/params.go new file mode 100644 index 0000000000..1bbb098dc7 --- /dev/null +++ b/command/bridge/common/params.go @@ -0,0 +1,264 @@ +package common + +import ( + "bytes" + "errors" + "fmt" + "math/big" + "strings" + + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" + + cmdHelper "github.com/0xPolygon/polygon-edge/command/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" +) + +type TokenType int + +const ( + ERC20 TokenType = iota + ERC721 + ERC1155 +) + +const ( + SenderKeyFlag = "sender-key" + ReceiversFlag = "receivers" + AmountsFlag = "amounts" + TokenIDsFlag = "token-ids" + RootTokenFlag = "root-token" + RootPredicateFlag = "root-predicate" + ChildPredicateFlag = "child-predicate" + ChildTokenFlag = "child-token" + JSONRPCFlag = "json-rpc" + ChildChainMintableFlag = "child-chain-mintable" + + MinterKeyFlag = "minter-key" + MinterKeyFlagDesc = "minter key is the account which is able to mint tokens to sender account " + + "(if provided tokens are minted prior to depositing)" +) + +var ( + errInconsistentAmounts = errors.New("receivers and amounts must be equal length") + errInconsistentTokenIds = errors.New("receivers and token ids must be equal length") +) + +type BridgeParams struct { + SenderKey string + Receivers []string + TokenAddr string + PredicateAddr string + JSONRPCAddr string + ChildChainMintable bool +} + +// RegisterCommonFlags registers common bridge flags to a given command +func (p *BridgeParams) RegisterCommonFlags(cmd *cobra.Command) { + cmd.Flags().StringVar( + &p.SenderKey, + SenderKeyFlag, + "", + "hex encoded private key of the account which sends bridge transactions", + ) + + cmd.Flags().StringSliceVar( + &p.Receivers, + ReceiversFlag, + nil, + "receiving accounts addresses", + ) + + cmd.Flags().StringVar( + &p.JSONRPCAddr, + JSONRPCFlag, + txrelayer.DefaultRPCAddress, + "the JSON RPC endpoint", + ) + + cmd.Flags().BoolVar( + &p.ChildChainMintable, + ChildChainMintableFlag, + false, + "flag indicating whether tokens originate from child chain", + ) +} + +type ERC20BridgeParams struct { + *BridgeParams + Amounts []string +} + +func NewERC20BridgeParams() *ERC20BridgeParams { + return &ERC20BridgeParams{BridgeParams: &BridgeParams{}} +} + +func (bp *ERC20BridgeParams) Validate() error { + if len(bp.Receivers) != len(bp.Amounts) { + return errInconsistentAmounts + } + + return nil +} + +type ERC721BridgeParams struct { + *BridgeParams + TokenIDs []string +} + +func NewERC721BridgeParams() *ERC721BridgeParams { + return &ERC721BridgeParams{BridgeParams: &BridgeParams{}} +} + +func (bp *ERC721BridgeParams) Validate() error { + if len(bp.Receivers) != len(bp.TokenIDs) { + return errInconsistentTokenIds + } + + return nil +} + +type ERC1155BridgeParams struct { + *BridgeParams + Amounts []string + TokenIDs []string +} + +func NewERC1155BridgeParams() *ERC1155BridgeParams { + return &ERC1155BridgeParams{BridgeParams: &BridgeParams{}} +} + +func (bp *ERC1155BridgeParams) Validate() error { + if len(bp.Receivers) != len(bp.Amounts) { + return errInconsistentAmounts + } + + if len(bp.Receivers) != len(bp.TokenIDs) { + return errInconsistentTokenIds + } + + return nil +} + +// ExtractExitEventID tries to extract exit event id from provided receipt +func ExtractExitEventID(receipt *ethgo.Receipt) (*big.Int, error) { + var exitEvent contractsapi.L2StateSyncedEvent + for _, log := range receipt.Logs { + doesMatch, err := exitEvent.ParseLog(log) + if err != nil { + return nil, err + } + + if !doesMatch { + continue + } + + return exitEvent.ID, nil + } + + return nil, errors.New("failed to find exit event log") +} + +// ExtractChildTokenAddr extracts predicted deterministic child token address +func ExtractChildTokenAddr(receipt *ethgo.Receipt, childChainMintable bool) (*types.Address, error) { + var ( + l1TokenMapped contractsapi.TokenMappedEvent + l2TokenMapped contractsapi.L2MintableTokenMappedEvent + ) + + for _, log := range receipt.Logs { + if childChainMintable { + doesMatch, err := l2TokenMapped.ParseLog(log) + if err != nil { + return nil, err + } + + if !doesMatch { + continue + } + + return &l2TokenMapped.ChildToken, nil + } else { + doesMatch, err := l1TokenMapped.ParseLog(log) + if err != nil { + return nil, err + } + + if !doesMatch { + continue + } + + return &l1TokenMapped.ChildToken, nil + } + } + + return nil, nil +} + +type BridgeTxResult struct { + Sender string `json:"sender"` + Receivers []string `json:"receivers"` + ExitEventIDs []*big.Int `json:"exitEventIDs"` + Amounts []string `json:"amounts"` + TokenIDs []string `json:"tokenIds"` + BlockNumbers []uint64 `json:"blockNumbers"` + ChildTokenAddr *types.Address `json:"childTokenAddr"` + + Title string `json:"title"` +} + +func (r *BridgeTxResult) GetOutput() string { + var buffer bytes.Buffer + + vals := make([]string, 0, 7) + vals = append(vals, fmt.Sprintf("Sender|%s", r.Sender)) + vals = append(vals, fmt.Sprintf("Receivers|%s", strings.Join(r.Receivers, ", "))) + + if len(r.Amounts) > 0 { + vals = append(vals, fmt.Sprintf("Amounts|%s", strings.Join(r.Amounts, ", "))) + } + + if len(r.TokenIDs) > 0 { + vals = append(vals, fmt.Sprintf("Token Ids|%s", strings.Join(r.TokenIDs, ", "))) + } + + if len(r.ExitEventIDs) > 0 { + var buf bytes.Buffer + + for i, id := range r.ExitEventIDs { + buf.WriteString(id.String()) + + if i != len(r.ExitEventIDs)-1 { + buf.WriteString(", ") + } + } + + vals = append(vals, fmt.Sprintf("Exit Event IDs|%s", buf.String())) + } + + if len(r.BlockNumbers) > 0 { + var buf bytes.Buffer + + for i, blockNum := range r.BlockNumbers { + buf.WriteString(fmt.Sprintf("%d", blockNum)) + + if i != len(r.BlockNumbers)-1 { + buf.WriteString(", ") + } + } + + vals = append(vals, fmt.Sprintf("Inclusion Block Numbers|%s", buf.String())) + } + + if r.ChildTokenAddr != nil { + vals = append(vals, fmt.Sprintf("Child Token Address|%s", (*r.ChildTokenAddr).String())) + } + + _, _ = buffer.WriteString(fmt.Sprintf("\n[%s]\n", r.Title)) + _, _ = buffer.WriteString(cmdHelper.FormatKV(vals)) + _, _ = buffer.WriteString("\n") + + return buffer.String() +} diff --git a/command/bridge/deposit/deposit_erc20.go b/command/bridge/deposit/deposit_erc20.go deleted file mode 100644 index c85b6e0b11..0000000000 --- a/command/bridge/deposit/deposit_erc20.go +++ /dev/null @@ -1,327 +0,0 @@ -package deposit - -import ( - "bytes" - "fmt" - "math/big" - "strings" - - "github.com/spf13/cobra" - "github.com/umbracle/ethgo" - "golang.org/x/sync/errgroup" - - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/command/bridge/common" - cmdHelper "github.com/0xPolygon/polygon-edge/command/helper" - "github.com/0xPolygon/polygon-edge/command/rootchain/helper" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/txrelayer" - "github.com/0xPolygon/polygon-edge/types" -) - -const ( - rootTokenFlag = "root-token" - rootPredicateFlag = "root-predicate" - jsonRPCFlag = "json-rpc" -) - -type depositERC20Params struct { - *common.ERC20BridgeParams - rootTokenAddr string - rootPredicateAddr string - jsonRPCAddress string - testMode bool -} - -var ( - // depositParams is abstraction for provided bridge parameter values - dp *depositERC20Params = &depositERC20Params{ERC20BridgeParams: &common.ERC20BridgeParams{}} -) - -// GetCommand returns the bridge deposit command -func GetCommand() *cobra.Command { - depositCmd := &cobra.Command{ - Use: "deposit-erc20", - Short: "Deposits ERC20 tokens from the root chain to the child chain", - PreRunE: runPreRun, - Run: runCommand, - } - - depositCmd.Flags().StringVar( - &dp.SenderKey, - common.SenderKeyFlag, - "", - "hex encoded private key of the account which sends rootchain deposit transactions", - ) - - depositCmd.Flags().StringSliceVar( - &dp.Receivers, - common.ReceiversFlag, - nil, - "receiving accounts addresses on child chain", - ) - - depositCmd.Flags().StringSliceVar( - &dp.Amounts, - common.AmountsFlag, - nil, - "amounts to send to receiving accounts", - ) - - depositCmd.Flags().StringVar( - &dp.rootTokenAddr, - rootTokenFlag, - "", - "root ERC20 token address", - ) - - depositCmd.Flags().StringVar( - &dp.rootPredicateAddr, - rootPredicateFlag, - "", - "root ERC20 token predicate address", - ) - - depositCmd.Flags().StringVar( - &dp.jsonRPCAddress, - jsonRPCFlag, - "http://127.0.0.1:8545", - "the JSON RPC root chain endpoint", - ) - - depositCmd.Flags().BoolVar( - &dp.testMode, - helper.TestModeFlag, - false, - "test indicates whether depositor is hardcoded test account "+ - "(in that case tokens are minted to it, so it is able to make deposits)", - ) - - _ = depositCmd.MarkFlagRequired(common.ReceiversFlag) - _ = depositCmd.MarkFlagRequired(common.AmountsFlag) - _ = depositCmd.MarkFlagRequired(rootTokenFlag) - _ = depositCmd.MarkFlagRequired(rootPredicateFlag) - - depositCmd.MarkFlagsMutuallyExclusive(helper.TestModeFlag, common.SenderKeyFlag) - - return depositCmd -} - -func runPreRun(cmd *cobra.Command, _ []string) error { - if err := dp.ValidateFlags(); err != nil { - return err - } - - return nil -} - -func runCommand(cmd *cobra.Command, _ []string) { - outputter := command.InitializeOutputter(cmd) - defer outputter.WriteOutput() - - depositorKey, err := helper.GetRootchainPrivateKey(dp.SenderKey) - if err != nil { - outputter.SetError(fmt.Errorf("failed to initialize depositor private key: %w", err)) - } - - depositorAddr := depositorKey.Address() - - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(dp.jsonRPCAddress)) - if err != nil { - outputter.SetError(fmt.Errorf("failed to initialize rootchain tx relayer: %w", err)) - - return - } - - amounts := make([]*big.Int, len(dp.Amounts)) - aggregateAmount := new(big.Int) - - for i, amountRaw := range dp.Amounts { - amountRaw := amountRaw - - amount, err := types.ParseUint256orHex(&amountRaw) - if err != nil { - outputter.SetError(fmt.Errorf("failed to decode provided amount %s: %w", amount, err)) - - return - } - - amounts[i] = amount - aggregateAmount.Add(aggregateAmount, amount) - } - - if dp.testMode { - // mint tokens to depositor, so he is able to send them - mintTxn, err := createMintTxn(types.Address(depositorAddr), types.Address(depositorAddr), aggregateAmount) - if err != nil { - outputter.SetError(fmt.Errorf("mint transaction creation failed: %w", err)) - - return - } - - receipt, err := txRelayer.SendTransaction(mintTxn, depositorKey) - if err != nil { - outputter.SetError(fmt.Errorf("failed to send mint transaction to depositor %s", depositorAddr)) - - return - } - - if receipt.Status == uint64(types.ReceiptFailed) { - outputter.SetError(fmt.Errorf("failed to mint tokens to depositor %s", depositorAddr)) - - return - } - } - - // approve root erc20 predicate - approveTxn, err := createApproveERC20PredicateTxn(aggregateAmount, - types.StringToAddress(dp.rootPredicateAddr), - types.StringToAddress(dp.rootTokenAddr)) - if err != nil { - outputter.SetError(fmt.Errorf("failed to create root erc20 approve transaction: %w", err)) - - return - } - - receipt, err := txRelayer.SendTransaction(approveTxn, depositorKey) - if err != nil { - outputter.SetError(fmt.Errorf("failed to send root erc20 approve transaction")) - - return - } - - if receipt.Status == uint64(types.ReceiptFailed) { - outputter.SetError(fmt.Errorf("failed to approve root erc20 predicate")) - - return - } - - g, ctx := errgroup.WithContext(cmd.Context()) - - for i := range dp.Receivers { - receiver := dp.Receivers[i] - amount := amounts[i] - - g.Go(func() error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - // deposit tokens - depositTxn, err := createDepositTxn(types.Address(depositorAddr), types.StringToAddress(receiver), amount) - if err != nil { - return fmt.Errorf("failed to create tx input: %w", err) - } - - receipt, err = txRelayer.SendTransaction(depositTxn, depositorKey) - if err != nil { - return fmt.Errorf("receiver: %s, amount: %s, error: %w", receiver, amount, err) - } - - if receipt.Status == uint64(types.ReceiptFailed) { - return fmt.Errorf("receiver: %s, amount: %s", receiver, amount) - } - - return nil - } - }) - } - - if err = g.Wait(); err != nil { - outputter.SetError(fmt.Errorf("sending deposit transactions to the rootchain failed: %w", err)) - - return - } - - outputter.SetCommandResult(&depositERC20Result{ - Sender: depositorAddr.String(), - Receivers: dp.Receivers, - Amounts: dp.Amounts, - }) -} - -// createDepositTxn encodes parameters for deposit function on rootchain predicate contract -func createDepositTxn(sender, receiver types.Address, amount *big.Int) (*ethgo.Transaction, error) { - depositToFn := &contractsapi.DepositToRootERC20PredicateFn{ - RootToken: types.StringToAddress(dp.rootTokenAddr), - Receiver: receiver, - Amount: amount, - } - - input, err := depositToFn.EncodeAbi() - if err != nil { - return nil, fmt.Errorf("failed to encode provided parameters: %w", err) - } - - addr := ethgo.Address(types.StringToAddress(dp.rootPredicateAddr)) - - return ðgo.Transaction{ - From: ethgo.Address(sender), - To: &addr, - Input: input, - }, nil -} - -// createMintTxn encodes parameters for mint function on rootchain token contract -func createMintTxn(sender, receiver types.Address, amount *big.Int) (*ethgo.Transaction, error) { - mintFn := &contractsapi.MintRootERC20Fn{ - To: receiver, - Amount: amount, - } - - input, err := mintFn.EncodeAbi() - if err != nil { - return nil, fmt.Errorf("failed to encode provided parameters: %w", err) - } - - addr := ethgo.Address(types.StringToAddress(dp.rootTokenAddr)) - - return ðgo.Transaction{ - From: ethgo.Address(sender), - To: &addr, - Input: input, - }, nil -} - -// createApproveERC20PredicateTxn sends approve transaction -// to ERC20 token for ERC20 predicate so that it is able to spend given tokens -func createApproveERC20PredicateTxn(amount *big.Int, - rootERC20Predicate, rootERC20Token types.Address) (*ethgo.Transaction, error) { - approveFnParams := &contractsapi.ApproveRootERC20Fn{ - Spender: rootERC20Predicate, - Amount: amount, - } - - input, err := approveFnParams.EncodeAbi() - if err != nil { - return nil, fmt.Errorf("failed to encode parameters for RootERC20.approve. error: %w", err) - } - - addr := ethgo.Address(rootERC20Token) - - return ðgo.Transaction{ - To: &addr, - Input: input, - }, nil -} - -type depositERC20Result struct { - Sender string `json:"sender"` - Receivers []string `json:"receivers"` - Amounts []string `json:"amounts"` -} - -func (r *depositERC20Result) GetOutput() string { - var buffer bytes.Buffer - - vals := make([]string, 0, 3) - vals = append(vals, fmt.Sprintf("Sender|%s", r.Sender)) - vals = append(vals, fmt.Sprintf("Receivers|%s", strings.Join(r.Receivers, ", "))) - vals = append(vals, fmt.Sprintf("Amounts|%s", strings.Join(r.Amounts, ", "))) - - buffer.WriteString("\n[DEPOSIT ERC20]\n") - buffer.WriteString(cmdHelper.FormatKV(vals)) - buffer.WriteString("\n") - - return buffer.String() -} diff --git a/command/bridge/deposit/erc1155/deposit_erc1155.go b/command/bridge/deposit/erc1155/deposit_erc1155.go new file mode 100644 index 0000000000..7cfaf8cb83 --- /dev/null +++ b/command/bridge/deposit/erc1155/deposit_erc1155.go @@ -0,0 +1,312 @@ +package erc1155 + +import ( + "fmt" + "math/big" + "strings" + + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/bridge/common" + "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" +) + +type depositERC1155Params struct { + *common.ERC1155BridgeParams + minterKey string +} + +var ( + // depositParams is abstraction for provided bridge parameter values + dp *depositERC1155Params = &depositERC1155Params{ERC1155BridgeParams: common.NewERC1155BridgeParams()} +) + +// GetCommand returns the bridge deposit command +func GetCommand() *cobra.Command { + depositCmd := &cobra.Command{ + Use: "deposit-erc1155", + Short: "Deposits ERC 1155 tokens from the origin to the destination chain", + PreRunE: preRunCommand, + Run: runCommand, + } + + dp.RegisterCommonFlags(depositCmd) + + depositCmd.Flags().StringSliceVar( + &dp.Amounts, + common.AmountsFlag, + nil, + "amounts that are sent to the receivers accounts", + ) + + depositCmd.Flags().StringSliceVar( + &dp.TokenIDs, + common.TokenIDsFlag, + nil, + "token ids that are sent to the receivers accounts", + ) + + depositCmd.Flags().StringVar( + &dp.TokenAddr, + common.RootTokenFlag, + "", + "root ERC 1155 token address", + ) + + depositCmd.Flags().StringVar( + &dp.PredicateAddr, + common.RootPredicateFlag, + "", + "root ERC 1155 token predicate address", + ) + + depositCmd.Flags().StringVar( + &dp.minterKey, + common.MinterKeyFlag, + "", + common.MinterKeyFlagDesc, + ) + + _ = depositCmd.MarkFlagRequired(common.ReceiversFlag) + _ = depositCmd.MarkFlagRequired(common.AmountsFlag) + _ = depositCmd.MarkFlagRequired(common.TokenIDsFlag) + _ = depositCmd.MarkFlagRequired(common.RootTokenFlag) + _ = depositCmd.MarkFlagRequired(common.RootPredicateFlag) + + return depositCmd +} + +func preRunCommand(_ *cobra.Command, _ []string) error { + return dp.Validate() +} + +func runCommand(cmd *cobra.Command, _ []string) { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + depositorKey, err := helper.DecodePrivateKey(dp.SenderKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize depositor private key: %w", err)) + } + + depositorAddr := depositorKey.Address() + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(dp.JSONRPCAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize tx relayer: %w", err)) + + return + } + + amounts := make([]*big.Int, len(dp.Amounts)) + tokenIDs := make([]*big.Int, len(dp.TokenIDs)) + + for i := range dp.Receivers { + amountRaw := dp.Amounts[i] + tokenIDRaw := dp.TokenIDs[i] + + amount, err := types.ParseUint256orHex(&amountRaw) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode provided amount %s: %w", amountRaw, err)) + + return + } + + amounts[i] = amount + + tokenID, err := types.ParseUint256orHex(&tokenIDRaw) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode provided token id %s: %w", tokenIDRaw, err)) + + return + } + + tokenIDs[i] = tokenID + } + + if dp.minterKey != "" { + minterKey, err := helper.DecodePrivateKey(dp.minterKey) + if err != nil { + outputter.SetError(fmt.Errorf("invalid minter key provided: %w", err)) + + return + } + + // mint tokens to depositor, so he is able to send them + mintTxn, err := createMintTxn(types.Address(depositorAddr), types.Address(depositorAddr), amounts, tokenIDs) + if err != nil { + outputter.SetError(fmt.Errorf("mint transaction creation failed: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(mintTxn, minterKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send mint transaction to depositor %s", depositorAddr)) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to mint tokens to depositor %s", depositorAddr)) + + return + } + } + + // approve root erc1155 predicate + approveTxn, err := createApproveERC1155PredicateTxn( + types.StringToAddress(dp.PredicateAddr), + types.StringToAddress(dp.TokenAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("failed to create root erc 1155 approve transaction: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(approveTxn, depositorKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send root erc 1155 approve transaction")) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to approve root erc 1155 predicate")) + + return + } + + receivers := make([]ethgo.Address, len(dp.Receivers)) + for i, receiverRaw := range dp.Receivers { + receivers[i] = ethgo.Address(types.StringToAddress(receiverRaw)) + } + + // deposit tokens + depositTxn, err := createDepositTxn(depositorAddr, receivers, amounts, tokenIDs) + if err != nil { + outputter.SetError(fmt.Errorf("failed to create tx input: %w", err)) + + return + } + + receipt, err = txRelayer.SendTransaction(depositTxn, depositorKey) + if err != nil { + outputter.SetError(fmt.Errorf("sending deposit transactions failed (receivers: %s, amount: %s): %w", + strings.Join(dp.Receivers, ", "), strings.Join(dp.Amounts, ", "), err)) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("sending deposit transactions failed (receivers: %s, amounts: %s)", + strings.Join(dp.Receivers, ", "), strings.Join(dp.Amounts, ", "))) + + return + } + + res := &common.BridgeTxResult{ + Sender: depositorAddr.String(), + Receivers: dp.Receivers, + Amounts: dp.Amounts, + TokenIDs: dp.TokenIDs, + BlockNumbers: []uint64{receipt.BlockNumber}, + Title: "DEPOSIT ERC 1155", + } + + if dp.ChildChainMintable { + exitEventID, err := common.ExtractExitEventID(receipt) + if err != nil { + outputter.SetError(fmt.Errorf("failed to extract exit event: %w", err)) + + return + } + + res.ExitEventIDs = []*big.Int{exitEventID} + } + + // populate child token address if a token is mapped alongside with deposit + childToken, err := common.ExtractChildTokenAddr(receipt, dp.ChildChainMintable) + if err != nil { + outputter.SetError(fmt.Errorf("failed to extract child token address: %w", err)) + + return + } + + res.ChildTokenAddr = childToken + + outputter.SetCommandResult(res) +} + +// createDepositTxn encodes parameters for deposit function on rootchain predicate contract +func createDepositTxn(sender ethgo.Address, receivers []ethgo.Address, + amounts, tokenIDs []*big.Int) (*ethgo.Transaction, error) { + depositBatchFn := &contractsapi.DepositBatchRootERC1155PredicateFn{ + RootToken: types.StringToAddress(dp.TokenAddr), + Receivers: receivers, + TokenIDs: tokenIDs, + Amounts: amounts, + } + + input, err := depositBatchFn.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(types.StringToAddress(dp.PredicateAddr)) + + return ðgo.Transaction{ + From: sender, + To: &addr, + Input: input, + }, nil +} + +// createMintTxn encodes parameters for mint function on rootchain token contract +func createMintTxn(sender, receiver types.Address, amounts, tokenIDs []*big.Int) (*ethgo.Transaction, error) { + mintFn := &contractsapi.MintBatchRootERC1155Fn{ + To: receiver, + Amounts: amounts, + IDs: tokenIDs, + } + + input, err := mintFn.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(types.StringToAddress(dp.TokenAddr)) + + return ðgo.Transaction{ + From: ethgo.Address(sender), + To: &addr, + Input: input, + }, nil +} + +// createApproveERC1155PredicateTxn sends approve transaction +// to ERC1155 token for ERC1155 predicate so that it is able to spend given tokens +func createApproveERC1155PredicateTxn(rootERC1155Predicate, + rootERC1155Token types.Address) (*ethgo.Transaction, error) { + approveFnParams := &contractsapi.SetApprovalForAllRootERC1155Fn{ + Operator: rootERC1155Predicate, + Approved: true, + } + + input, err := approveFnParams.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode parameters for RootERC1155.setApprovalForAll. error: %w", err) + } + + addr := ethgo.Address(rootERC1155Token) + + return ðgo.Transaction{ + To: &addr, + Input: input, + }, nil +} diff --git a/command/bridge/deposit/erc20/deposit_erc20.go b/command/bridge/deposit/erc20/deposit_erc20.go new file mode 100644 index 0000000000..48efebecf8 --- /dev/null +++ b/command/bridge/deposit/erc20/deposit_erc20.go @@ -0,0 +1,284 @@ +package erc20 + +import ( + "fmt" + "math/big" + + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" + "golang.org/x/sync/errgroup" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/bridge/common" + "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" +) + +type depositERC20Params struct { + *common.ERC20BridgeParams + minterKey string +} + +var ( + // depositParams is abstraction for provided bridge parameter values + dp *depositERC20Params = &depositERC20Params{ERC20BridgeParams: common.NewERC20BridgeParams()} +) + +// GetCommand returns the bridge deposit command +func GetCommand() *cobra.Command { + depositCmd := &cobra.Command{ + Use: "deposit-erc20", + Short: "Deposits ERC 20 tokens from the origin to the destination chain", + PreRunE: preRunCommand, + Run: runCommand, + } + + dp.RegisterCommonFlags(depositCmd) + + depositCmd.Flags().StringSliceVar( + &dp.Amounts, + common.AmountsFlag, + nil, + "amounts to send to receiving accounts", + ) + + depositCmd.Flags().StringVar( + &dp.TokenAddr, + common.RootTokenFlag, + "", + "root ERC 20 token address", + ) + + depositCmd.Flags().StringVar( + &dp.PredicateAddr, + common.RootPredicateFlag, + "", + "root ERC 20 token predicate address", + ) + + depositCmd.Flags().StringVar( + &dp.minterKey, + common.MinterKeyFlag, + "", + common.MinterKeyFlagDesc, + ) + + _ = depositCmd.MarkFlagRequired(common.ReceiversFlag) + _ = depositCmd.MarkFlagRequired(common.AmountsFlag) + _ = depositCmd.MarkFlagRequired(common.RootTokenFlag) + _ = depositCmd.MarkFlagRequired(common.RootPredicateFlag) + + return depositCmd +} + +func preRunCommand(cmd *cobra.Command, _ []string) error { + return dp.Validate() +} + +func runCommand(cmd *cobra.Command, _ []string) { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + depositorKey, err := helper.DecodePrivateKey(dp.SenderKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize depositor private key: %w", err)) + } + + depositorAddr := depositorKey.Address() + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(dp.JSONRPCAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize tx relayer: %w", err)) + + return + } + + amounts := make([]*big.Int, len(dp.Amounts)) + aggregateAmount := new(big.Int) + + for i, amountRaw := range dp.Amounts { + amountRaw := amountRaw + + amount, err := types.ParseUint256orHex(&amountRaw) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode provided amount %s: %w", amountRaw, err)) + + return + } + + amounts[i] = amount + aggregateAmount.Add(aggregateAmount, amount) + } + + if dp.minterKey != "" { + minterKey, err := helper.DecodePrivateKey(dp.minterKey) + if err != nil { + outputter.SetError(fmt.Errorf("invalid minter key provided: %w", err)) + + return + } + + // mint tokens to depositor, so he is able to send them + mintTxn, err := helper.CreateMintTxn(types.Address(depositorAddr), + types.StringToAddress(dp.TokenAddr), aggregateAmount) + if err != nil { + outputter.SetError(fmt.Errorf("mint transaction creation failed: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(mintTxn, minterKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send mint transaction to depositor %s", depositorAddr)) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to mint tokens to depositor %s", depositorAddr)) + + return + } + } + + // approve erc20 predicate + approveTxn, err := helper.CreateApproveERC20Txn(aggregateAmount, + types.StringToAddress(dp.PredicateAddr), + types.StringToAddress(dp.TokenAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("failed to create root erc 20 approve transaction: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(approveTxn, depositorKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send root erc 20 approve transaction")) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to approve root erc 20 predicate")) + + return + } + + type bridgeTxData struct { + exitEventID *big.Int + blockNumber uint64 + childTokenAddr *types.Address + } + + g, ctx := errgroup.WithContext(cmd.Context()) + bridgeTxCh := make(chan bridgeTxData, len(dp.Receivers)) + exitEventIDs := make([]*big.Int, 0, len(dp.Receivers)) + blockNumbers := make([]uint64, 0, len(dp.Receivers)) + + for i := range dp.Receivers { + receiver := dp.Receivers[i] + amount := amounts[i] + + g.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + // deposit tokens + depositTxn, err := createDepositTxn(types.Address(depositorAddr), types.StringToAddress(receiver), amount) + if err != nil { + return fmt.Errorf("failed to create tx input: %w", err) + } + + receipt, err = txRelayer.SendTransaction(depositTxn, depositorKey) + if err != nil { + return fmt.Errorf("receiver: %s, amount: %s, error: %w", receiver, amount, err) + } + + if receipt.Status == uint64(types.ReceiptFailed) { + return fmt.Errorf("receiver: %s, amount: %s", receiver, amount) + } + + var exitEventID *big.Int + + if dp.ChildChainMintable { + if exitEventID, err = common.ExtractExitEventID(receipt); err != nil { + return fmt.Errorf("failed to extract exit event: %w", err) + } + } + + // populate child token address if a token is mapped alongside with deposit + childToken, err := common.ExtractChildTokenAddr(receipt, dp.ChildChainMintable) + if err != nil { + return fmt.Errorf("failed to extract child token address: %w", err) + } + + // send aggregated data to channel if everything went ok + bridgeTxCh <- bridgeTxData{ + blockNumber: receipt.BlockNumber, + exitEventID: exitEventID, + childTokenAddr: childToken, + } + + return nil + } + }) + } + + if err = g.Wait(); err != nil { + outputter.SetError(fmt.Errorf("sending deposit transactions failed: %w", err)) + + return + } + + close(bridgeTxCh) + + var childToken *types.Address + + for x := range bridgeTxCh { + if x.exitEventID != nil { + exitEventIDs = append(exitEventIDs, x.exitEventID) + } + + blockNumbers = append(blockNumbers, x.blockNumber) + + if x.childTokenAddr != nil { + childToken = x.childTokenAddr + } + } + + outputter.SetCommandResult( + &common.BridgeTxResult{ + Sender: depositorAddr.String(), + Receivers: dp.Receivers, + Amounts: dp.Amounts, + ExitEventIDs: exitEventIDs, + ChildTokenAddr: childToken, + BlockNumbers: blockNumbers, + Title: "DEPOSIT ERC 20", + }) +} + +// createDepositTxn encodes parameters for deposit function on rootchain predicate contract +func createDepositTxn(sender, receiver types.Address, amount *big.Int) (*ethgo.Transaction, error) { + depositToFn := &contractsapi.DepositToRootERC20PredicateFn{ + RootToken: types.StringToAddress(dp.TokenAddr), + Receiver: receiver, + Amount: amount, + } + + input, err := depositToFn.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(types.StringToAddress(dp.PredicateAddr)) + + return ðgo.Transaction{ + From: ethgo.Address(sender), + To: &addr, + Input: input, + }, nil +} diff --git a/command/bridge/deposit/erc721/deposit_erc721.go b/command/bridge/deposit/erc721/deposit_erc721.go new file mode 100644 index 0000000000..0ba42f487c --- /dev/null +++ b/command/bridge/deposit/erc721/deposit_erc721.go @@ -0,0 +1,280 @@ +package deposit + +import ( + "fmt" + "math/big" + "strings" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/bridge/common" + "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" +) + +type depositERC721Params struct { + *common.ERC721BridgeParams + minterKey string +} + +var ( + dp *depositERC721Params = &depositERC721Params{ERC721BridgeParams: common.NewERC721BridgeParams()} +) + +func GetCommand() *cobra.Command { + depositCmd := &cobra.Command{ + Use: "deposit-erc721", + Short: "Deposits ERC721 tokens from the origin to the destination chain", + PreRunE: preRunCommand, + Run: runCommand, + } + + dp.RegisterCommonFlags(depositCmd) + + depositCmd.Flags().StringSliceVar( + &dp.TokenIDs, + common.TokenIDsFlag, + nil, + "token ids that are sent to the receivers accounts", + ) + + depositCmd.Flags().StringVar( + &dp.TokenAddr, + common.RootTokenFlag, + "", + "root ERC 721 token address", + ) + + depositCmd.Flags().StringVar( + &dp.PredicateAddr, + common.RootPredicateFlag, + "", + "root ERC 721 token predicate address", + ) + + depositCmd.Flags().StringVar( + &dp.minterKey, + common.MinterKeyFlag, + "", + common.MinterKeyFlagDesc, + ) + + _ = depositCmd.MarkFlagRequired(common.ReceiversFlag) + _ = depositCmd.MarkFlagRequired(common.TokenIDsFlag) + _ = depositCmd.MarkFlagRequired(common.RootTokenFlag) + _ = depositCmd.MarkFlagRequired(common.RootPredicateFlag) + + return depositCmd +} + +func preRunCommand(_ *cobra.Command, _ []string) error { + return dp.Validate() +} + +func runCommand(cmd *cobra.Command, _ []string) { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + depositorKey, err := helper.DecodePrivateKey(dp.SenderKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize depositor private key: %w", err)) + } + + depositorAddr := depositorKey.Address() + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(dp.JSONRPCAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize tx relayer: %w", err)) + + return + } + + receivers := make([]ethgo.Address, len(dp.Receivers)) + tokenIDs := make([]*big.Int, len(dp.Receivers)) + + for i, tokenIDRaw := range dp.TokenIDs { + tokenIDRaw := tokenIDRaw + + tokenID, err := types.ParseUint256orHex(&tokenIDRaw) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode provided token id %s: %w", tokenIDRaw, err)) + + return + } + + receivers[i] = ethgo.Address(types.StringToAddress(dp.Receivers[i])) + tokenIDs[i] = tokenID + } + + if dp.minterKey != "" { + minterKey, err := helper.DecodePrivateKey(dp.minterKey) + if err != nil { + outputter.SetError(fmt.Errorf("invalid minter key provided: %w", err)) + + return + } + + for i := 0; i < len(tokenIDs); i++ { + mintTxn, err := createMintTxn(types.Address(depositorAddr), types.Address(depositorAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("mint transaction creation failed: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(mintTxn, minterKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send mint transaction to depositor %s", depositorAddr)) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to mint tokens to depositor %s", depositorAddr)) + + return + } + } + } + + approveTxn, err := createApproveERC721PredicateTxn(types.StringToAddress(dp.PredicateAddr), + types.StringToAddress(dp.TokenAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("failed to approve predicate: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(approveTxn, depositorKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send root erc 721 approve transaction")) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to approve root erc 721 predicate")) + + return + } + + // deposit tokens + depositTxn, err := createDepositTxn(depositorAddr, receivers, tokenIDs) + if err != nil { + outputter.SetError(fmt.Errorf("failed to create tx input: %w", err)) + + return + } + + receipt, err = txRelayer.SendTransaction(depositTxn, depositorKey) + if err != nil { + outputter.SetError(fmt.Errorf("sending deposit transactions failed (receivers: %s, tokenIDs: %s): %w", + strings.Join(dp.Receivers, ", "), strings.Join(dp.TokenIDs, ", "), err)) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("sending deposit transactions failed (receivers: %s, tokenIDs: %s)", + strings.Join(dp.Receivers, ", "), strings.Join(dp.TokenIDs, ", "))) + + return + } + + res := &common.BridgeTxResult{ + Sender: depositorAddr.String(), + Receivers: dp.Receivers, + TokenIDs: dp.TokenIDs, + BlockNumbers: []uint64{receipt.BlockNumber}, + Title: "DEPOSIT ERC 721", + } + + if dp.ChildChainMintable { + exitEventID, err := common.ExtractExitEventID(receipt) + if err != nil { + outputter.SetError(fmt.Errorf("failed to extract exit event: %w", err)) + + return + } + + res.ExitEventIDs = []*big.Int{exitEventID} + } + + // populate child token address if a token is mapped alongside with deposit + childToken, err := common.ExtractChildTokenAddr(receipt, dp.ChildChainMintable) + if err != nil { + outputter.SetError(fmt.Errorf("failed to extract child token address: %w", err)) + + return + } + + res.ChildTokenAddr = childToken + + outputter.SetCommandResult(res) +} + +// createDepositTxn encodes parameters for deposit fnction on rootchain predicate contract +func createDepositTxn(sender ethgo.Address, + receivers []ethgo.Address, tokenIDs []*big.Int) (*ethgo.Transaction, error) { + depositToRoot := &contractsapi.DepositBatchRootERC721PredicateFn{ + RootToken: types.StringToAddress(dp.TokenAddr), + Receivers: receivers, + TokenIDs: tokenIDs, + } + + input, err := depositToRoot.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(types.StringToAddress(dp.PredicateAddr)) + + return ðgo.Transaction{ + From: sender, + To: &addr, + Input: input, + }, nil +} + +// createMintTxn encodes parameters for mint function on rootchain token contract +func createMintTxn(sender, receiver types.Address) (*ethgo.Transaction, error) { + mintFn := &contractsapi.MintRootERC721Fn{ + To: receiver, + } + + input, err := mintFn.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(types.StringToAddress(dp.TokenAddr)) + + return ðgo.Transaction{ + From: ethgo.Address(sender), + To: &addr, + Input: input, + }, nil +} + +// createApproveERC721PredicateTxn sends approve transaction +func createApproveERC721PredicateTxn(rootERC721Predicate, rootERC721Token types.Address) (*ethgo.Transaction, error) { + approveFnParams := &contractsapi.SetApprovalForAllRootERC721Fn{ + Operator: rootERC721Predicate, + Approved: true, + } + + input, err := approveFnParams.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode parameters for RootERC721.approve. error: %w", err) + } + + addr := ethgo.Address(rootERC721Token) + + return ðgo.Transaction{ + To: &addr, + Input: input, + }, nil +} diff --git a/command/bridge/exit/exit.go b/command/bridge/exit/exit.go index 6b5b0fe659..dc74eef0d9 100644 --- a/command/bridge/exit/exit.go +++ b/command/bridge/exit/exit.go @@ -79,7 +79,7 @@ func GetCommand() *cobra.Command { exitCmd.Flags().StringVar( &ep.rootJSONRPCAddr, rootJSONRPCFlag, - "http://127.0.0.1:8545", + txrelayer.DefaultRPCAddress, "the JSON RPC root chain endpoint", ) @@ -107,7 +107,7 @@ func run(cmd *cobra.Command, _ []string) { outputter := command.InitializeOutputter(cmd) defer outputter.WriteOutput() - senderKey, err := helper.GetRootchainPrivateKey(ep.senderKey) + senderKey, err := helper.DecodePrivateKey(ep.senderKey) if err != nil { outputter.SetError(fmt.Errorf("failed to create wallet from private key: %w", err)) @@ -218,6 +218,7 @@ func createExitTxn(sender ethgo.Address, proof types.Proof) (*ethgo.Transaction, From: sender, To: &exitHelperAddr, Input: input, + Gas: txrelayer.DefaultGasLimit, } return txn, exitEvent, err diff --git a/command/bridge/withdraw/erc1155/withdraw_erc1155.go b/command/bridge/withdraw/erc1155/withdraw_erc1155.go new file mode 100644 index 0000000000..ab1ca84d38 --- /dev/null +++ b/command/bridge/withdraw/erc1155/withdraw_erc1155.go @@ -0,0 +1,193 @@ +package erc1155 + +import ( + "encoding/hex" + "fmt" + "math/big" + "strings" + + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/wallet" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/bridge/common" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" +) + +var ( + wp *common.ERC1155BridgeParams = common.NewERC1155BridgeParams() +) + +// GetCommand returns the bridge withdraw command +func GetCommand() *cobra.Command { + withdrawCmd := &cobra.Command{ + Use: "withdraw-erc1155", + Short: "Withdraws ERC 1155 tokens from the destination to the origin chain", + PreRunE: preRunCommand, + Run: runCommand, + } + + wp.RegisterCommonFlags(withdrawCmd) + + withdrawCmd.Flags().StringSliceVar( + &wp.Amounts, + common.AmountsFlag, + nil, + "amounts that are sent to the receivers accounts", + ) + + withdrawCmd.Flags().StringSliceVar( + &wp.TokenIDs, + common.TokenIDsFlag, + nil, + "token ids that are sent to the receivers accounts", + ) + + withdrawCmd.Flags().StringVar( + &wp.PredicateAddr, + common.ChildPredicateFlag, + contracts.ChildERC1155PredicateContract.String(), + "ERC 1155 child chain predicate address", + ) + + withdrawCmd.Flags().StringVar( + &wp.TokenAddr, + common.ChildTokenFlag, + contracts.ChildERC1155Contract.String(), + "ERC 1155 child chain token address", + ) + + _ = withdrawCmd.MarkFlagRequired(common.ReceiversFlag) + _ = withdrawCmd.MarkFlagRequired(common.AmountsFlag) + _ = withdrawCmd.MarkFlagRequired(common.TokenIDsFlag) + + return withdrawCmd +} + +func preRunCommand(_ *cobra.Command, _ []string) error { + return wp.Validate() +} + +func runCommand(cmd *cobra.Command, _ []string) { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + senderKeyRaw, err := hex.DecodeString(wp.SenderKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode sender private key: %w", err)) + + return + } + + senderAccount, err := wallet.NewWalletFromPrivKey(senderKeyRaw) + if err != nil { + outputter.SetError(err) + + return + } + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(wp.JSONRPCAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("could not create child chain tx relayer: %w", err)) + + return + } + + receivers := make([]ethgo.Address, len(wp.Receivers)) + amounts := make([]*big.Int, len(wp.Receivers)) + TokenIDs := make([]*big.Int, len(wp.Receivers)) + + for i, receiverRaw := range wp.Receivers { + receivers[i] = ethgo.Address(types.StringToAddress(receiverRaw)) + amountRaw := wp.Amounts[i] + tokenIDRaw := wp.TokenIDs[i] + + amount, err := types.ParseUint256orHex(&amountRaw) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode provided amount %s: %w", amountRaw, err)) + + return + } + + tokenID, err := types.ParseUint256orHex(&tokenIDRaw) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode provided token id %s: %w", amountRaw, err)) + + return + } + + amounts[i] = amount + TokenIDs[i] = tokenID + } + + // withdraw tokens transaction + txn, err := createWithdrawTxn(receivers, amounts, TokenIDs) + if err != nil { + outputter.SetError(fmt.Errorf("failed to create tx input: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(txn, senderAccount) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send withdrawal transaction (receivers: %s, amounts: %s, token ids: %s): %w", + strings.Join(wp.Receivers, ", "), strings.Join(wp.Amounts, ", "), strings.Join(wp.TokenIDs, ", "), err)) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to execute withdrawal transaction (receivers: %s, amounts: %s, token ids: %s)", + strings.Join(wp.Receivers, ", "), strings.Join(wp.Amounts, ", "), strings.Join(wp.TokenIDs, ", "))) + + return + } + + res := &common.BridgeTxResult{ + Sender: senderAccount.Address().String(), + Receivers: wp.Receivers, + Amounts: wp.Amounts, + TokenIDs: wp.TokenIDs, + BlockNumbers: []uint64{receipt.BlockNumber}, + Title: "WITHDRAW ERC 1155", + } + + if !wp.ChildChainMintable { + exitEventID, err := common.ExtractExitEventID(receipt) + if err != nil { + outputter.SetError(fmt.Errorf("failed to extract exit event: %w", err)) + + return + } + + res.ExitEventIDs = []*big.Int{exitEventID} + } + + outputter.SetCommandResult(res) +} + +// createWithdrawTxn encodes parameters for withdraw function on child chain predicate contract +func createWithdrawTxn(receivers []ethgo.Address, amounts, TokenIDs []*big.Int) (*ethgo.Transaction, error) { + withdrawFn := &contractsapi.WithdrawBatchChildERC1155PredicateFn{ + ChildToken: types.StringToAddress(wp.TokenAddr), + Receivers: receivers, + Amounts: amounts, + TokenIDs: TokenIDs, + } + + input, err := withdrawFn.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(types.StringToAddress(wp.PredicateAddr)) + + return ðgo.Transaction{ + To: &addr, + Input: input, + }, nil +} diff --git a/command/bridge/withdraw/erc20/withdraw_erc20.go b/command/bridge/withdraw/erc20/withdraw_erc20.go new file mode 100644 index 0000000000..422f9365a8 --- /dev/null +++ b/command/bridge/withdraw/erc20/withdraw_erc20.go @@ -0,0 +1,171 @@ +package erc20 + +import ( + "encoding/hex" + "fmt" + "math/big" + + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/wallet" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/bridge/common" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" +) + +var ( + wp *common.ERC20BridgeParams = common.NewERC20BridgeParams() +) + +// GetCommand returns the bridge withdraw command +func GetCommand() *cobra.Command { + withdrawCmd := &cobra.Command{ + Use: "withdraw-erc20", + Short: "Withdraws ERC 20 tokens from the destination to the origin chain", + PreRunE: preRunCommand, + Run: runCommand, + } + + wp.RegisterCommonFlags(withdrawCmd) + + withdrawCmd.Flags().StringSliceVar( + &wp.Amounts, + common.AmountsFlag, + nil, + "amounts to send to receiving accounts", + ) + + withdrawCmd.Flags().StringVar( + &wp.PredicateAddr, + common.ChildPredicateFlag, + contracts.ChildERC20PredicateContract.String(), + "child ERC 20 predicate address", + ) + + withdrawCmd.Flags().StringVar( + &wp.TokenAddr, + common.ChildTokenFlag, + contracts.NativeERC20TokenContract.String(), + "child ERC 20 token address", + ) + + _ = withdrawCmd.MarkFlagRequired(common.ReceiversFlag) + _ = withdrawCmd.MarkFlagRequired(common.AmountsFlag) + + return withdrawCmd +} + +func preRunCommand(_ *cobra.Command, _ []string) error { + return wp.Validate() +} + +func runCommand(cmd *cobra.Command, _ []string) { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + senderKeyRaw, err := hex.DecodeString(wp.SenderKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode sender private key: %w", err)) + + return + } + + senderAccount, err := wallet.NewWalletFromPrivKey(senderKeyRaw) + if err != nil { + outputter.SetError(err) + + return + } + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(wp.JSONRPCAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("could not create destination chain tx relayer: %w", err)) + + return + } + + exitEventIDs := make([]*big.Int, 0, len(wp.Receivers)) + blockNumbers := make([]uint64, len(wp.Receivers)) + + for i := range wp.Receivers { + receiver := wp.Receivers[i] + amount := wp.Amounts[i] + + amountBig, err := types.ParseUint256orHex(&amount) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode provided amount %s: %w", amount, err)) + + return + } + + // withdraw tokens transaction + txn, err := createWithdrawTxn(types.StringToAddress(receiver), amountBig) + if err != nil { + outputter.SetError(fmt.Errorf("failed to create tx input: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(txn, senderAccount) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send withdraw transaction (receiver: %s, amount: %s). error: %w)", + receiver, amount, err)) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to execute withdrawal (receiver: %s, amount: %s)", receiver, amount)) + + return + } + + if !wp.ChildChainMintable { + exitEventID, err := common.ExtractExitEventID(receipt) + if err != nil { + outputter.SetError(fmt.Errorf("failed to extract exit event: %w", err)) + + return + } + + exitEventIDs = append(exitEventIDs, exitEventID) + } + + blockNumbers[i] = receipt.BlockNumber + } + + outputter.SetCommandResult( + &common.BridgeTxResult{ + Sender: senderAccount.Address().String(), + Receivers: wp.Receivers, + Amounts: wp.Amounts, + ExitEventIDs: exitEventIDs, + BlockNumbers: blockNumbers, + Title: "WITHDRAW ERC 20", + }) +} + +// createWithdrawTxn encodes parameters for withdraw function on destination predicate contract +func createWithdrawTxn(receiver types.Address, amount *big.Int) (*ethgo.Transaction, error) { + withdrawToFn := &contractsapi.WithdrawToChildERC20PredicateFn{ + ChildToken: types.StringToAddress(wp.TokenAddr), + Receiver: receiver, + Amount: amount, + } + + input, err := withdrawToFn.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(types.StringToAddress(wp.PredicateAddr)) + + return ðgo.Transaction{ + To: &addr, + Input: input, + }, nil +} diff --git a/command/bridge/withdraw/erc721/withdraw_erc721.go b/command/bridge/withdraw/erc721/withdraw_erc721.go new file mode 100644 index 0000000000..1688b2aeab --- /dev/null +++ b/command/bridge/withdraw/erc721/withdraw_erc721.go @@ -0,0 +1,171 @@ +package withdraw + +import ( + "encoding/hex" + "fmt" + "math/big" + "strings" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/bridge/common" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/wallet" +) + +var ( + wp *common.ERC721BridgeParams = common.NewERC721BridgeParams() +) + +func GetCommand() *cobra.Command { + withdrawCmd := &cobra.Command{ + Use: "withdraw-erc721", + Short: "Withdraws ERC 721 tokens from the destination to the origin chain", + PreRunE: preRun, + Run: run, + } + + wp.RegisterCommonFlags(withdrawCmd) + + withdrawCmd.Flags().StringSliceVar( + &wp.TokenIDs, + common.TokenIDsFlag, + nil, + "tokens ids to send to receiving accounts", + ) + + withdrawCmd.Flags().StringVar( + &wp.PredicateAddr, + common.ChildPredicateFlag, + contracts.ChildERC721PredicateContract.String(), + "ERC 721 child chain predicate address", + ) + + withdrawCmd.Flags().StringVar( + &wp.TokenAddr, + common.ChildTokenFlag, + contracts.ChildERC721Contract.String(), + "ERC 721 child chain token address", + ) + + _ = withdrawCmd.MarkFlagRequired(common.SenderKeyFlag) + _ = withdrawCmd.MarkFlagRequired(common.ReceiversFlag) + _ = withdrawCmd.MarkFlagRequired(common.TokenIDsFlag) + + return withdrawCmd +} + +func preRun(_ *cobra.Command, _ []string) error { + return wp.Validate() +} + +func run(cmd *cobra.Command, _ []string) { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + senderKeyRaw, err := hex.DecodeString(wp.SenderKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode sender private key: %w", err)) + + return + } + + senderAccount, err := wallet.NewWalletFromPrivKey(senderKeyRaw) + if err != nil { + outputter.SetError(err) + + return + } + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(wp.JSONRPCAddr)) + if err != nil { + outputter.SetError(fmt.Errorf("could not create child chain tx relayer: %w", err)) + + return + } + + receivers := make([]ethgo.Address, len(wp.Receivers)) + tokenIDs := make([]*big.Int, len(wp.Receivers)) + + for i, tokenIDRaw := range wp.TokenIDs { + tokenIDRaw := tokenIDRaw + + tokenID, err := types.ParseUint256orHex(&tokenIDRaw) + if err != nil { + outputter.SetError(fmt.Errorf("failed to decode provided token id %s: %w", tokenIDRaw, err)) + + return + } + + receivers[i] = ethgo.Address(types.StringToAddress(wp.Receivers[i])) + tokenIDs[i] = tokenID + } + + txn, err := createWithdrawTxn(receivers, tokenIDs) + if err != nil { + outputter.SetError(fmt.Errorf("failed to create tx input: %w", err)) + + return + } + + receipt, err := txRelayer.SendTransaction(txn, senderAccount) + if err != nil { + outputter.SetError(fmt.Errorf("failed to send withdrawal transaction (receivers: %s, token ids: %s): %w", + strings.Join(wp.Receivers, ", "), strings.Join(wp.TokenIDs, ", "), err)) + + return + } + + if receipt.Status == uint64(types.ReceiptFailed) { + outputter.SetError(fmt.Errorf("failed to execute withdrawal transaction (receivers: %s, token ids: %s)", + strings.Join(wp.Receivers, ", "), strings.Join(wp.TokenIDs, ", "))) + + return + } + + res := &common.BridgeTxResult{ + Sender: senderAccount.Address().String(), + Receivers: wp.Receivers, + TokenIDs: wp.TokenIDs, + BlockNumbers: []uint64{receipt.BlockNumber}, + Title: "WITHDRAW ERC 721", + } + + if !wp.ChildChainMintable { + exitEventID, err := common.ExtractExitEventID(receipt) + if err != nil { + outputter.SetError(fmt.Errorf("failed to extract exit event: %w", err)) + + return + } + + res.ExitEventIDs = []*big.Int{exitEventID} + } + + outputter.SetCommandResult(res) +} + +// createWithdrawTxn encodes parameters for withdraw function on child chain predicate contract +func createWithdrawTxn(receivers []ethgo.Address, tokenIDs []*big.Int) (*ethgo.Transaction, error) { + withdrawToFn := &contractsapi.WithdrawBatchChildERC721PredicateFn{ + ChildToken: types.StringToAddress(wp.TokenAddr), + Receivers: receivers, + TokenIDs: tokenIDs, + } + + input, err := withdrawToFn.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(types.StringToAddress(wp.PredicateAddr)) + + return ðgo.Transaction{ + To: &addr, + Input: input, + }, nil +} diff --git a/command/bridge/withdraw/withdraw_erc20.go b/command/bridge/withdraw/withdraw_erc20.go deleted file mode 100644 index 6e00c63dbb..0000000000 --- a/command/bridge/withdraw/withdraw_erc20.go +++ /dev/null @@ -1,253 +0,0 @@ -package withdraw - -import ( - "bytes" - "encoding/hex" - "errors" - "fmt" - "math/big" - "strconv" - "strings" - - "github.com/spf13/cobra" - "github.com/umbracle/ethgo" - "github.com/umbracle/ethgo/wallet" - - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/command/bridge/common" - cmdHelper "github.com/0xPolygon/polygon-edge/command/helper" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/contracts" - "github.com/0xPolygon/polygon-edge/txrelayer" - "github.com/0xPolygon/polygon-edge/types" -) - -const ( - jsonRPCFlag = "json-rpc" - childPredicateFlag = "child-predicate" - childTokenFlag = "child-token" -) - -type withdrawParams struct { - *common.ERC20BridgeParams - childPredicateAddr string - childTokenAddr string - jsonRPCAddress string -} - -var ( - wp *withdrawParams = &withdrawParams{ - ERC20BridgeParams: &common.ERC20BridgeParams{}, - } -) - -// GetCommand returns the bridge withdraw command -func GetCommand() *cobra.Command { - withdrawCmd := &cobra.Command{ - Use: "withdraw-erc20", - Short: "Withdraws tokens from the child chain to the root chain", - PreRunE: preRun, - Run: run, - } - - withdrawCmd.Flags().StringVar( - &wp.SenderKey, - common.SenderKeyFlag, - "", - "withdraw transaction sender hex-encoded private key", - ) - - withdrawCmd.Flags().StringSliceVar( - &wp.Receivers, - common.ReceiversFlag, - nil, - "receiving accounts addresses on the root chain", - ) - - withdrawCmd.Flags().StringSliceVar( - &wp.Amounts, - common.AmountsFlag, - nil, - "amounts to send to receiving accounts", - ) - - withdrawCmd.Flags().StringVar( - &wp.childPredicateAddr, - childPredicateFlag, - contracts.ChildERC20PredicateContract.String(), - "ERC20 child chain predicate address", - ) - - withdrawCmd.Flags().StringVar( - &wp.childTokenAddr, - childTokenFlag, - contracts.NativeERC20TokenContract.String(), - "ERC20 child chain token address", - ) - - withdrawCmd.Flags().StringVar( - &wp.jsonRPCAddress, - jsonRPCFlag, - "http://127.0.0.1:9545", - "the JSON RPC child chain endpoint", - ) - - _ = withdrawCmd.MarkFlagRequired(common.ReceiversFlag) - _ = withdrawCmd.MarkFlagRequired(common.AmountsFlag) - - return withdrawCmd -} - -func preRun(cmd *cobra.Command, _ []string) error { - if err := wp.ValidateFlags(); err != nil { - return err - } - - return nil -} - -func run(cmd *cobra.Command, _ []string) { - outputter := command.InitializeOutputter(cmd) - defer outputter.WriteOutput() - - senderKeyRaw, err := hex.DecodeString(wp.SenderKey) - if err != nil { - outputter.SetError(fmt.Errorf("failed to decode sender private key: %w", err)) - - return - } - - senderAccount, err := wallet.NewWalletFromPrivKey(senderKeyRaw) - if err != nil { - outputter.SetError(err) - - return - } - - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(wp.jsonRPCAddress)) - if err != nil { - outputter.SetError(fmt.Errorf("could not create child chain tx relayer: %w", err)) - - return - } - - exitEventIDs := make([]string, len(wp.Receivers)) - blockNumbers := make([]string, len(wp.Receivers)) - - for i := range wp.Receivers { - receiver := wp.Receivers[i] - amount := wp.Amounts[i] - - amountBig, err := types.ParseUint256orHex(&amount) - if err != nil { - outputter.SetError(fmt.Errorf("failed to decode provided amount %s: %w", amount, err)) - - return - } - - // withdraw tokens transaction - txn, err := createWithdrawTxn(types.StringToAddress(receiver), amountBig) - if err != nil { - outputter.SetError(fmt.Errorf("failed to create tx input: %w", err)) - - return - } - - receipt, err := txRelayer.SendTransaction(txn, senderAccount) - if err != nil { - outputter.SetError(fmt.Errorf("receiver: %s, amount: %s, error: %w", receiver, amount, err)) - - return - } - - if receipt.Status == uint64(types.ReceiptFailed) { - outputter.SetError(fmt.Errorf("receiver: %s, amount: %s", receiver, amount)) - - return - } - - exitEventID, err := extractExitEventID(receipt) - if err != nil { - outputter.SetError(fmt.Errorf("failed to extract exit event: %w", err)) - - return - } - - exitEventIDs[i] = strconv.FormatUint(exitEventID.Uint64(), 10) - blockNumbers[i] = strconv.FormatUint(receipt.BlockNumber, 10) - } - - outputter.SetCommandResult( - &withdrawERC20Result{ - Sender: senderAccount.Address().String(), - Receivers: wp.Receivers, - Amounts: wp.Amounts, - ExitEventIDs: exitEventIDs, - BlockNumbers: blockNumbers, - }) -} - -// createWithdrawTxn encodes parameters for withdraw function on child chain predicate contract -func createWithdrawTxn(receiver types.Address, amount *big.Int) (*ethgo.Transaction, error) { - withdrawToFn := &contractsapi.WithdrawToChildERC20PredicateFn{ - ChildToken: types.StringToAddress(wp.childTokenAddr), - Receiver: receiver, - Amount: amount, - } - - input, err := withdrawToFn.EncodeAbi() - if err != nil { - return nil, fmt.Errorf("failed to encode provided parameters: %w", err) - } - - addr := ethgo.Address(types.StringToAddress(wp.childPredicateAddr)) - - return ðgo.Transaction{ - To: &addr, - Input: input, - }, nil -} - -// extractExitEventID tries to extract exit event id from provided receipt -func extractExitEventID(receipt *ethgo.Receipt) (*big.Int, error) { - var exitEvent contractsapi.L2StateSyncedEvent - for _, log := range receipt.Logs { - doesMatch, err := exitEvent.ParseLog(log) - if !doesMatch { - continue - } - - if err != nil { - return nil, err - } - - return exitEvent.ID, nil - } - - return nil, errors.New("failed to find exit event log") -} - -type withdrawERC20Result struct { - Sender string `json:"sender"` - Receivers []string `json:"receivers"` - Amounts []string `json:"amounts"` - ExitEventIDs []string `json:"exitEventIDs"` - BlockNumbers []string `json:"blockNumbers"` -} - -func (r *withdrawERC20Result) GetOutput() string { - var buffer bytes.Buffer - - vals := make([]string, 0, 5) - vals = append(vals, fmt.Sprintf("Sender|%s", r.Sender)) - vals = append(vals, fmt.Sprintf("Receivers|%s", strings.Join(r.Receivers, ", "))) - vals = append(vals, fmt.Sprintf("Amounts|%s", strings.Join(r.Amounts, ", "))) - vals = append(vals, fmt.Sprintf("Exit Event IDs|%s", strings.Join(r.ExitEventIDs, ", "))) - vals = append(vals, fmt.Sprintf("Inclusion Block Numbers|%s", strings.Join(r.BlockNumbers, ", "))) - - buffer.WriteString("\n[WITHDRAW ERC20]\n") - buffer.WriteString(cmdHelper.FormatKV(vals)) - buffer.WriteString("\n") - - return buffer.String() -} diff --git a/command/default.go b/command/default.go index 6ba242fa25..ab6af9d7d4 100644 --- a/command/default.go +++ b/command/default.go @@ -1,22 +1,26 @@ package command import ( - "github.com/0xPolygon/polygon-edge/server" "github.com/umbracle/ethgo" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/server" ) const ( - DefaultGenesisFileName = "genesis.json" - DefaultChainName = "polygon-edge" - DefaultChainID = 100 - DefaultConsensus = server.PolyBFTConsensus - DefaultGenesisGasUsed = 458752 // 0x70000 - DefaultGenesisGasLimit = 5242880 // 0x500000 + DefaultGenesisFileName = "genesis.json" + DefaultChainName = "polygon-edge" + DefaultChainID = 100 + DefaultConsensus = server.PolyBFTConsensus + DefaultGenesisGasUsed = 458752 // 0x70000 + DefaultGenesisGasLimit = 5242880 // 0x500000 + DefaultGenesisBaseFeeEM = chain.GenesisBaseFeeEM ) var ( DefaultStake = ethgo.Ether(1e6) DefaultPremineBalance = ethgo.Ether(1e6) + DefaultGenesisBaseFee = chain.GenesisBaseFee ) const ( diff --git a/command/genesis/genesis.go b/command/genesis/genesis.go index db737161d1..bf455956db 100644 --- a/command/genesis/genesis.go +++ b/command/genesis/genesis.go @@ -16,12 +16,10 @@ func GetCommand() *cobra.Command { genesisCmd := &cobra.Command{ Use: "genesis", Short: "Generates the genesis configuration file with the passed in parameters", - PreRunE: runPreRun, + PreRunE: preRunCommand, Run: runCommand, } - helper.RegisterGRPCAddressFlag(genesisCmd) - setFlags(genesisCmd) setLegacyFlags(genesisCmd) @@ -45,7 +43,7 @@ func setFlags(cmd *cobra.Command) { ¶ms.chainID, chainIDFlag, command.DefaultChainID, - "the ID of the chain", + "the ID of the chain (only used for IBFT consensus)", ) cmd.Flags().StringVar( @@ -60,7 +58,7 @@ func setFlags(cmd *cobra.Command) { premineFlag, []string{}, fmt.Sprintf( - "the premined accounts and balances (format:
:). Default premined balance: %d", + "the premined accounts and balances (format:
[:]). Default premined balance: %d", command.DefaultPremineBalance, ), ) @@ -72,6 +70,13 @@ func setFlags(cmd *cobra.Command) { "the maximum amount of gas used by all transactions in a block", ) + cmd.Flags().StringVar( + ¶ms.burnContract, + burnContractFlag, + "", + "the burn contract block and address (format: :
[:])", + ) + cmd.Flags().StringArrayVar( ¶ms.bootnodes, command.BootnodeFlag, @@ -150,19 +155,29 @@ func setFlags(cmd *cobra.Command) { // PolyBFT { cmd.Flags().StringVar( - ¶ms.manifestPath, - manifestPathFlag, - defaultManifestPath, - "the manifest file path, which contains genesis metadata", + ¶ms.validatorsPath, + validatorsPathFlag, + "./", + "root path containing polybft validators secrets", ) - cmd.Flags().IntVar( - ¶ms.validatorSetSize, - validatorSetSizeFlag, - defaultValidatorSetSize, - "the total number of validators", + cmd.Flags().StringVar( + ¶ms.validatorsPrefixPath, + validatorsPrefixFlag, + defaultValidatorPrefixPath, + "folder prefix names for polybft validators secrets", + ) + + cmd.Flags().StringArrayVar( + ¶ms.validators, + validatorsFlag, + []string{}, + "validators defined by user (format: ::)", ) + cmd.MarkFlagsMutuallyExclusive(validatorsFlag, validatorsPathFlag) + cmd.MarkFlagsMutuallyExclusive(validatorsFlag, validatorsPrefixFlag) + cmd.Flags().Uint64Var( ¶ms.sprintSize, sprintSizeFlag, @@ -177,13 +192,6 @@ func setFlags(cmd *cobra.Command) { "the predefined period which determines block creation frequency", ) - cmd.Flags().StringVar( - ¶ms.bridgeJSONRPCAddr, - bridgeFlag, - "", - "the rootchain JSON RPC endpoint", - ) - cmd.Flags().Uint64Var( ¶ms.epochReward, epochRewardFlag, @@ -191,15 +199,7 @@ func setFlags(cmd *cobra.Command) { "reward size for block sealing", ) - cmd.Flags().StringArrayVar( - ¶ms.eventTrackerStartBlocks, - trackerStartBlocksFlag, - []string{}, - "event tracker starting block configuration, which is specified per contract address "+ - "(format: :)", - ) - - //Regenesis flag that allows to start from non-empty database + // regenesis flag that allows to start from non-empty database cmd.Flags().StringVar( ¶ms.initialStateRoot, trieRootFlag, @@ -207,29 +207,121 @@ func setFlags(cmd *cobra.Command) { "trie root from the corresponding triedb", ) - cmd.Flags().BoolVar( - ¶ms.mintableNativeToken, - mintableTokenFlag, - false, - "flag indicate whether mintable or non-mintable native ERC20 token is deployed", + cmd.Flags().StringVar( + ¶ms.nativeTokenConfigRaw, + nativeTokenConfigFlag, + "", + "native token configuration, provided in the following format: "+ + "", + ) + + cmd.Flags().StringVar( + ¶ms.rewardTokenCode, + rewardTokenCodeFlag, + "", + "hex encoded reward token byte code", + ) + + cmd.Flags().StringVar( + ¶ms.rewardWallet, + rewardWalletFlag, + "", + "configuration of reward wallet in format ", + ) + + cmd.Flags().Uint64Var( + ¶ms.blockTimeDrift, + blockTimeDriftFlag, + defaultBlockTimeDrift, + "configuration for block time drift value (in seconds)", ) } - // Allow list + // Access Control Lists { cmd.Flags().StringArrayVar( ¶ms.contractDeployerAllowListAdmin, - contractDeployedAllowListAdminFlag, + contractDeployerAllowListAdminFlag, []string{}, "list of addresses to use as admin accounts in the contract deployer allow list", ) cmd.Flags().StringArrayVar( ¶ms.contractDeployerAllowListEnabled, - contractDeployedAllowListEnabledFlag, + contractDeployerAllowListEnabledFlag, []string{}, "list of addresses to enable by default in the contract deployer allow list", ) + + cmd.Flags().StringArrayVar( + ¶ms.contractDeployerBlockListAdmin, + contractDeployerBlockListAdminFlag, + []string{}, + "list of addresses to use as admin accounts in the contract deployer block list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.contractDeployerBlockListEnabled, + contractDeployerBlockListEnabledFlag, + []string{}, + "list of addresses to enable by default in the contract deployer block list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.transactionsAllowListAdmin, + transactionsAllowListAdminFlag, + []string{}, + "list of addresses to use as admin accounts in the transactions allow list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.transactionsAllowListEnabled, + transactionsAllowListEnabledFlag, + []string{}, + "list of addresses to enable by default in the transactions allow list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.transactionsBlockListAdmin, + transactionsBlockListAdminFlag, + []string{}, + "list of addresses to use as admin accounts in the transactions block list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.transactionsBlockListEnabled, + transactionsBlockListEnabledFlag, + []string{}, + "list of addresses to enable by default in the transactions block list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.bridgeAllowListAdmin, + bridgeAllowListAdminFlag, + []string{}, + "list of addresses to use as admin accounts in the bridge allow list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.bridgeAllowListEnabled, + bridgeAllowListEnabledFlag, + []string{}, + "list of addresses to enable by default in the bridge allow list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.bridgeBlockListAdmin, + bridgeBlockListAdminFlag, + []string{}, + "list of addresses to use as admin accounts in the bridge block list", + ) + + cmd.Flags().StringArrayVar( + ¶ms.bridgeBlockListEnabled, + bridgeBlockListEnabledFlag, + []string{}, + "list of addresses to enable by default in the bridge block list", + ) } } @@ -241,13 +333,13 @@ func setLegacyFlags(cmd *cobra.Command) { ¶ms.chainID, chainIDFlagLEGACY, command.DefaultChainID, - "the ID of the chain (not-applicable for Polybft consensus protocol as chain id is defined in manifest.json)", + "the ID of the chain", ) _ = cmd.Flags().MarkHidden(chainIDFlagLEGACY) } -func runPreRun(cmd *cobra.Command, _ []string) error { +func preRunCommand(cmd *cobra.Command, _ []string) error { if err := params.validateFlags(); err != nil { return err } diff --git a/command/genesis/params.go b/command/genesis/params.go index 7ba94efa8b..3524a6712f 100644 --- a/command/genesis/params.go +++ b/command/genesis/params.go @@ -3,6 +3,11 @@ package genesis import ( "errors" "fmt" + "math" + "math/big" + "os" + "strconv" + "strings" "time" "github.com/0xPolygon/polygon-edge/chain" @@ -11,6 +16,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/ibft" "github.com/0xPolygon/polygon-edge/consensus/ibft/fork" "github.com/0xPolygon/polygon-edge/consensus/ibft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft" "github.com/0xPolygon/polygon-edge/contracts/staking" stakingHelper "github.com/0xPolygon/polygon-edge/helper/staking" "github.com/0xPolygon/polygon-edge/server" @@ -19,17 +25,25 @@ import ( ) const ( - dirFlag = "dir" - nameFlag = "name" - premineFlag = "premine" - chainIDFlag = "chain-id" - epochSizeFlag = "epoch-size" - epochRewardFlag = "epoch-reward" - blockGasLimitFlag = "block-gas-limit" - posFlag = "pos" - minValidatorCount = "min-validator-count" - maxValidatorCount = "max-validator-count" - mintableTokenFlag = "mintable-native-token" + dirFlag = "dir" + nameFlag = "name" + premineFlag = "premine" + chainIDFlag = "chain-id" + epochSizeFlag = "epoch-size" + epochRewardFlag = "epoch-reward" + blockGasLimitFlag = "block-gas-limit" + burnContractFlag = "burn-contract" + posFlag = "pos" + minValidatorCount = "min-validator-count" + maxValidatorCount = "max-validator-count" + nativeTokenConfigFlag = "native-token-config" + rewardTokenCodeFlag = "reward-token-code" + rewardWalletFlag = "reward-wallet" + + defaultNativeTokenName = "Polygon" + defaultNativeTokenSymbol = "MATIC" + defaultNativeTokenDecimals = uint8(18) + minNativeTokenParamsNumber = 4 ) // Legacy flags that need to be preserved for running clients @@ -45,6 +59,9 @@ var ( errValidatorsNotSpecified = errors.New("validator information not specified") errUnsupportedConsensus = errors.New("specified consensusRaw not supported") errInvalidEpochSize = errors.New("epoch size must be greater than 1") + errInvalidTokenParams = errors.New("native token params were not submitted in proper format " + + "()") + errRewardWalletAmountZero = errors.New("reward wallet amount can not be zero or negative") ) type genesisParams struct { @@ -64,6 +81,8 @@ type genesisParams struct { blockGasLimit uint64 isPos bool + burnContract string + minNumValidators uint64 maxNumValidators uint64 @@ -78,20 +97,36 @@ type genesisParams struct { genesisConfig *chain.Chain // PolyBFT - manifestPath string - validatorSetSize int - sprintSize uint64 - blockTime time.Duration - bridgeJSONRPCAddr string - epochReward uint64 - eventTrackerStartBlocks []string + validatorsPath string + validatorsPrefixPath string + validators []string + sprintSize uint64 + blockTime time.Duration + epochReward uint64 + blockTimeDrift uint64 initialStateRoot string - // allowlist + // access lists contractDeployerAllowListAdmin []string contractDeployerAllowListEnabled []string - mintableNativeToken bool + contractDeployerBlockListAdmin []string + contractDeployerBlockListEnabled []string + transactionsAllowListAdmin []string + transactionsAllowListEnabled []string + transactionsBlockListAdmin []string + transactionsBlockListEnabled []string + bridgeAllowListAdmin []string + bridgeAllowListEnabled []string + bridgeBlockListAdmin []string + bridgeBlockListEnabled []string + + nativeTokenConfigRaw string + nativeTokenConfig *polybft.TokenConfig + + // rewards + rewardTokenCode string + rewardWallet string } func (p *genesisParams) validateFlags() error { @@ -107,6 +142,20 @@ func (p *genesisParams) validateFlags() error { return errValidatorsNotSpecified } + if p.isPolyBFTConsensus() { + if err := p.extractNativeTokenMetadata(); err != nil { + return err + } + + if err := p.validateBurnContract(); err != nil { + return err + } + + if err := p.validateRewardWallet(); err != nil { + return err + } + } + // Check if the genesis file already exists if generateError := verifyGenesisExistence(p.genesisPath); generateError != nil { return errors.New(generateError.GetMessage()) @@ -120,12 +169,15 @@ func (p *genesisParams) validateFlags() error { return errInvalidEpochSize } - // Validate min and max validators number - if err := command.ValidateMinMaxValidatorsNumber(p.minNumValidators, p.maxNumValidators); err != nil { - return err + // Validate validatorsPath only if validators information were not provided via CLI flag + if len(p.validators) == 0 { + if _, err := os.Stat(p.validatorsPath); err != nil { + return fmt.Errorf("invalid validators path ('%s') provided. Error: %w", p.validatorsPath, err) + } } - return nil + // Validate min and max validators number + return command.ValidateMinMaxValidatorsNumber(p.minNumValidators, p.maxNumValidators) } func (p *genesisParams) isIBFTConsensus() bool { @@ -296,6 +348,7 @@ func (p *genesisParams) initIBFTEngineMap(ibftType fork.IBFTType) { string(server.IBFTConsensus): map[string]interface{}{ fork.KeyType: ibftType, fork.KeyValidatorType: p.ibftValidatorType, + fork.KeyBlockTime: p.blockTime, ibft.KeyEpochSize: p.epochSize, }, } @@ -317,6 +370,12 @@ func (p *genesisParams) generateGenesis() error { } func (p *genesisParams) initGenesisConfig() error { + // Disable london hardfork if burn contract address is not provided + enabledForks := chain.AllForksEnabled + if !p.isBurnContractEnabled() { + enabledForks.RemoveFork(chain.London) + } + chainConfig := &chain.Chain{ Name: p.name, Genesis: &chain.Genesis{ @@ -328,12 +387,27 @@ func (p *genesisParams) initGenesisConfig() error { }, Params: &chain.Params{ ChainID: int64(p.chainID), - Forks: chain.AllForksEnabled, + Forks: enabledForks, Engine: p.consensusEngineConfig, }, Bootnodes: p.bootnodes, } + // burn contract can be set only for non mintable native token + if p.isBurnContractEnabled() { + chainConfig.Genesis.BaseFee = command.DefaultGenesisBaseFee + chainConfig.Genesis.BaseFeeEM = command.DefaultGenesisBaseFeeEM + chainConfig.Params.BurnContract = make(map[uint64]types.Address, 1) + + burnContractInfo, err := parseBurnContractInfo(p.burnContract) + if err != nil { + return err + } + + chainConfig.Params.BurnContract[burnContractInfo.BlockNumber] = burnContractInfo.Address + chainConfig.Params.BurnContractDestinationAddress = burnContractInfo.DestinationAddress + } + // Predeploy staking smart contract if needed if p.shouldPredeployStakingSC() { stakingAccount, err := p.predeployStakingSC() @@ -345,13 +419,13 @@ func (p *genesisParams) initGenesisConfig() error { } for _, premineRaw := range p.premine { - premineInfo, err := ParsePremineInfo(premineRaw) + premineInfo, err := parsePremineInfo(premineRaw) if err != nil { return err } - chainConfig.Genesis.Alloc[premineInfo.Address] = &chain.GenesisAccount{ - Balance: premineInfo.Amount, + chainConfig.Genesis.Alloc[premineInfo.address] = &chain.GenesisAccount{ + Balance: premineInfo.amount, } } @@ -380,6 +454,122 @@ func (p *genesisParams) predeployStakingSC() (*chain.GenesisAccount, error) { return stakingAccount, nil } +// validateRewardWallet validates reward wallet flag +func (p *genesisParams) validateRewardWallet() error { + if p.rewardWallet == "" { + return errors.New("reward wallet address must be defined") + } + + if p.rewardWallet == types.AddressToString(types.ZeroAddress) { + return errors.New("reward wallet address must not be zero address") + } + + premineInfo, err := parsePremineInfo(p.rewardWallet) + if err != nil { + return err + } + + if premineInfo.amount.Cmp(big.NewInt(0)) < 1 { + return errRewardWalletAmountZero + } + + return nil +} + +// validateBurnContract validates burn contract. If native token is mintable, +// burn contract flag must not be set. If native token is non mintable only one burn contract +// can be set and the specified address will be used to predeploy default EIP1559 burn contract. +func (p *genesisParams) validateBurnContract() error { + if p.isBurnContractEnabled() { + burnContractInfo, err := parseBurnContractInfo(p.burnContract) + if err != nil { + return fmt.Errorf("invalid burn contract info provided: %w", err) + } + + if p.nativeTokenConfig.IsMintable { + if burnContractInfo.Address != types.ZeroAddress { + return errors.New("only zero address is allowed as burn destination for mintable native token") + } + } else { + if burnContractInfo.Address == types.ZeroAddress { + return errors.New("it is not allowed to deploy burn contract to 0x0 address") + } + } + } + + return nil +} + +// isBurnContractEnabled returns true in case burn contract info is provided +func (p *genesisParams) isBurnContractEnabled() bool { + return p.burnContract != "" +} + +// extractNativeTokenMetadata parses provided native token metadata (such as name, symbol and decimals count) +func (p *genesisParams) extractNativeTokenMetadata() error { + if p.nativeTokenConfigRaw == "" { + p.nativeTokenConfig = &polybft.TokenConfig{ + Name: defaultNativeTokenName, + Symbol: defaultNativeTokenSymbol, + Decimals: defaultNativeTokenDecimals, + IsMintable: false, + Owner: types.ZeroAddress, + } + + return nil + } + + params := strings.Split(p.nativeTokenConfigRaw, ":") + if len(params) < minNativeTokenParamsNumber { + return errInvalidTokenParams + } + + // name + name := strings.TrimSpace(params[0]) + if name == "" { + return errInvalidTokenParams + } + + // symbol + symbol := strings.TrimSpace(params[1]) + if symbol == "" { + return errInvalidTokenParams + } + + // decimals + decimals, err := strconv.ParseUint(strings.TrimSpace(params[2]), 10, 8) + if err != nil || decimals > math.MaxUint8 { + return errInvalidTokenParams + } + + // is mintable native token used + isMintable, err := strconv.ParseBool(strings.TrimSpace(params[3])) + if err != nil { + return errInvalidTokenParams + } + + // in case it is mintable native token, it is expected to have 5 parameters provided + if isMintable && len(params) != minNativeTokenParamsNumber+1 { + return errInvalidTokenParams + } + + // owner address + owner := types.ZeroAddress + if isMintable { + owner = types.StringToAddress(strings.TrimSpace(params[4])) + } + + p.nativeTokenConfig = &polybft.TokenConfig{ + Name: name, + Symbol: symbol, + Decimals: uint8(decimals), + IsMintable: isMintable, + Owner: owner, + } + + return nil +} + func (p *genesisParams) getResult() command.CommandResult { return &GenesisResult{ Message: fmt.Sprintf("\nGenesis written to %s\n", p.genesisPath), diff --git a/command/genesis/params_test.go b/command/genesis/params_test.go new file mode 100644 index 0000000000..601db39b03 --- /dev/null +++ b/command/genesis/params_test.go @@ -0,0 +1,118 @@ +package genesis + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/types" +) + +func Test_extractNativeTokenMetadata(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + rawConfig string + expectedCfg *polybft.TokenConfig + expectErr bool + }{ + { + name: "default token config", + rawConfig: "", + expectedCfg: &polybft.TokenConfig{ + Name: defaultNativeTokenName, + Symbol: defaultNativeTokenSymbol, + Decimals: defaultNativeTokenDecimals, + IsMintable: false, + Owner: types.ZeroAddress, + }, + expectErr: false, + }, + { + name: "not enough params provided", + rawConfig: "Test:TST:18", + expectErr: true, + }, + { + name: "empty name provided", + rawConfig: ":TST:18:false", + expectErr: true, + }, + { + name: "empty symbol provided", + rawConfig: "Test::18:false", + expectErr: true, + }, + { + name: "invalid decimals number provided", + rawConfig: "Test:TST:9999999999999999999999999999999999999999999999999999999999:false", + expectErr: true, + }, + { + name: "invalid mintable flag provided", + rawConfig: "Test:TST:18:bar", + expectErr: true, + }, + { + name: "mintable token not enough params provided", + rawConfig: "Test:TST:18:true", + expectErr: true, + }, + { + name: "non-mintable valid config", + rawConfig: "MyToken:MTK:9:false", + expectedCfg: &polybft.TokenConfig{ + Name: "MyToken", + Symbol: "MTK", + Decimals: 9, + IsMintable: false, + Owner: types.ZeroAddress, + }, + expectErr: false, + }, + { + name: "non-mintable token config, owner provided but ignored", + rawConfig: "MyToken:MTK:9:false:0x123456789", + expectedCfg: &polybft.TokenConfig{ + Name: "MyToken", + Symbol: "MTK", + Decimals: 9, + IsMintable: false, + Owner: types.ZeroAddress, + }, + expectErr: false, + }, + { + name: "mintable token valid config", + rawConfig: "MyMintToken:MMTK:9:true:0x123456789", + expectedCfg: &polybft.TokenConfig{ + Name: "MyMintToken", + Symbol: "MMTK", + Decimals: 9, + IsMintable: true, + Owner: types.StringToAddress("0x123456789"), + }, + expectErr: false, + }, + } + + for _, c := range cases { + c := c + t.Run(c.name, func(t *testing.T) { + t.Parallel() + + p := &genesisParams{nativeTokenConfigRaw: c.rawConfig} + err := p.extractNativeTokenMetadata() + + if c.expectErr { + require.Error(t, err) + require.Nil(t, p.nativeTokenConfig) + } else { + require.NoError(t, err) + require.Equal(t, c.expectedCfg, p.nativeTokenConfig) + } + }) + } +} diff --git a/command/genesis/polybft_params.go b/command/genesis/polybft_params.go index 561e68734f..b141788c44 100644 --- a/command/genesis/polybft_params.go +++ b/command/genesis/polybft_params.go @@ -1,107 +1,172 @@ package genesis import ( + "encoding/hex" "errors" "fmt" "math/big" + "path" "strings" "time" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" + "github.com/multiformats/go-multiaddr" "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/helper" - "github.com/0xPolygon/polygon-edge/consensus/polybft" - "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/server" "github.com/0xPolygon/polygon-edge/types" ) const ( - manifestPathFlag = "manifest" - validatorSetSizeFlag = "validator-set-size" - sprintSizeFlag = "sprint-size" - blockTimeFlag = "block-time" - bridgeFlag = "bridge-json-rpc" - trackerStartBlocksFlag = "tracker-start-blocks" - trieRootFlag = "trieroot" - - defaultManifestPath = "./manifest.json" + validatorsFlag = "validators" + validatorsPathFlag = "validators-path" + validatorsPrefixFlag = "validators-prefix" + + defaultValidatorPrefixPath = "test-chain-" + + sprintSizeFlag = "sprint-size" + blockTimeFlag = "block-time" + trieRootFlag = "trieroot" + + blockTimeDriftFlag = "block-time-drift" + defaultEpochSize = uint64(10) defaultSprintSize = uint64(5) defaultValidatorSetSize = 100 defaultBlockTime = 2 * time.Second - defaultBridge = false defaultEpochReward = 1 - - contractDeployedAllowListAdminFlag = "contract-deployer-allow-list-admin" - contractDeployedAllowListEnabledFlag = "contract-deployer-allow-list-enabled" + defaultBlockTimeDrift = uint64(10) + + contractDeployerAllowListAdminFlag = "contract-deployer-allow-list-admin" + contractDeployerAllowListEnabledFlag = "contract-deployer-allow-list-enabled" + contractDeployerBlockListAdminFlag = "contract-deployer-block-list-admin" + contractDeployerBlockListEnabledFlag = "contract-deployer-block-list-enabled" + transactionsAllowListAdminFlag = "transactions-allow-list-admin" + transactionsAllowListEnabledFlag = "transactions-allow-list-enabled" + transactionsBlockListAdminFlag = "transactions-block-list-admin" + transactionsBlockListEnabledFlag = "transactions-block-list-enabled" + bridgeAllowListAdminFlag = "bridge-allow-list-admin" + bridgeAllowListEnabledFlag = "bridge-allow-list-enabled" + bridgeBlockListAdminFlag = "bridge-block-list-admin" + bridgeBlockListEnabledFlag = "bridge-block-list-enabled" bootnodePortStart = 30301 + + ecdsaAddressLength = 40 + blsKeyLength = 256 ) var ( errNoGenesisValidators = errors.New("genesis validators aren't provided") + errNoPremineAllowed = errors.New("native token is not mintable, so no premine is allowed " + + "except for zero address and reward wallet if native token is used as reward token") ) // generatePolyBftChainConfig creates and persists polybft chain configuration to the provided file path func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) error { - // load manifest file - manifest, err := polybft.LoadManifest(p.manifestPath) + // populate premine balance map + premineBalances := make(map[types.Address]*premineInfo, len(p.premine)) + + for _, premine := range p.premine { + premineInfo, err := parsePremineInfo(premine) + if err != nil { + return fmt.Errorf("invalid balance amount provided '%s' : %w", premine, err) + } + + premineBalances[premineInfo.address] = premineInfo + } + + walletPremineInfo, err := parsePremineInfo(p.rewardWallet) if err != nil { - return fmt.Errorf("failed to load manifest file from provided path '%s': %w", p.manifestPath, err) + return fmt.Errorf("invalid reward wallet configuration provided '%s' : %w", p.rewardWallet, err) } - if len(manifest.GenesisValidators) == 0 { - return errNoGenesisValidators + if !p.nativeTokenConfig.IsMintable { + // validate premine map, no premine is allowed if token is not mintable, + // except for the reward wallet (if native token is used as reward token) and zero address + for a := range premineBalances { + if a != types.ZeroAddress && (p.rewardTokenCode != "" || a != walletPremineInfo.address) { + return errNoPremineAllowed + } + } } - eventTrackerStartBlock, err := parseTrackerStartBlocks(params.eventTrackerStartBlocks) - if err != nil { - return err + var ( + rewardTokenByteCode []byte + rewardTokenAddr = contracts.NativeERC20TokenContract + ) + + if p.rewardTokenCode == "" { + // native token is used as a reward token, and reward wallet is not a zero address + // so we need to add that address to premine map + premineBalances[walletPremineInfo.address] = walletPremineInfo + } else { + bytes, err := hex.DecodeString(p.rewardTokenCode) + if err != nil { + return fmt.Errorf("could not decode reward token byte code '%s' : %w", p.rewardTokenCode, err) + } + + rewardTokenByteCode = bytes + rewardTokenAddr = contracts.RewardTokenContract } - var bridge *polybft.BridgeConfig + initialValidators, err := p.getValidatorAccounts(premineBalances) + if err != nil { + return fmt.Errorf("failed to retrieve genesis validators: %w", err) + } - // populate bridge configuration - if p.bridgeJSONRPCAddr != "" && manifest.RootchainConfig != nil { - bridge = manifest.RootchainConfig.ToBridgeConfig() - bridge.JSONRPCEndpoint = p.bridgeJSONRPCAddr - bridge.EventTrackerStartBlocks = eventTrackerStartBlock + if len(initialValidators) == 0 { + return errNoGenesisValidators } if _, err := o.Write([]byte("[GENESIS VALIDATORS]\n")); err != nil { return err } - for _, v := range manifest.GenesisValidators { + for _, v := range initialValidators { if _, err := o.Write([]byte(fmt.Sprintf("%v\n", v))); err != nil { return err } } polyBftConfig := &polybft.PolyBFTConfig{ - InitialValidatorSet: manifest.GenesisValidators, - BlockTime: p.blockTime, + InitialValidatorSet: initialValidators, + BlockTime: common.Duration{Duration: p.blockTime}, EpochSize: p.epochSize, SprintSize: p.sprintSize, EpochReward: p.epochReward, // use 1st account as governance address - Governance: manifest.GenesisValidators[0].Address, - Bridge: bridge, - InitialTrieRoot: types.StringToHash(p.initialStateRoot), - MintableERC20Token: p.mintableNativeToken, + Governance: types.ZeroAddress, + InitialTrieRoot: types.StringToHash(p.initialStateRoot), + NativeTokenConfig: p.nativeTokenConfig, + MinValidatorSetSize: p.minNumValidators, + MaxValidatorSetSize: p.maxNumValidators, + RewardConfig: &polybft.RewardsConfig{ + TokenAddress: rewardTokenAddr, + WalletAddress: walletPremineInfo.address, + WalletAmount: walletPremineInfo.amount, + }, + BlockTimeDrift: p.blockTimeDrift, + } + + // Disable london hardfork if burn contract address is not provided + enabledForks := chain.AllForksEnabled + if !p.isBurnContractEnabled() { + enabledForks.RemoveFork(chain.London) } chainConfig := &chain.Chain{ Name: p.name, Params: &chain.Params{ - ChainID: manifest.ChainID, - Forks: chain.AllForksEnabled, + ChainID: int64(p.chainID), + Forks: enabledForks, Engine: map[string]interface{}{ string(server.PolyBFTConsensus): polyBftConfig, }, @@ -109,72 +174,48 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er Bootnodes: p.bootnodes, } - genesisValidators := make(map[types.Address]struct{}, len(manifest.GenesisValidators)) - totalStake := big.NewInt(0) + burnContractAddr := types.ZeroAddress - for _, validator := range manifest.GenesisValidators { - // populate premine info for validator accounts - genesisValidators[validator.Address] = struct{}{} - - // increment total stake - totalStake.Add(totalStake, validator.Stake) - } + if p.isBurnContractEnabled() { + chainConfig.Params.BurnContract = make(map[uint64]types.Address, 1) - // deploy genesis contracts - allocs, err := p.deployContracts(totalStake) - if err != nil { - return err - } - - premineInfos := make([]*PremineInfo, len(p.premine)) - premineValidatorsAddrs := []string{} - // premine non-validator - for i, premine := range p.premine { - premineInfo, err := ParsePremineInfo(premine) + burnContractInfo, err := parseBurnContractInfo(p.burnContract) if err != nil { return err } - // collect validators addresses which got premined, as it is an error - // genesis validators balances must be defined in manifest file and should not be changed in the genesis - if _, ok := genesisValidators[premineInfo.Address]; ok { - premineValidatorsAddrs = append(premineValidatorsAddrs, premineInfo.Address.String()) + if !p.nativeTokenConfig.IsMintable { + // burn contract can be specified on arbitrary address for non-mintable native tokens + burnContractAddr = burnContractInfo.Address + chainConfig.Params.BurnContract[burnContractInfo.BlockNumber] = burnContractAddr + chainConfig.Params.BurnContractDestinationAddress = burnContractInfo.DestinationAddress } else { - premineInfos[i] = premineInfo + // burnt funds are sent to zero address when dealing with mintable native tokens + chainConfig.Params.BurnContract[burnContractInfo.BlockNumber] = types.ZeroAddress } } - // if there are any premined validators in the genesis command, consider it as an error - if len(premineValidatorsAddrs) > 0 { - return fmt.Errorf("it is not allowed to override genesis validators balance outside from the manifest definition. "+ - "Validators which got premined: (%s)", strings.Join(premineValidatorsAddrs, ", ")) + // deploy genesis contracts + allocs, err := p.deployContracts(rewardTokenByteCode, polyBftConfig, chainConfig, burnContractAddr) + if err != nil { + return err } - // populate genesis validators balances - for _, validator := range manifest.GenesisValidators { - allocs[validator.Address] = &chain.GenesisAccount{ - Balance: validator.Balance, + // premine other accounts + for _, premine := range premineBalances { + // validators have already been premined, so no need to premine them again + if _, ok := allocs[premine.address]; ok { + continue } - } - // premine non-validator accounts - for _, premine := range premineInfos { - allocs[premine.Address] = &chain.GenesisAccount{ - Balance: premine.Amount, + allocs[premine.address] = &chain.GenesisAccount{ + Balance: premine.amount, } } - validatorMetadata := make([]*polybft.ValidatorMetadata, len(manifest.GenesisValidators)) - - for i, validator := range manifest.GenesisValidators { - // update balance of genesis validator, because it could be changed via premine flag - balance, err := chain.GetGenesisAccountBalance(validator.Address, allocs) - if err != nil { - return err - } - - validator.Balance = balance + validatorMetadata := make([]*validator.ValidatorMetadata, len(initialValidators)) + for i, validator := range initialValidators { // create validator metadata instance metadata, err := validator.ToValidatorMetadata() if err != nil { @@ -189,7 +230,7 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er } } - genesisExtraData, err := generateExtraDataPolyBft(validatorMetadata) + genesisExtraData, err := GenerateExtraDataPolyBft(validatorMetadata) if err != nil { return err } @@ -207,27 +248,78 @@ func (p *genesisParams) generatePolyBftChainConfig(o command.OutputFormatter) er if len(p.contractDeployerAllowListAdmin) != 0 { // only enable allow list if there is at least one address as **admin**, otherwise // the allow list could never be updated - chainConfig.Params.ContractDeployerAllowList = &chain.AllowListConfig{ + chainConfig.Params.ContractDeployerAllowList = &chain.AddressListConfig{ AdminAddresses: stringSliceToAddressSlice(p.contractDeployerAllowListAdmin), EnabledAddresses: stringSliceToAddressSlice(p.contractDeployerAllowListEnabled), } } + if len(p.contractDeployerBlockListAdmin) != 0 { + // only enable block list if there is at least one address as **admin**, otherwise + // the block list could never be updated + chainConfig.Params.ContractDeployerBlockList = &chain.AddressListConfig{ + AdminAddresses: stringSliceToAddressSlice(p.contractDeployerBlockListAdmin), + EnabledAddresses: stringSliceToAddressSlice(p.contractDeployerBlockListEnabled), + } + } + + if len(p.transactionsAllowListAdmin) != 0 { + // only enable allow list if there is at least one address as **admin**, otherwise + // the allow list could never be updated + chainConfig.Params.TransactionsAllowList = &chain.AddressListConfig{ + AdminAddresses: stringSliceToAddressSlice(p.transactionsAllowListAdmin), + EnabledAddresses: stringSliceToAddressSlice(p.transactionsAllowListEnabled), + } + } + + if len(p.transactionsBlockListAdmin) != 0 { + // only enable block list if there is at least one address as **admin**, otherwise + // the block list could never be updated + chainConfig.Params.TransactionsBlockList = &chain.AddressListConfig{ + AdminAddresses: stringSliceToAddressSlice(p.transactionsBlockListAdmin), + EnabledAddresses: stringSliceToAddressSlice(p.transactionsBlockListEnabled), + } + } + + if len(p.bridgeAllowListAdmin) != 0 { + // only enable allow list if there is at least one address as **admin**, otherwise + // the allow list could never be updated + chainConfig.Params.BridgeAllowList = &chain.AddressListConfig{ + AdminAddresses: stringSliceToAddressSlice(p.bridgeAllowListAdmin), + EnabledAddresses: stringSliceToAddressSlice(p.bridgeAllowListEnabled), + } + } + + if len(p.bridgeBlockListAdmin) != 0 { + // only enable block list if there is at least one address as **admin**, otherwise + // the block list could never be updated + chainConfig.Params.BridgeBlockList = &chain.AddressListConfig{ + AdminAddresses: stringSliceToAddressSlice(p.bridgeBlockListAdmin), + EnabledAddresses: stringSliceToAddressSlice(p.bridgeBlockListEnabled), + } + } + + if p.isBurnContractEnabled() { + // only populate base fee and base fee multiplier values if burn contract(s) + // is provided + chainConfig.Genesis.BaseFee = command.DefaultGenesisBaseFee + chainConfig.Genesis.BaseFeeEM = command.DefaultGenesisBaseFeeEM + } + return helper.WriteGenesisConfigToDisk(chainConfig, params.genesisPath) } -func (p *genesisParams) deployContracts(totalStake *big.Int) (map[types.Address]*chain.GenesisAccount, error) { +func (p *genesisParams) deployContracts( + rewardTokenByteCode []byte, + polybftConfig *polybft.PolyBFTConfig, + chainConfig *chain.Chain, + burnContractAddr types.Address) (map[types.Address]*chain.GenesisAccount, error) { type contractInfo struct { artifact *artifact.Artifact address types.Address } genesisContracts := []*contractInfo{ - { - // ChildValidatorSet contract - artifact: contractsapi.ChildValidatorSet, - address: contracts.ValidatorSetContract, - }, { // State receiver contract artifact: contractsapi.StateReceiver, @@ -239,9 +331,14 @@ func (p *genesisParams) deployContracts(totalStake *big.Int) (map[types.Address] address: contracts.ChildERC20Contract, }, { - // ChildERC20Predicate contract - artifact: contractsapi.ChildERC20Predicate, - address: contracts.ChildERC20PredicateContract, + // ChildERC721 token contract + artifact: contractsapi.ChildERC721, + address: contracts.ChildERC721Contract, + }, + { + // ChildERC1155 contract + artifact: contractsapi.ChildERC1155, + address: contracts.ChildERC1155Contract, }, { // BLS contract @@ -258,17 +355,119 @@ func (p *genesisParams) deployContracts(totalStake *big.Int) (map[types.Address] artifact: contractsapi.L2StateSender, address: contracts.L2StateSenderContract, }, + { + artifact: contractsapi.ValidatorSet, + address: contracts.ValidatorSetContract, + }, + { + artifact: contractsapi.RewardPool, + address: contracts.RewardPoolContract, + }, } - if !params.mintableNativeToken { + if !params.nativeTokenConfig.IsMintable { + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.NativeERC20, + address: contracts.NativeERC20TokenContract, + }) + + // burn contract can be set only for non-mintable native token. If burn contract is set, + // default EIP1559 contract will be deployed. + if p.isBurnContractEnabled() { + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.EIP1559Burn, + address: burnContractAddr, + }) + } + } else { + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.NativeERC20Mintable, + address: contracts.NativeERC20TokenContract, + }) + } + + if len(params.bridgeAllowListAdmin) != 0 || len(params.bridgeBlockListAdmin) != 0 { + // rootchain originated tokens predicates (with access lists) + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.ChildERC20PredicateACL, + address: contracts.ChildERC20PredicateContract, + }) + + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.ChildERC721PredicateACL, + address: contracts.ChildERC721PredicateContract, + }) + + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.ChildERC1155PredicateACL, + address: contracts.ChildERC1155PredicateContract, + }) + + // childchain originated tokens predicates (with access lists) + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.RootMintableERC20PredicateACL, + address: contracts.RootMintableERC20PredicateContract, + }) + + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.RootMintableERC721PredicateACL, + address: contracts.RootMintableERC721PredicateContract, + }) + genesisContracts = append(genesisContracts, - &contractInfo{artifact: contractsapi.NativeERC20, address: contracts.NativeERC20TokenContract}) + &contractInfo{ + artifact: contractsapi.RootMintableERC1155PredicateACL, + address: contracts.RootMintableERC1155PredicateContract, + }) } else { + // rootchain originated tokens predicates + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.ChildERC20Predicate, + address: contracts.ChildERC20PredicateContract, + }) + + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.ChildERC721Predicate, + address: contracts.ChildERC721PredicateContract, + }) + + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.ChildERC1155Predicate, + address: contracts.ChildERC1155PredicateContract, + }) + + // childchain originated tokens predicates + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.RootMintableERC20Predicate, + address: contracts.RootMintableERC20PredicateContract, + }) + + genesisContracts = append(genesisContracts, + &contractInfo{ + artifact: contractsapi.RootMintableERC721Predicate, + address: contracts.RootMintableERC721PredicateContract, + }) + genesisContracts = append(genesisContracts, - &contractInfo{artifact: contractsapi.NativeERC20Mintable, address: contracts.NativeERC20TokenContract}) + &contractInfo{ + artifact: contractsapi.RootMintableERC1155Predicate, + address: contracts.RootMintableERC1155PredicateContract, + }) } - allocations := make(map[types.Address]*chain.GenesisAccount, len(genesisContracts)) + allocations := make(map[types.Address]*chain.GenesisAccount, len(genesisContracts)+1) for _, contract := range genesisContracts { allocations[contract.address] = &chain.GenesisAccount{ @@ -277,22 +476,85 @@ func (p *genesisParams) deployContracts(totalStake *big.Int) (map[types.Address] } } - // ChildValidatorSet must have funds pre-allocated, because of withdrawal workflow - allocations[contracts.ValidatorSetContract].Balance = totalStake + if rewardTokenByteCode != nil { + // if reward token is provided in genesis then, add it to allocations + // to RewardTokenContract address and update Polybft config + allocations[contracts.RewardTokenContract] = &chain.GenesisAccount{ + Balance: big.NewInt(0), + Code: rewardTokenByteCode, + } + } return allocations, nil } -// generateExtraDataPolyBft populates Extra with specific fields required for polybft consensus protocol -func generateExtraDataPolyBft(validators []*polybft.ValidatorMetadata) ([]byte, error) { - delta := &polybft.ValidatorSetDelta{ - Added: validators, - Removed: bitmap.Bitmap{}, +// getValidatorAccounts gathers validator accounts info either from CLI or from provided local storage +func (p *genesisParams) getValidatorAccounts( + premineBalances map[types.Address]*premineInfo) ([]*validator.GenesisValidator, error) { + // populate validators premine info + if len(p.validators) > 0 { + validators := make([]*validator.GenesisValidator, len(p.validators)) + for i, val := range p.validators { + parts := strings.Split(val, ":") + if len(parts) != 3 { + return nil, fmt.Errorf("expected 3 parts provided in the following format "+ + ", but got %d part(s)", + len(parts)) + } + + if _, err := multiaddr.NewMultiaddr(parts[0]); err != nil { + return nil, fmt.Errorf("invalid P2P multi address '%s' provided: %w ", parts[0], err) + } + + trimmedAddress := strings.TrimPrefix(parts[1], "0x") + if len(trimmedAddress) != ecdsaAddressLength { + return nil, fmt.Errorf("invalid ECDSA address: %s", parts[1]) + } + + trimmedBLSKey := strings.TrimPrefix(parts[2], "0x") + if len(trimmedBLSKey) != blsKeyLength { + return nil, fmt.Errorf("invalid BLS key: %s", parts[2]) + } + + addr := types.StringToAddress(trimmedAddress) + validators[i] = &validator.GenesisValidator{ + MultiAddr: parts[0], + Address: addr, + BlsKey: trimmedBLSKey, + Balance: getPremineAmount(addr, premineBalances, big.NewInt(0)), + Stake: big.NewInt(0), + } + } + + return validators, nil + } + + validatorsPath := p.validatorsPath + if validatorsPath == "" { + validatorsPath = path.Dir(p.genesisPath) } - extra := polybft.Extra{Validators: delta, Checkpoint: &polybft.CheckpointData{}} + validators, err := ReadValidatorsByPrefix(validatorsPath, p.validatorsPrefixPath) + if err != nil { + return nil, err + } + + for _, v := range validators { + v.Balance = getPremineAmount(v.Address, premineBalances, big.NewInt(0)) + v.Stake = big.NewInt(0) + } + + return validators, nil +} + +// getPremineAmount retrieves amount from the premine map or if not provided, returns default amount +func getPremineAmount(addr types.Address, premineMap map[types.Address]*premineInfo, + defaultAmount *big.Int) *big.Int { + if premine, exists := premineMap[addr]; exists { + return premine.amount + } - return append(make([]byte, polybft.ExtraVanity), extra.MarshalRLPTo(nil)...), nil + return defaultAmount } func stringSliceToAddressSlice(addrs []string) []types.Address { diff --git a/command/genesis/utils.go b/command/genesis/utils.go index bef4153758..5e05603593 100644 --- a/command/genesis/utils.go +++ b/command/genesis/utils.go @@ -13,6 +13,8 @@ import ( "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/secrets" "github.com/0xPolygon/polygon-edge/secrets/helper" @@ -62,13 +64,13 @@ func verifyGenesisExistence(genesisPath string) *GenesisGenError { return nil } -type PremineInfo struct { - Address types.Address - Amount *big.Int +type premineInfo struct { + address types.Address + amount *big.Int } -// ParsePremineInfo parses provided premine information and returns premine address and amount -func ParsePremineInfo(premineInfoRaw string) (*PremineInfo, error) { +// parsePremineInfo parses provided premine information and returns premine address and amount +func parsePremineInfo(premineInfoRaw string) (*premineInfo, error) { var ( address types.Address amount = command.DefaultPremineBalance @@ -90,7 +92,7 @@ func ParsePremineInfo(premineInfoRaw string) (*PremineInfo, error) { address = types.StringToAddress(premineInfoRaw) } - return &PremineInfo{Address: address, Amount: amount}, nil + return &premineInfo{address: address, amount: amount}, nil } // parseTrackerStartBlocks parses provided event tracker start blocks configuration. @@ -120,6 +122,46 @@ func parseTrackerStartBlocks(trackerStartBlocksRaw []string) (map[types.Address] return trackerStartBlocksConfig, nil } +// parseBurnContractInfo parses provided burn contract information and returns burn contract block and address +func parseBurnContractInfo(burnContractInfoRaw string) (*polybft.BurnContractInfo, error) { + // :
[:] + burnContractParts := strings.Split(burnContractInfoRaw, ":") + if len(burnContractParts) < 2 || len(burnContractParts) > 3 { + return nil, fmt.Errorf("expected format: :
[:]") + } + + blockRaw := burnContractParts[0] + + blockNum, err := types.ParseUint64orHex(&blockRaw) + if err != nil { + return nil, fmt.Errorf("failed to parse block number %s: %w", blockRaw, err) + } + + contractAddress := burnContractParts[1] + if err = types.IsValidAddress(contractAddress); err != nil { + return nil, fmt.Errorf("failed to parse contract address %s: %w", contractAddress, err) + } + + if len(burnContractParts) == 2 { + return &polybft.BurnContractInfo{ + BlockNumber: blockNum, + Address: types.StringToAddress(contractAddress), + DestinationAddress: types.ZeroAddress, + }, nil + } + + destinationAddress := burnContractParts[2] + if err = types.IsValidAddress(destinationAddress); err != nil { + return nil, fmt.Errorf("failed to parse burn destination address %s: %w", destinationAddress, err) + } + + return &polybft.BurnContractInfo{ + BlockNumber: blockNum, + Address: types.StringToAddress(contractAddress), + DestinationAddress: types.StringToAddress(destinationAddress), + }, nil +} + // GetValidatorKeyFiles returns file names which has validator secrets func GetValidatorKeyFiles(rootDir, filePrefix string) ([]string, error) { if rootDir == "" { @@ -158,27 +200,26 @@ func GetValidatorKeyFiles(rootDir, filePrefix string) ([]string, error) { } // ReadValidatorsByPrefix reads validators secrets on a given root directory and with given folder prefix -func ReadValidatorsByPrefix(dir, prefix string) ([]*polybft.Validator, error) { +func ReadValidatorsByPrefix(dir, prefix string) ([]*validator.GenesisValidator, error) { validatorKeyFiles, err := GetValidatorKeyFiles(dir, prefix) if err != nil { return nil, err } - validators := make([]*polybft.Validator, len(validatorKeyFiles)) + validators := make([]*validator.GenesisValidator, len(validatorKeyFiles)) for i, file := range validatorKeyFiles { path := filepath.Join(dir, file) - account, nodeID, blsSignature, err := getSecrets(path) + account, nodeID, err := getSecrets(path) if err != nil { return nil, err } - validators[i] = &polybft.Validator{ + validators[i] = &validator.GenesisValidator{ Address: types.Address(account.Ecdsa.Address()), BlsPrivateKey: account.Bls, BlsKey: hex.EncodeToString(account.Bls.PublicKey().Marshal()), - BlsSignature: blsSignature, MultiAddr: fmt.Sprintf("/ip4/%s/tcp/%d/p2p/%s", "127.0.0.1", bootnodePortStart+int64(i), nodeID), } } @@ -186,7 +227,7 @@ func ReadValidatorsByPrefix(dir, prefix string) ([]*polybft.Validator, error) { return validators, nil } -func getSecrets(directory string) (*wallet.Account, string, string, error) { +func getSecrets(directory string) (*wallet.Account, string, error) { baseConfig := &secrets.SecretsManagerParams{ Logger: hclog.NewNullLogger(), Extra: map[string]interface{}{ @@ -196,20 +237,30 @@ func getSecrets(directory string) (*wallet.Account, string, string, error) { localManager, err := local.SecretsManagerFactory(nil, baseConfig) if err != nil { - return nil, "", "", fmt.Errorf("unable to instantiate local secrets manager, %w", err) + return nil, "", fmt.Errorf("unable to instantiate local secrets manager, %w", err) } nodeID, err := helper.LoadNodeID(localManager) if err != nil { - return nil, "", "", err + return nil, "", err } account, err := wallet.NewAccountFromSecret(localManager) if err != nil { - return nil, "", "", err + return nil, "", err + } + + return account, nodeID, err +} + +// GenerateExtraDataPolyBft populates Extra with specific fields required for polybft consensus protocol +func GenerateExtraDataPolyBft(validators []*validator.ValidatorMetadata) ([]byte, error) { + delta := &validator.ValidatorSetDelta{ + Added: validators, + Removed: bitmap.Bitmap{}, } - blsSignature, err := helper.LoadBLSSignature(localManager) + extra := polybft.Extra{Validators: delta, Checkpoint: &polybft.CheckpointData{}} - return account, nodeID, blsSignature, err + return extra.MarshalRLPTo(nil), nil } diff --git a/command/helper/helper.go b/command/helper/helper.go index e19b25d441..82411528e3 100644 --- a/command/helper/helper.go +++ b/command/helper/helper.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "math/big" "net" "net/url" "time" @@ -250,3 +251,12 @@ func SetRequiredFlags(cmd *cobra.Command, requiredFlags []string) { _ = cmd.MarkFlagRequired(requiredFlag) } } + +func ParseAmount(amount string) (*big.Int, error) { + result, ok := new(big.Int).SetString(amount, 0) + if !ok || result.Cmp(big.NewInt(0)) <= 0 { + return nil, fmt.Errorf("amount %s should be numerical value greater than zero", amount) + } + + return result, nil +} diff --git a/command/ibft/switch/params.go b/command/ibft/switch/params.go index 2926008ad0..109e2f9bbf 100644 --- a/command/ibft/switch/params.go +++ b/command/ibft/switch/params.go @@ -403,6 +403,7 @@ func appendIBFTForks( Type: ibftType, ValidatorType: validatorType, From: common.JSONNumber{Value: from}, + BlockTime: lastFork.BlockTime, } switch ibftType { diff --git a/command/polybft/polybft_command.go b/command/polybft/polybft_command.go index 22b0c2f6fa..af5bed0800 100644 --- a/command/polybft/polybft_command.go +++ b/command/polybft/polybft_command.go @@ -1,13 +1,16 @@ package polybft import ( - "github.com/0xPolygon/polygon-edge/command/sidechain/registration" - "github.com/0xPolygon/polygon-edge/command/sidechain/staking" + "github.com/0xPolygon/polygon-edge/command/rootchain/registration" + "github.com/0xPolygon/polygon-edge/command/rootchain/staking" + "github.com/0xPolygon/polygon-edge/command/rootchain/supernet" + "github.com/0xPolygon/polygon-edge/command/rootchain/supernet/stakemanager" + "github.com/0xPolygon/polygon-edge/command/rootchain/validators" + "github.com/0xPolygon/polygon-edge/command/rootchain/whitelist" + "github.com/0xPolygon/polygon-edge/command/rootchain/withdraw" + "github.com/0xPolygon/polygon-edge/command/sidechain/rewards" "github.com/0xPolygon/polygon-edge/command/sidechain/unstaking" - "github.com/0xPolygon/polygon-edge/command/sidechain/validators" - - "github.com/0xPolygon/polygon-edge/command/sidechain/whitelist" - "github.com/0xPolygon/polygon-edge/command/sidechain/withdraw" + sidechainWithdraw "github.com/0xPolygon/polygon-edge/command/sidechain/withdraw" "github.com/spf13/cobra" ) @@ -18,12 +21,27 @@ func GetCommand() *cobra.Command { } polybftCmd.AddCommand( - staking.GetCommand(), + // sidechain (validator set) command to unstake on child chain unstaking.GetCommand(), + // sidechain (validator set) command to withdraw stake on child chain + sidechainWithdraw.GetCommand(), + // sidechain (reward pool) command to withdraw pending rewards + rewards.GetCommand(), + // rootchain (stake manager) command to withdraw stake withdraw.GetCommand(), + // rootchain (supernet manager) command that queries validator info validators.GetCommand(), + // rootchain (supernet manager) whitelist validator whitelist.GetCommand(), + // rootchain (supernet manager) register validator registration.GetCommand(), + // rootchain (stake manager) stake command + staking.GetCommand(), + // rootchain (supernet manager) command for finalizing genesis + // validator set and enabling staking + supernet.GetCommand(), + // rootchain command for deploying stake manager + stakemanager.GetCommand(), ) return polybftCmd diff --git a/command/polybftmanifest/manifest_init.go b/command/polybftmanifest/manifest_init.go deleted file mode 100644 index 5d22a09486..0000000000 --- a/command/polybftmanifest/manifest_init.go +++ /dev/null @@ -1,268 +0,0 @@ -package polybftmanifest - -import ( - "bytes" - "errors" - "fmt" - "math/big" - "os" - "path" - "strings" - - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/command/genesis" - "github.com/0xPolygon/polygon-edge/consensus/polybft" - "github.com/0xPolygon/polygon-edge/types" - "github.com/multiformats/go-multiaddr" - "github.com/spf13/cobra" -) - -const ( - manifestPathFlag = "path" - premineValidatorsFlag = "premine-validators" - stakeFlag = "stake" - validatorsFlag = "validators" - validatorsPathFlag = "validators-path" - validatorsPrefixFlag = "validators-prefix" - chainIDFlag = "chain-id" - - defaultValidatorPrefixPath = "test-chain-" - defaultManifestPath = "./manifest.json" - - ecdsaAddressLength = 40 - blsKeyLength = 256 - blsSignatureLength = 128 -) - -var ( - params = &manifestInitParams{} -) - -func GetCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "manifest", - Short: "Initializes manifest file. It is applicable only to polybft consensus protocol.", - PreRunE: runPreRun, - Run: runCommand, - } - - setFlags(cmd) - - return cmd -} - -func runPreRun(_ *cobra.Command, _ []string) error { - return params.validateFlags() -} - -func setFlags(cmd *cobra.Command) { - cmd.Flags().StringVar( - ¶ms.manifestPath, - manifestPathFlag, - defaultManifestPath, - "the file path where manifest file is going to be stored", - ) - - cmd.Flags().StringVar( - ¶ms.validatorsPath, - validatorsPathFlag, - "./", - "root path containing polybft validator keys", - ) - - cmd.Flags().StringVar( - ¶ms.validatorsPrefixPath, - validatorsPrefixFlag, - defaultValidatorPrefixPath, - "folder prefix names for polybft validator keys", - ) - - cmd.Flags().StringArrayVar( - ¶ms.validators, - validatorsFlag, - []string{}, - "validators defined by user (format: :::)", - ) - - cmd.Flags().StringArrayVar( - ¶ms.premineValidators, - premineValidatorsFlag, - []string{}, - fmt.Sprintf( - "the premined validators and balances (format:
[:]). Default premined balance: %d", - command.DefaultPremineBalance, - ), - ) - - cmd.Flags().Int64Var( - ¶ms.chainID, - chainIDFlag, - command.DefaultChainID, - "the ID of the chain", - ) - - cmd.Flags().StringArrayVar( - ¶ms.stakes, - stakeFlag, - []string{}, - fmt.Sprintf( - "validators staked amount (format:
[:]). Default stake amount: %d", - command.DefaultStake, - ), - ) - - cmd.MarkFlagsMutuallyExclusive(validatorsFlag, validatorsPathFlag) - cmd.MarkFlagsMutuallyExclusive(validatorsFlag, validatorsPrefixFlag) -} - -func runCommand(cmd *cobra.Command, _ []string) { - outputter := command.InitializeOutputter(cmd) - defer outputter.WriteOutput() - - validators, err := params.getValidatorAccounts() - if err != nil { - outputter.SetError(fmt.Errorf("failed to get validator accounts: %w", err)) - - return - } - - manifest := &polybft.Manifest{GenesisValidators: validators, ChainID: params.chainID} - if err = manifest.Save(params.manifestPath); err != nil { - outputter.SetError(fmt.Errorf("failed to save manifest file '%s': %w", params.manifestPath, err)) - - return - } - - outputter.SetCommandResult(params.getResult()) -} - -type manifestInitParams struct { - manifestPath string - validatorsPath string - validatorsPrefixPath string - premineValidators []string - stakes []string - validators []string - chainID int64 -} - -func (p *manifestInitParams) validateFlags() error { - if _, err := os.Stat(p.validatorsPath); errors.Is(err, os.ErrNotExist) { - return fmt.Errorf("provided validators path '%s' doesn't exist", p.validatorsPath) - } - - return nil -} - -// getValidatorAccounts gathers validator accounts info either from CLI or from provided local storage -func (p *manifestInitParams) getValidatorAccounts() ([]*polybft.Validator, error) { - // populate validators premine info - premineMap := make(map[types.Address]*genesis.PremineInfo, len(p.premineValidators)) - stakeMap := make(map[types.Address]*genesis.PremineInfo, len(p.stakes)) - - for _, premine := range p.premineValidators { - premineInfo, err := genesis.ParsePremineInfo(premine) - if err != nil { - return nil, err - } - - premineMap[premineInfo.Address] = premineInfo - } - - for _, stake := range p.stakes { - stakeInfo, err := genesis.ParsePremineInfo(stake) - if err != nil { - return nil, fmt.Errorf("invalid stake amount provided '%s' : %w", stake, err) - } - - stakeMap[stakeInfo.Address] = stakeInfo - } - - if len(p.validators) > 0 { - validators := make([]*polybft.Validator, len(p.validators)) - for i, validator := range p.validators { - parts := strings.Split(validator, ":") - if len(parts) != 4 { - return nil, fmt.Errorf("expected 4 parts provided in the following format "+ - ", but got %d part(s)", - len(parts)) - } - - if _, err := multiaddr.NewMultiaddr(parts[0]); err != nil { - return nil, fmt.Errorf("invalid P2P multi address '%s' provided: %w ", parts[0], err) - } - - trimmedAddress := strings.TrimPrefix(parts[1], "0x") - if len(trimmedAddress) != ecdsaAddressLength { - return nil, fmt.Errorf("invalid ECDSA address: %s", parts[1]) - } - - trimmedBLSKey := strings.TrimPrefix(parts[2], "0x") - if len(trimmedBLSKey) != blsKeyLength { - return nil, fmt.Errorf("invalid BLS key: %s", parts[2]) - } - - if len(parts[3]) != blsSignatureLength { - return nil, fmt.Errorf("invalid BLS signature: %s", parts[3]) - } - - addr := types.StringToAddress(trimmedAddress) - validators[i] = &polybft.Validator{ - MultiAddr: parts[0], - Address: addr, - BlsKey: trimmedBLSKey, - BlsSignature: parts[3], - Balance: getPremineAmount(addr, premineMap, command.DefaultPremineBalance), - Stake: getPremineAmount(addr, stakeMap, command.DefaultStake), - } - } - - return validators, nil - } - - validatorsPath := p.validatorsPath - if validatorsPath == "" { - validatorsPath = path.Dir(p.manifestPath) - } - - validators, err := genesis.ReadValidatorsByPrefix(validatorsPath, p.validatorsPrefixPath) - if err != nil { - return nil, err - } - - for _, v := range validators { - v.Balance = getPremineAmount(v.Address, premineMap, command.DefaultPremineBalance) - v.Stake = getPremineAmount(v.Address, stakeMap, command.DefaultStake) - } - - return validators, nil -} - -// getPremineAmount retrieves amount from the premine map or if not provided, returns default amount -func getPremineAmount(addr types.Address, premineMap map[types.Address]*genesis.PremineInfo, - defaultAmount *big.Int) *big.Int { - if premine, exists := premineMap[addr]; exists { - return premine.Amount - } - - return defaultAmount -} - -func (p *manifestInitParams) getResult() command.CommandResult { - return &result{ - message: fmt.Sprintf("Manifest file written to %s\n", p.manifestPath), - } -} - -type result struct { - message string -} - -func (r *result) GetOutput() string { - var buffer bytes.Buffer - - buffer.WriteString("\n[MANIFEST INITIALIZATION SUCCESS]\n") - buffer.WriteString(r.message) - - return buffer.String() -} diff --git a/command/polybftsecrets/params.go b/command/polybftsecrets/params.go index f35d2bea13..ec521ecbfc 100644 --- a/command/polybftsecrets/params.go +++ b/command/polybftsecrets/params.go @@ -20,7 +20,6 @@ const ( networkFlag = "network" numFlag = "num" outputFlag = "output" - chainIDFlag = "chain-id" // maxInitNum is the maximum value for "num" flag maxInitNum = 30 @@ -40,8 +39,6 @@ type initParams struct { insecureLocalStore bool output bool - - chainID int64 } func (ip *initParams) validateFlags() error { @@ -119,13 +116,6 @@ func (ip *initParams) setFlags(cmd *cobra.Command) { false, "the flag indicating to output existing secrets", ) - - cmd.Flags().Int64Var( - &ip.chainID, - chainIDFlag, - command.DefaultChainID, - "the ID of the chain", - ) } func (ip *initParams) Execute() (Results, error) { @@ -196,19 +186,6 @@ func (ip *initParams) initKeys(secretsManager secrets.SecretsManager) ([]string, } generated = append(generated, secrets.ValidatorKey, secrets.ValidatorBLSKey) - } else { - a, err = wallet.NewAccountFromSecret(secretsManager) - if err != nil { - return generated, fmt.Errorf("error loading account: %w", err) - } - } - - if !secretsManager.HasSecret(secrets.ValidatorBLSSignature) { - if _, err = helper.InitValidatorBLSSignature(secretsManager, a, ip.chainID); err != nil { - return generated, fmt.Errorf("%w: error initializing validator-bls-signature", err) - } - - generated = append(generated, secrets.ValidatorBLSSignature) } } @@ -234,12 +211,6 @@ func (ip *initParams) getResult( res.Address = types.Address(account.Ecdsa.Address()) res.BLSPubkey = hex.EncodeToString(account.Bls.PublicKey().Marshal()) - s, err := secretsManager.GetSecret(secrets.ValidatorBLSSignature) - if err != nil { - return nil, err - } - - res.BLSSignature = string(s) res.Generated = strings.Join(generated, ", ") if ip.printPrivateKey { diff --git a/command/polybftsecrets/params_test.go b/command/polybftsecrets/params_test.go index 0671db3505..2d140973b6 100644 --- a/command/polybftsecrets/params_test.go +++ b/command/polybftsecrets/params_test.go @@ -29,7 +29,6 @@ func Test_initKeys(t *testing.T) { ip := &initParams{ generatesAccount: false, generatesNetwork: false, - chainID: 1, } _, err = ip.initKeys(sm) @@ -38,16 +37,14 @@ func Test_initKeys(t *testing.T) { assert.False(t, fileExists(path.Join(dir, "consensus/validator.key"))) assert.False(t, fileExists(path.Join(dir, "consensus/validator-bls.key"))) assert.False(t, fileExists(path.Join(dir, "libp2p/libp2p.key"))) - assert.False(t, fileExists(path.Join(dir, "consensus/validator.sig"))) ip.generatesAccount = true res, err := ip.initKeys(sm) require.NoError(t, err) - assert.Len(t, res, 3) + assert.Len(t, res, 2) assert.True(t, fileExists(path.Join(dir, "consensus/validator.key"))) assert.True(t, fileExists(path.Join(dir, "consensus/validator-bls.key"))) - assert.True(t, fileExists(path.Join(dir, "consensus/validator.sig"))) assert.False(t, fileExists(path.Join(dir, "libp2p/libp2p.key"))) ip.generatesNetwork = true @@ -83,7 +80,6 @@ func Test_getResult(t *testing.T) { generatesAccount: true, generatesNetwork: true, printPrivateKey: true, - chainID: 1, } _, err = ip.initKeys(sm) @@ -92,13 +88,7 @@ func Test_getResult(t *testing.T) { res, err := ip.getResult(sm, []string{}) require.NoError(t, err) - // Test BLS signature sir := res.(*SecretsInitResult) //nolint:forcetypeassert - ds, err := hex.DecodeString(sir.BLSSignature) - require.NoError(t, err) - - _, err = bls.UnmarshalSignature(ds) - require.NoError(t, err) // Test public key serialization privKey, err := hex.DecodeString(sir.PrivateKey) diff --git a/command/polybftsecrets/result.go b/command/polybftsecrets/result.go index 70adf2afd5..f3867312c3 100644 --- a/command/polybftsecrets/result.go +++ b/command/polybftsecrets/result.go @@ -28,7 +28,6 @@ type SecretsInitResult struct { NodeID string `json:"node_id"` PrivateKey string `json:"private_key"` BLSPrivateKey string `json:"bls_private_key"` - BLSSignature string `json:"bls_signature"` Insecure bool `json:"insecure"` Generated string `json:"generated"` } @@ -64,13 +63,6 @@ func (r *SecretsInitResult) GetOutput() string { ) } - if r.BLSSignature != "" { - vals = append( - vals, - fmt.Sprintf("BLS Signature|%s", r.BLSSignature), - ) - } - vals = append(vals, fmt.Sprintf("Node ID|%s", r.NodeID)) if r.Insecure { diff --git a/command/polybftsecrets/utils.go b/command/polybftsecrets/utils.go index 9507c0cb31..655f9b9e87 100644 --- a/command/polybftsecrets/utils.go +++ b/command/polybftsecrets/utils.go @@ -12,15 +12,18 @@ import ( const ( AccountDirFlag = "data-dir" AccountConfigFlag = "config" + PrivateKeyFlag = "private-key" + ChainIDFlag = "chain-id" AccountDirFlagDesc = "the directory for the Polygon Edge data if the local FS is used" AccountConfigFlagDesc = "the path to the SecretsManager config file, if omitted, the local FS secrets manager is used" + PrivateKeyFlagDesc = "hex-encoded private key of the account which executes rootchain commands" + ChainIDFlagDesc = "ID of child chain" ) // common errors for all polybft commands var ( ErrInvalidNum = fmt.Errorf("num flag value should be between 1 and %d", maxInitNum) - ErrInvalidConfig = errors.New("invalid secrets configuration") ErrInvalidParams = errors.New("no config file or data directory passed in") ErrUnsupportedType = errors.New("unsupported secrets manager") ErrSecureLocalStoreNotImplemented = errors.New( @@ -35,9 +38,7 @@ func GetSecretsManager(dataPath, configPath string, insecureLocalStore bool) (se if configPath != "" { secretsConfig, readErr := secrets.ReadConfig(configPath) if readErr != nil { - invalidConfigErr := ErrInvalidConfig.Error() - - return nil, fmt.Errorf("%s: %w", invalidConfigErr, readErr) + return nil, fmt.Errorf("invalid secrets configuration: %w", readErr) } if !secrets.SupportedServiceManager(secretsConfig.Type) { diff --git a/command/regenesis/howtotest.md b/command/regenesis/howtotest.md index 8a474a228c..6c0064cbae 100644 --- a/command/regenesis/howtotest.md +++ b/command/regenesis/howtotest.md @@ -1,166 +1,178 @@ -1) create cluster -```bash -scripts/cluster ibft -``` -2) check balance -```bash -curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002 - -{"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"} -``` - -3) get trie root -```bash -./polygon-edge regenesis getroot --rpc "http://localhost:10002" - -[Trie copy SUCCESS] -state root 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 for block 38 - -``` - -4) make trie snapshot -```bash - -./polygon-edge regenesis --target-path ./trie_new --stateRoot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 --source-path ./test-chain-1/trie - -[Trie copy SUCCESS] - -``` - -5) remove old chain data -```bash -rm -rf test-chain-* -``` -6) create new validators -```bash -./polygon-edge polybft-secrets --insecure --data-dir test-chain- --num 4 - -[WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] - -[SECRETS INIT] -Public key (address) = 0x467CaA6185461E4c518597dCE7DE497Fb98a5680 -BLS Public key = 197059fdc3a78bd4001d802481c5ff1d84870c0b37aef851c83522323bd80f6429751ddae63cf38d180a8d45a5b4bf5519f380d60d6eedf9ccd22c3f95fc5e3a1193155af6ff3ab9e2aea5beab3f52e5e364d2cb410d6108c92f9a8375aac73110b8526407691c7e92e5cfab984e9011202b0606dc2be942808554b848cce67b -Node ID = 16Uiu2HAmTN2YAviWyyG4A56Zz8gsVJhmksdojymS4pk54SZqVbGV - -[WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] - -[SECRETS INIT] -Public key (address) = 0x33177bBAebcB20F8545864a83b9b6EE334e4f94D -BLS Public key = 12d82d172646703d298453cef6f4415ceab2052267d9ec300fd4742fa46fd8db0168b5e98372ae3efd52d647f9b356043163fc4f76182f1ef685faf5e53b1dba15b7d0d9cb9b7868592e02179255775618dbacafd384cffba95b647a5d84de9a27995bb8cc0766194f370ad5b274d1a53b9b8ab21a3dee2f4ee4f177f63fb1f0 -Node ID = 16Uiu2HAkvtXkr1Hsct3UGn19ULNb7jgzPvEPu6Fpdakco8P45648 - -[WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] - -[SECRETS INIT] -Public key (address) = 0xf308dF858dA25c2e40485FfA2c037D98105FD254 -BLS Public key = 220efa87e71744f44e286230cf4ac95a419abdd6d33d1a578fee21387b841fa32184dd132c077adb8f46db0eb66333672e36b5f363778030475672defce0b5622bb0974424dd7babfdf722fe9eab75ab6e5e34e2ecfcea89420f757bf8adfeb7020f0f961ca946cdb2dde40413c5c0d48aa9f13182ec35b58c4052de466c0e25 -Node ID = 16Uiu2HAmJqYRtWGbepPjQMgWfXnFEkXuX4GKH8AdD1voTwHpKuFa - -[WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] - -[SECRETS INIT] -Public key (address) = 0x7eC6b7fc98D988472AD1AC0cFcaC6DA993d865B0 -BLS Public key = 2b8188f4bc99a19d5476fc97d14e17231cfb80b205a9fc45261725edefb0195209d972e9c1ad7d3c52b8fa129637738a88203c92fe8aa70fd0998d00f6251cb403ee077ddb4192fac270fe321468fe209308ea7597288e2505ed819f551ed00510c61f3da60f6a83d6017cbaeb7590c44bd354415178bbb160701b12a72a35a6 -Node ID = 16Uiu2HAmEuYYyzQKpyVr2HVCG8Gqx5e5DLCi8LWY4TkFYvHYcWAq - -``` - -7) generate genesis manifest -```bash -./polygon-edge manifest -``` - -8) generate genesis file -```bash -./polygon-edge genesis --consensus polybft --validator-set-size=4 --bridge-json-rpc http://127.0.0.1:8545 \ ---block-gas-limit 10000000 \ ---epoch-size 10 --trieroot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 - -[GENESIS SUCCESS] -**** POLYBFT CONSENSUS PROTOCOL IS IN EXPERIMENTAL PHASE AND IS NOT FULLY PRODUCTION READY. YOU ARE USING IT AT YOUR OWN RISK. **** -Genesis written to ./genesis.json - -``` - -9) Try to start a new v0.7 chain -```bash - ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG & -wait - -[1] 2615 -[2] 2616 -[3] 2617 -[4] 2618 -2023-03-15T11:02:25.149+0400 [INFO] polygon.server: Data dir: path=./test-chain-1 -2023-03-15T11:02:25.149+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:02:25.233+0400 [INFO] polygon.server: Data dir: path=./test-chain-3 -2023-03-15T11:02:25.251+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -invalid initial state root -[1] exit 1 ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json :10000 -2023-03-15T11:02:25.299+0400 [INFO] polygon.server: Data dir: path=./test-chain-2 -2023-03-15T11:02:25.302+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:02:25.396+0400 [INFO] polygon.server: Data dir: path=./test-chain-4 -2023-03-15T11:02:25.413+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -invalid initial state root -[3] - exit 1 ./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json :30000 -invalid initial state root -[2] - exit 1 ./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json :20000 -invalid initial state root -[4] + exit 1 ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json :40000 -``` - -It fails, because we havent provided trie database with correct state trie. - -10) Copy snapshot trie to our data directory -```bash -rm -rf ./test-chain-1/trie -rm -rf ./test-chain-2/trie -rm -rf ./test-chain-3/trie -rm -rf ./test-chain-4/trie -cp -fR ./trie_new/ ./test-chain-1/trie/ -cp -fR ./trie_new/ ./test-chain-2/trie/ -cp -fR ./trie_new/ ./test-chain-3/trie/ -cp -fR ./trie_new/ ./test-chain-4/trie/ -``` - -11) run chain again -```bash - ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG & -./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG & -wait - -[1] 2721 -[2] 2722 -[3] 2723 -[4] 2724 -2023-03-15T11:09:41.481+0400 [INFO] polygon.server: Data dir: path=./test-chain-2 -2023-03-15T11:09:41.481+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:09:41.597+0400 [INFO] polygon.server: Data dir: path=./test-chain-1 -2023-03-15T11:09:41.597+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:09:41.609+0400 [WARN] polygon: Initial state root checked and correct -2023-03-15T11:09:41.661+0400 [INFO] polygon.server: Data dir: path=./test-chain-4 -2023-03-15T11:09:41.661+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:09:41.725+0400 [INFO] polygon.server: Data dir: path=./test-chain-3 -2023-03-15T11:09:41.725+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. -2023-03-15T11:09:41.844+0400 [INFO] polygon.blockchain: genesis: hash=0x627b70a8abc294324808d9820015faa5e0616afca5fdc75528b03b703a461acd -2023-03-15T11:09:41.844+0400 [INFO] polygon.server.polybft: initializing polybft... -2023-03-15T11:09:41.951+0400 [WARN] polygon: Initial state root checked and correct -2023-03-15T11:09:42.101+0400 [WARN] polygon: Initial state root checked and correct -2023-03-15T11:09:42.254+0400 [WARN] polygon: Initial state root checked and correct -2023-03-15T11:09:42.445+0400 [INFO] polygon.blockchain: genesis: hash=0x627b70a8abc294324808d9820015faa5e0616afca5fdc75528b03b703a461acd -2023-03-15T11:09:42.445+0400 [INFO] polygon.server.polybft: initializing polybft... -2023-03-15T11:09:42.462+0400 [INFO] polygon.server.polybft.consensus_runtime: restartEpoch: block number=0 epoch=1 validators=4 firstBlockInEpoch=1 -... -``` - -12) check that balance of account on v0.6 is not 0 -```bash - curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002 - -{"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"}% -``` \ No newline at end of file +# Regenesis procedure + +This document outlines step necessary to perform a regenesis data migration. + +## Steps + +1. Create cluster + + ```bash + scripts/cluster ibft + ``` + +2. Check balance + + ```bash + curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002 + + {"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"} + ``` + +3. Get trie root + + ```bash + ./polygon-edge regenesis getroot --rpc "http://localhost:10002" + + [Trie copy SUCCESS] + state root 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 for block 38 + ``` + +4. Make trie snapshot + + ```bash + ./polygon-edge regenesis --target-path ./trie_new --stateRoot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 --source-path ./test-chain-1/trie + + [Trie copy SUCCESS] + + ``` + +5. Remove old chain data + + ```bash + rm -rf test-chain-* + ``` + +6. Create new validators + + ```bash + ./polygon-edge polybft-secrets --insecure --data-dir test-chain- --num 4 + + [WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] + + [SECRETS INIT] + Public key (address. = 0x467CaA6185461E4c518597dCE7DE497Fb98a5680 + BLS Public key = 197059fdc3a78bd4001d802481c5ff1d84870c0b37aef851c83522323bd80f6429751ddae63cf38d180a8d45a5b4bf5519f380d60d6eedf9ccd22c3f95fc5e3a1193155af6ff3ab9e2aea5beab3f52e5e364d2cb410d6108c92f9a8375aac73110b8526407691c7e92e5cfab984e9011202b0606dc2be942808554b848cce67b + Node ID = 16Uiu2HAmTN2YAviWyyG4A56Zz8gsVJhmksdojymS4pk54SZqVbGV + + [WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] + + [SECRETS INIT] + Public key (address. = 0x33177bBAebcB20F8545864a83b9b6EE334e4f94D + BLS Public key = 12d82d172646703d298453cef6f4415ceab2052267d9ec300fd4742fa46fd8db0168b5e98372ae3efd52d647f9b356043163fc4f76182f1ef685faf5e53b1dba15b7d0d9cb9b7868592e02179255775618dbacafd384cffba95b647a5d84de9a27995bb8cc0766194f370ad5b274d1a53b9b8ab21a3dee2f4ee4f177f63fb1f0 + Node ID = 16Uiu2HAkvtXkr1Hsct3UGn19ULNb7jgzPvEPu6Fpdakco8P45648 + + [WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] + + [SECRETS INIT] + Public key (address. = 0xf308dF858dA25c2e40485FfA2c037D98105FD254 + BLS Public key = 220efa87e71744f44e286230cf4ac95a419abdd6d33d1a578fee21387b841fa32184dd132c077adb8f46db0eb66333672e36b5f363778030475672defce0b5622bb0974424dd7babfdf722fe9eab75ab6e5e34e2ecfcea89420f757bf8adfeb7020f0f961ca946cdb2dde40413c5c0d48aa9f13182ec35b58c4052de466c0e25 + Node ID = 16Uiu2HAmJqYRtWGbepPjQMgWfXnFEkXuX4GKH8AdD1voTwHpKuFa + + [WARNING: INSECURE LOCAL SECRETS - SHOULD NOT BE RUN IN PRODUCTION] + + [SECRETS INIT] + Public key (address. = 0x7eC6b7fc98D988472AD1AC0cFcaC6DA993d865B0 + BLS Public key = 2b8188f4bc99a19d5476fc97d14e17231cfb80b205a9fc45261725edefb0195209d972e9c1ad7d3c52b8fa129637738a88203c92fe8aa70fd0998d00f6251cb403ee077ddb4192fac270fe321468fe209308ea7597288e2505ed819f551ed00510c61f3da60f6a83d6017cbaeb7590c44bd354415178bbb160701b12a72a35a6 + Node ID = 16Uiu2HAmEuYYyzQKpyVr2HVCG8Gqx5e5DLCi8LWY4TkFYvHYcWAq + + ``` + +7. Generate genesis file + + ```bash + ./polygon-edge genesis --consensus polybft \ + --block-gas-limit 10000000 \ + --epoch-size 10 --trieroot 0xf5ef1a28c82226effb90f4465180ec3469226747818579673f4be929f1cd8663 + + [GENESIS SUCCESS] + **** POLYBFT CONSENSUS PROTOCOL IS IN EXPERIMENTAL PHASE AND IS NOT FULLY PRODUCTION READY. YOU ARE USING IT AT YOUR OWN RISK. **** + Genesis written to ./genesis.json + + ``` + +8. Try to start a new v0.7 chain + + ```bash + ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG & + wait + + [1] 2615 + [2] 2616 + [3] 2617 + [4] 2618 + 2023-03-15T11:02:25.149+0400 [INFO] polygon.server: Data dir: path=./test-chain-1 + 2023-03-15T11:02:25.149+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:02:25.233+0400 [INFO] polygon.server: Data dir: path=./test-chain-3 + 2023-03-15T11:02:25.251+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + invalid initial state root + [1] exit 1 ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json :10000 + 2023-03-15T11:02:25.299+0400 [INFO] polygon.server: Data dir: path=./test-chain-2 + 2023-03-15T11:02:25.302+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:02:25.396+0400 [INFO] polygon.server: Data dir: path=./test-chain-4 + 2023-03-15T11:02:25.413+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + invalid initial state root + [3] - exit 1 ./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json :30000 + invalid initial state root + [2] - exit 1 ./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json :20000 + invalid initial state root + [4] + exit 1 ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json :40000 + ``` + + It fails, because we havent provided trie database with correct state trie. + +9. Copy snapshot trie to our data directory + + ```bash + rm -rf ./test-chain-1/trie + rm -rf ./test-chain-2/trie + rm -rf ./test-chain-3/trie + rm -rf ./test-chain-4/trie + cp -fR ./trie_new/ ./test-chain-1/trie/ + cp -fR ./trie_new/ ./test-chain-2/trie/ + cp -fR ./trie_new/ ./test-chain-3/trie/ + cp -fR ./trie_new/ ./test-chain-4/trie/ + ``` + +10. Run chain again + + ```bash + ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :20000 --libp2p :30302 --jsonrpc :20002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :30000 --libp2p :30303 --jsonrpc :30002 --seal --log-level DEBUG & + ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 --seal --log-level DEBUG & + wait + + [1] 2721 + [2] 2722 + [3] 2723 + [4] 2724 + 2023-03-15T11:09:41.481+0400 [INFO] polygon.server: Data dir: path=./test-chain-2 + 2023-03-15T11:09:41.481+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:09:41.597+0400 [INFO] polygon.server: Data dir: path=./test-chain-1 + 2023-03-15T11:09:41.597+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:09:41.609+0400 [WARN] polygon: Initial state root checked and correct + 2023-03-15T11:09:41.661+0400 [INFO] polygon.server: Data dir: path=./test-chain-4 + 2023-03-15T11:09:41.661+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:09:41.725+0400 [INFO] polygon.server: Data dir: path=./test-chain-3 + 2023-03-15T11:09:41.725+0400 [DEBUG] polygon.server: DataDog profiler disabled, set DD_PROFILING_ENABLED env var to enable it. + 2023-03-15T11:09:41.844+0400 [INFO] polygon.blockchain: genesis: hash=0x627b70a8abc294324808d9820015faa5e0616afca5fdc75528b03b703a461acd + 2023-03-15T11:09:41.844+0400 [INFO] polygon.server.polybft: initializing polybft... + 2023-03-15T11:09:41.951+0400 [WARN] polygon: Initial state root checked and correct + 2023-03-15T11:09:42.101+0400 [WARN] polygon: Initial state root checked and correct + 2023-03-15T11:09:42.254+0400 [WARN] polygon: Initial state root checked and correct + 2023-03-15T11:09:42.445+0400 [INFO] polygon.blockchain: genesis: hash=0x627b70a8abc294324808d9820015faa5e0616afca5fdc75528b03b703a461acd + 2023-03-15T11:09:42.445+0400 [INFO] polygon.server.polybft: initializing polybft... + 2023-03-15T11:09:42.462+0400 [INFO] polygon.server.polybft.consensus_runtime: restartEpoch: block number=0 epoch=1 validators=4 firstBlockInEpoch=1 + ... + ``` + +11. Check that balance of account on v0.6 is not 0 + + ```bash + curl -s -X POST --data '{"jsonrpc":"2.0", "method":"eth_getBalance", "params":["0x85da99c8a7c2c95964c8efd687e95e632fc533d6", "latest"], "id":1}' http://localhost:10002 + + {"jsonrpc":"2.0","id":1,"result":"0x3635c9adc5dea00000"}% + ``` diff --git a/command/root/root.go b/command/root/root.go index 2641bc22d6..b52fb188cb 100644 --- a/command/root/root.go +++ b/command/root/root.go @@ -15,7 +15,6 @@ import ( "github.com/0xPolygon/polygon-edge/command/monitor" "github.com/0xPolygon/polygon-edge/command/peers" "github.com/0xPolygon/polygon-edge/command/polybft" - "github.com/0xPolygon/polygon-edge/command/polybftmanifest" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" "github.com/0xPolygon/polygon-edge/command/regenesis" "github.com/0xPolygon/polygon-edge/command/rootchain" @@ -25,7 +24,6 @@ import ( "github.com/0xPolygon/polygon-edge/command/status" "github.com/0xPolygon/polygon-edge/command/txpool" "github.com/0xPolygon/polygon-edge/command/version" - "github.com/0xPolygon/polygon-edge/command/whitelist" ) type RootCommand struct { @@ -59,12 +57,10 @@ func (rc *RootCommand) registerSubCommands() { backup.GetCommand(), genesis.GetCommand(), server.GetCommand(), - whitelist.GetCommand(), license.GetCommand(), sidecar.GetCommand(), polybftsecrets.GetCommand(), polybft.GetCommand(), - polybftmanifest.GetCommand(), bridge.GetCommand(), regenesis.GetCommand(), ) diff --git a/command/rootchain/README.md b/command/rootchain/README.md index 446e979af5..7e6b2ab8b4 100644 --- a/command/rootchain/README.md +++ b/command/rootchain/README.md @@ -4,7 +4,7 @@ Top level command for manipulating rootchain server. ## Start rootchain server -This command starts `ethereum/client-go` container which is basically geth node. +This command starts `ethereum/client-go` container which is Geth node started in dev mode. ```bash $ polygon-edge rootchain server @@ -17,7 +17,9 @@ This command funds the initialized accounts via `polygon-edge polybft-secrets` c ```bash $ polygon-edge rootchain fund --data-dir data-dir- --num 2 ``` -Or + +or + ```bash $ polygon-edge rootchain fund --data-dir data-dir-1 ``` @@ -27,10 +29,12 @@ $ polygon-edge rootchain fund --data-dir data-dir-1 This command deploys and initializes rootchain contracts. Transactions are being sent to given `--json-rpc` endpoint and are signed by private key provided by `--adminKey` flag. ```bash -$ polygon-edge rootchain init-contracts - --manifest - --deployer-key +$ polygon-edge rootchain deploy \ + --genesis \ + --deployer-key \ + --stake-manager \ + --stake-token \ --json-rpc ``` -**Note:** In case `test` flag is provided, it engages test mode, which uses predefined test account private key to send transactions to the rootchain. \ No newline at end of file +**Note:** In case `test` flag is provided, it engages test mode, which uses predefined test account private key to send transactions to the rootchain. diff --git a/command/rootchain/deploy/deploy.go b/command/rootchain/deploy/deploy.go new file mode 100644 index 0000000000..8f931815d6 --- /dev/null +++ b/command/rootchain/deploy/deploy.go @@ -0,0 +1,687 @@ +package deploy + +import ( + "context" + "errors" + "fmt" + + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/jsonrpc" + "golang.org/x/sync/errgroup" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/command" + cmdHelper "github.com/0xPolygon/polygon-edge/command/helper" + "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" + bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" +) + +const ( + contractsDeploymentTitle = "[ROOTCHAIN - CONTRACTS DEPLOYMENT]" + + stateSenderName = "StateSender" + checkpointManagerName = "CheckpointManager" + blsName = "BLS" + bn256G2Name = "BN256G2" + exitHelperName = "ExitHelper" + rootERC20PredicateName = "RootERC20Predicate" + childERC20MintablePredicateName = "ChildERC20MintablePredicate" + rootERC20Name = "RootERC20" + erc20TemplateName = "ERC20Template" + rootERC721PredicateName = "RootERC721Predicate" + childERC721MintablePredicateName = "ChildERC721MintablePredicate" + erc721TemplateName = "ERC721Template" + rootERC1155PredicateName = "RootERC1155Predicate" + childERC1155MintablePredicateName = "ChildERC1155MintablePredicate" + erc1155TemplateName = "ERC1155Template" + customSupernetManagerName = "CustomSupernetManager" +) + +var ( + // params are the parameters of CLI command + params deployParams + + // consensusCfg contains consensus protocol configuration parameters + consensusCfg polybft.PolyBFTConfig + + // metadataPopulatorMap maps rootchain contract names to callback + // which populates appropriate field in the RootchainMetadata + metadataPopulatorMap = map[string]func(*polybft.RootchainConfig, types.Address){ + stateSenderName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.StateSenderAddress = addr + }, + checkpointManagerName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.CheckpointManagerAddress = addr + }, + blsName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.BLSAddress = addr + }, + bn256G2Name: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.BN256G2Address = addr + }, + exitHelperName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.ExitHelperAddress = addr + }, + rootERC20PredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.RootERC20PredicateAddress = addr + }, + childERC20MintablePredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.ChildMintableERC20PredicateAddress = addr + }, + rootERC20Name: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.RootNativeERC20Address = addr + }, + erc20TemplateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.ChildERC20Address = addr + }, + rootERC721PredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.RootERC721PredicateAddress = addr + }, + childERC721MintablePredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.ChildMintableERC721PredicateAddress = addr + }, + erc721TemplateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.ChildERC721Address = addr + }, + rootERC1155PredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.RootERC1155PredicateAddress = addr + }, + childERC1155MintablePredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.ChildMintableERC1155PredicateAddress = addr + }, + erc1155TemplateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.ChildERC1155Address = addr + }, + customSupernetManagerName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { + rootchainConfig.CustomSupernetManagerAddress = addr + }, + } + + // initializersMap maps rootchain contract names to initializer function callbacks + initializersMap = map[string]func(command.OutputFormatter, txrelayer.TxRelayer, + *polybft.RootchainConfig, ethgo.Key) error{ + customSupernetManagerName: func(fmt command.OutputFormatter, + relayer txrelayer.TxRelayer, + config *polybft.RootchainConfig, + key ethgo.Key) error { + initParams := &contractsapi.InitializeCustomSupernetManagerFn{ + NewStakeManager: config.StakeManagerAddress, + NewBls: config.BLSAddress, + NewStateSender: config.StateSenderAddress, + NewMatic: types.StringToAddress(params.stakeTokenAddr), + NewChildValidatorSet: contracts.ValidatorSetContract, + NewExitHelper: config.ExitHelperAddress, + NewDomain: bls.DomainValidatorSetString, + } + + return initContract(fmt, relayer, initParams, + config.CustomSupernetManagerAddress, customSupernetManagerName, key) + }, + exitHelperName: func(fmt command.OutputFormatter, + relayer txrelayer.TxRelayer, + config *polybft.RootchainConfig, + key ethgo.Key) error { + inputParams := &contractsapi.InitializeExitHelperFn{ + NewCheckpointManager: config.CheckpointManagerAddress, + } + + return initContract(fmt, relayer, inputParams, config.ExitHelperAddress, exitHelperName, key) + }, + rootERC20PredicateName: func(fmt command.OutputFormatter, + relayer txrelayer.TxRelayer, + config *polybft.RootchainConfig, + key ethgo.Key) error { + // map root native token on rootchain only if it is non-mintable on a childchain + nativeTokenRootAddr := types.ZeroAddress + if !consensusCfg.NativeTokenConfig.IsMintable { + nativeTokenRootAddr = config.RootNativeERC20Address + } + + inputParams := &contractsapi.InitializeRootERC20PredicateFn{ + NewStateSender: config.StateSenderAddress, + NewExitHelper: config.ExitHelperAddress, + NewChildERC20Predicate: contracts.ChildERC20PredicateContract, + NewChildTokenTemplate: contracts.ChildERC20Contract, + NativeTokenRootAddress: nativeTokenRootAddr, + } + + return initContract(fmt, relayer, inputParams, + config.RootERC20PredicateAddress, rootERC20PredicateName, key) + }, + childERC20MintablePredicateName: func(fmt command.OutputFormatter, + relayer txrelayer.TxRelayer, + config *polybft.RootchainConfig, + key ethgo.Key) error { + initParams := &contractsapi.InitializeChildMintableERC20PredicateFn{ + NewStateSender: config.StateSenderAddress, + NewExitHelper: config.ExitHelperAddress, + NewRootERC20Predicate: contracts.RootMintableERC20PredicateContract, + NewChildTokenTemplate: config.ChildERC20Address, + } + + return initContract(fmt, relayer, initParams, + config.ChildMintableERC20PredicateAddress, childERC20MintablePredicateName, key) + }, + rootERC721PredicateName: func(fmt command.OutputFormatter, + relayer txrelayer.TxRelayer, + config *polybft.RootchainConfig, + key ethgo.Key) error { + initParams := &contractsapi.InitializeRootERC721PredicateFn{ + NewStateSender: config.StateSenderAddress, + NewExitHelper: config.ExitHelperAddress, + NewChildERC721Predicate: contracts.ChildERC721PredicateContract, + NewChildTokenTemplate: contracts.ChildERC721Contract, + } + + return initContract(fmt, relayer, initParams, + config.RootERC721PredicateAddress, rootERC721PredicateName, key) + }, + childERC721MintablePredicateName: func(fmt command.OutputFormatter, + relayer txrelayer.TxRelayer, + config *polybft.RootchainConfig, + key ethgo.Key) error { + initParams := &contractsapi.InitializeChildMintableERC721PredicateFn{ + NewStateSender: config.StateSenderAddress, + NewExitHelper: config.ExitHelperAddress, + NewRootERC721Predicate: contracts.RootMintableERC721PredicateContract, + NewChildTokenTemplate: config.ChildERC721Address, + } + + return initContract(fmt, relayer, initParams, + config.ChildMintableERC721PredicateAddress, childERC721MintablePredicateName, key) + }, + rootERC1155PredicateName: func(fmt command.OutputFormatter, + relayer txrelayer.TxRelayer, + config *polybft.RootchainConfig, + key ethgo.Key) error { + initParams := &contractsapi.InitializeRootERC1155PredicateFn{ + NewStateSender: config.StateSenderAddress, + NewExitHelper: config.ExitHelperAddress, + NewChildERC1155Predicate: contracts.ChildERC1155PredicateContract, + NewChildTokenTemplate: contracts.ChildERC1155Contract, + } + + return initContract(fmt, relayer, initParams, + config.RootERC1155PredicateAddress, rootERC1155PredicateName, key) + }, + childERC1155MintablePredicateName: func(fmt command.OutputFormatter, + relayer txrelayer.TxRelayer, + config *polybft.RootchainConfig, + key ethgo.Key) error { + initParams := &contractsapi.InitializeChildMintableERC1155PredicateFn{ + NewStateSender: config.StateSenderAddress, + NewExitHelper: config.ExitHelperAddress, + NewRootERC1155Predicate: contracts.RootMintableERC1155PredicateContract, + NewChildTokenTemplate: config.ChildERC1155Address, + } + + return initContract(fmt, relayer, initParams, + config.ChildMintableERC1155PredicateAddress, childERC1155MintablePredicateName, key) + }, + } +) + +// GetCommand returns the rootchain deploy command +func GetCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "deploy", + Short: "Deploys and initializes required smart contracts on the rootchain", + PreRunE: preRunCommand, + Run: runCommand, + } + + cmd.Flags().StringVar( + ¶ms.genesisPath, + helper.GenesisPathFlag, + helper.DefaultGenesisPath, + helper.GenesisPathFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.deployerKey, + deployerKeyFlag, + "", + "hex-encoded private key of the account which deploys rootchain contracts", + ) + + cmd.Flags().StringVar( + ¶ms.jsonRPCAddress, + jsonRPCFlag, + txrelayer.DefaultRPCAddress, + "the JSON RPC rootchain IP address", + ) + + cmd.Flags().StringVar( + ¶ms.rootERC20TokenAddr, + erc20AddrFlag, + "", + "existing root chain root native token address", + ) + + cmd.Flags().BoolVar( + ¶ms.isTestMode, + helper.TestModeFlag, + false, + "test indicates whether rootchain contracts deployer is hardcoded test account"+ + " (otherwise provided secrets are used to resolve deployer account)", + ) + + cmd.Flags().StringVar( + ¶ms.stakeTokenAddr, + helper.StakeTokenFlag, + "", + helper.StakeTokenFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.stakeManagerAddr, + helper.StakeManagerFlag, + "", + helper.StakeManagerFlagDesc, + ) + + cmd.MarkFlagsMutuallyExclusive(helper.TestModeFlag, deployerKeyFlag) + _ = cmd.MarkFlagRequired(helper.StakeManagerFlag) + _ = cmd.MarkFlagRequired(helper.StakeTokenFlag) + + return cmd +} + +func preRunCommand(_ *cobra.Command, _ []string) error { + return params.validateFlags() +} + +func runCommand(cmd *cobra.Command, _ []string) { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + outputter.WriteCommandResult(&helper.MessageResult{ + Message: fmt.Sprintf("%s started... Rootchain JSON RPC address %s.", contractsDeploymentTitle, params.jsonRPCAddress), + }) + + chainConfig, err := chain.ImportFromFile(params.genesisPath) + if err != nil { + outputter.SetError(fmt.Errorf("failed to read chain configuration: %w", err)) + + return + } + + client, err := jsonrpc.NewClient(params.jsonRPCAddress) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize JSON RPC client for provided IP address: %s: %w", + params.jsonRPCAddress, err)) + + return + } + + if consensusCfg.Bridge != nil { + code, err := client.Eth().GetCode(ethgo.Address(consensusCfg.Bridge.StateSenderAddr), ethgo.Latest) + if err != nil { + outputter.SetError(fmt.Errorf("failed to check if rootchain contracts are deployed: %w", err)) + + return + } else if code != "0x" { + outputter.SetCommandResult(&helper.MessageResult{ + Message: fmt.Sprintf("%s contracts are already deployed. Aborting.", contractsDeploymentTitle), + }) + + return + } + } + + rootchainCfg, supernetID, err := deployContracts(outputter, client, + chainConfig.Params.ChainID, consensusCfg.InitialValidatorSet, cmd.Context()) + if err != nil { + outputter.SetError(fmt.Errorf("failed to deploy rootchain contracts: %w", err)) + + return + } + + // populate bridge configuration + bridgeConfig := rootchainCfg.ToBridgeConfig() + if consensusCfg.Bridge != nil { + // only true if stake-manager-deploy command was executed + // users can still deploy stake manager manually + // only used for e2e tests + bridgeConfig.StakeTokenAddr = consensusCfg.Bridge.StakeTokenAddr + } + + consensusCfg.Bridge = bridgeConfig + + // set event tracker start blocks for rootchain contract(s) of interest + blockNum, err := client.Eth().BlockNumber() + if err != nil { + outputter.SetError(fmt.Errorf("failed to query rootchain latest block number: %w", err)) + + return + } + + consensusCfg.Bridge.EventTrackerStartBlocks = map[types.Address]uint64{ + rootchainCfg.StateSenderAddress: blockNum, + } + consensusCfg.SupernetID = supernetID + + // write updated consensus configuration + chainConfig.Params.Engine[polybft.ConsensusName] = consensusCfg + + if err := cmdHelper.WriteGenesisConfigToDisk(chainConfig, params.genesisPath); err != nil { + outputter.SetError(fmt.Errorf("failed to save chain configuration bridge data: %w", err)) + + return + } + + outputter.SetCommandResult(&helper.MessageResult{ + Message: fmt.Sprintf("%s finished. All contracts are successfully deployed and initialized.", + contractsDeploymentTitle), + }) +} + +// deployContracts deploys and initializes rootchain smart contracts +func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, chainID int64, + initialValidators []*validator.GenesisValidator, cmdCtx context.Context) (*polybft.RootchainConfig, int64, error) { + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(client), txrelayer.WithWriter(outputter)) + if err != nil { + return nil, 0, fmt.Errorf("failed to initialize tx relayer: %w", err) + } + + deployerKey, err := helper.DecodePrivateKey(params.deployerKey) + if err != nil { + return nil, 0, fmt.Errorf("failed to initialize deployer key: %w", err) + } + + if params.isTestMode { + deployerAddr := deployerKey.Address() + txn := ðgo.Transaction{To: &deployerAddr, Value: ethgo.Ether(1)} + + if _, err = txRelayer.SendTransactionLocal(txn); err != nil { + return nil, 0, err + } + } + + type contractInfo struct { + name string + artifact *artifact.Artifact + } + + rootchainConfig := &polybft.RootchainConfig{ + JSONRPCAddr: params.jsonRPCAddress, + // update stake manager address in genesis in case if stake manager was deployed manually + StakeManagerAddress: types.StringToAddress(params.stakeManagerAddr), + } + + tokenContracts := []*contractInfo{} + + // deploy root ERC20 token only if non-mintable native token flavor is used on a child chain + if !consensusCfg.NativeTokenConfig.IsMintable { + if params.rootERC20TokenAddr != "" { + // use existing root chain ERC20 token + if err := populateExistingTokenAddr(client.Eth(), + params.rootERC20TokenAddr, rootERC20Name, rootchainConfig); err != nil { + return nil, 0, err + } + } else { + // deploy MockERC20 as a root chain root native token + tokenContracts = append(tokenContracts, + &contractInfo{name: rootERC20Name, artifact: contractsapi.RootERC20}) + } + } + + allContracts := []*contractInfo{ + { + name: stateSenderName, + artifact: contractsapi.StateSender, + }, + { + name: checkpointManagerName, + artifact: contractsapi.CheckpointManager, + }, + { + name: blsName, + artifact: contractsapi.BLS, + }, + { + name: bn256G2Name, + artifact: contractsapi.BLS256, + }, + { + name: exitHelperName, + artifact: contractsapi.ExitHelper, + }, + { + name: rootERC20PredicateName, + artifact: contractsapi.RootERC20Predicate, + }, + { + name: childERC20MintablePredicateName, + artifact: contractsapi.ChildMintableERC20Predicate, + }, + { + name: erc20TemplateName, + artifact: contractsapi.ChildERC20, + }, + { + name: rootERC721PredicateName, + artifact: contractsapi.RootERC721Predicate, + }, + { + name: childERC721MintablePredicateName, + artifact: contractsapi.ChildMintableERC721Predicate, + }, + { + name: erc721TemplateName, + artifact: contractsapi.ChildERC721, + }, + { + name: rootERC1155PredicateName, + artifact: contractsapi.RootERC1155Predicate, + }, + { + name: childERC1155MintablePredicateName, + artifact: contractsapi.ChildMintableERC1155Predicate, + }, + { + name: erc1155TemplateName, + artifact: contractsapi.ChildERC1155, + }, + { + name: customSupernetManagerName, + artifact: contractsapi.CustomSupernetManager, + }, + } + + allContracts = append(tokenContracts, allContracts...) + + g, ctx := errgroup.WithContext(cmdCtx) + results := make([]*deployContractResult, len(allContracts)) + + for i, contract := range allContracts { + i := i + contract := contract + + g.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + txn := ðgo.Transaction{ + To: nil, // contract deployment + Input: contract.artifact.Bytecode, + } + + receipt, err := txRelayer.SendTransaction(txn, deployerKey) + if err != nil { + return fmt.Errorf("failed sending %s contract deploy transaction: %w", contract.name, err) + } + + if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) { + return fmt.Errorf("deployment of %s contract failed", contract.name) + } + + results[i] = newDeployContractsResult(contract.name, + types.Address(receipt.ContractAddress), + receipt.TransactionHash, + receipt.GasUsed) + + return nil + } + }) + } + + if err := g.Wait(); err != nil { + _, _ = outputter.Write([]byte("[ROOTCHAIN - DEPLOY] Successfully deployed the following contracts\n")) + + for _, result := range results { + if result != nil { + // In case an error happened, some of the indices may not be populated. + // Filter those out. + outputter.WriteCommandResult(result) + } + } + + return nil, 0, err + } + + for _, result := range results { + populatorFn, ok := metadataPopulatorMap[result.Name] + if !ok { + return nil, 0, fmt.Errorf("rootchain metadata populator not registered for contract '%s'", result.Name) + } + + populatorFn(rootchainConfig, result.Address) + + outputter.WriteCommandResult(result) + } + + g, ctx = errgroup.WithContext(cmdCtx) + + for _, contract := range allContracts { + contract := contract + + initializer, exists := initializersMap[contract.name] + if !exists { + continue + } + + g.Go(func() error { + select { + case <-cmdCtx.Done(): + return cmdCtx.Err() + default: + return initializer(outputter, txRelayer, rootchainConfig, deployerKey) + } + }) + } + + if err := g.Wait(); err != nil { + return nil, 0, err + } + + // register supernets manager on stake manager + supernetID, err := registerChainOnStakeManager(txRelayer, rootchainConfig, deployerKey) + if err != nil { + return nil, 0, err + } + + return rootchainConfig, supernetID, nil +} + +// populateExistingTokenAddr checks whether given token is deployed on the provided address. +// If it is, then its address is set to the rootchain config, otherwise an error is returned +func populateExistingTokenAddr(eth *jsonrpc.Eth, tokenAddr, tokenName string, + rootchainCfg *polybft.RootchainConfig) error { + addr := types.StringToAddress(tokenAddr) + + code, err := eth.GetCode(ethgo.Address(addr), ethgo.Latest) + if err != nil { + return fmt.Errorf("failed to check is %s token deployed: %w", tokenName, err) + } else if code == "0x" { + return fmt.Errorf("%s token is not deployed on provided address %s", tokenName, tokenAddr) + } + + populatorFn, ok := metadataPopulatorMap[tokenName] + if !ok { + return fmt.Errorf("root chain metadata populator not registered for contract '%s'", tokenName) + } + + populatorFn(rootchainCfg, addr) + + return nil +} + +// registerChainOnStakeManager registers child chain and its supernet manager on rootchain +func registerChainOnStakeManager(txRelayer txrelayer.TxRelayer, + rootchainCfg *polybft.RootchainConfig, deployerKey ethgo.Key) (int64, error) { + registerChainFn := &contractsapi.RegisterChildChainStakeManagerFn{ + Manager: rootchainCfg.CustomSupernetManagerAddress, + } + + encoded, err := registerChainFn.EncodeAbi() + if err != nil { + return 0, fmt.Errorf("failed to encode parameters for registering child chain on supernets. error: %w", err) + } + + receipt, err := helper.SendTransaction(txRelayer, ethgo.Address(rootchainCfg.StakeManagerAddress), + encoded, checkpointManagerName, deployerKey) + if err != nil { + return 0, err + } + + var ( + childChainRegisteredEvent contractsapi.ChildManagerRegisteredEvent + found bool + supernetID int64 + ) + + for _, log := range receipt.Logs { + doesMatch, err := childChainRegisteredEvent.ParseLog(log) + if err != nil { + return 0, err + } + + if !doesMatch { + continue + } + + supernetID = childChainRegisteredEvent.ID.Int64() + found = true + + break + } + + if !found { + return 0, errors.New("could not find a log that child chain was registered on stake manager") + } + + return supernetID, nil +} + +// initContract initializes arbitrary contract with given parameters deployed on a given address +func initContract(cmdOutput command.OutputFormatter, txRelayer txrelayer.TxRelayer, + initInputFn contractsapi.StateTransactionInput, contractAddr types.Address, + contractName string, deployerKey ethgo.Key) error { + input, err := initInputFn.EncodeAbi() + if err != nil { + return fmt.Errorf("failed to encode initialization params for %s.initialize. error: %w", + contractName, err) + } + + if _, err := helper.SendTransaction(txRelayer, ethgo.Address(contractAddr), + input, contractName, deployerKey); err != nil { + return err + } + + cmdOutput.WriteCommandResult( + &helper.MessageResult{ + Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, contractName), + }) + + return nil +} diff --git a/command/rootchain/deploy/deploy_test.go b/command/rootchain/deploy/deploy_test.go new file mode 100644 index 0000000000..4381b8a476 --- /dev/null +++ b/command/rootchain/deploy/deploy_test.go @@ -0,0 +1,66 @@ +package deploy + +import ( + "context" + "os" + "testing" + + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/jsonrpc" + "github.com/umbracle/ethgo/testutil" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/types" +) + +func TestDeployContracts_NoPanics(t *testing.T) { + t.Parallel() + + server := testutil.DeployTestServer(t, nil) + t.Cleanup(func() { + if err := os.RemoveAll(params.genesisPath); err != nil { + t.Fatal(err) + } + }) + + client, err := jsonrpc.NewClient(server.HTTPAddr()) + require.NoError(t, err) + + testKey, err := helper.DecodePrivateKey("") + require.NoError(t, err) + + receipt, err := server.Fund(testKey.Address()) + require.NoError(t, err) + require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) + + txn := ðgo.Transaction{ + To: nil, // contract deployment + Input: contractsapi.StakeManager.Bytecode, + } + + receipt, err = server.SendTxn(txn) + require.NoError(t, err) + require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) + + outputter := command.InitializeOutputter(GetCommand()) + params.stakeManagerAddr = receipt.ContractAddress.String() + params.stakeTokenAddr = types.StringToAddress("0x123456789").String() + consensusCfg = polybft.PolyBFTConfig{ + NativeTokenConfig: &polybft.TokenConfig{ + Name: "Test", + Symbol: "TST", + Decimals: 18, + IsMintable: false, + }, + } + + require.NotPanics(t, func() { + _, _, err = deployContracts(outputter, client, 1, []*validator.GenesisValidator{}, context.Background()) + }) + require.NoError(t, err) +} diff --git a/command/rootchain/deploy/params.go b/command/rootchain/deploy/params.go new file mode 100644 index 0000000000..45593b32aa --- /dev/null +++ b/command/rootchain/deploy/params.go @@ -0,0 +1,53 @@ +package deploy + +import ( + "errors" + "fmt" + "os" + + "github.com/0xPolygon/polygon-edge/consensus/polybft" +) + +const ( + deployerKeyFlag = "deployer-key" + jsonRPCFlag = "json-rpc" + erc20AddrFlag = "erc20-token" +) + +type deployParams struct { + genesisPath string + deployerKey string + jsonRPCAddress string + stakeTokenAddr string + rootERC20TokenAddr string + stakeManagerAddr string + isTestMode bool +} + +func (ip *deployParams) validateFlags() error { + var err error + + if _, err = os.Stat(ip.genesisPath); err != nil { + return fmt.Errorf("provided genesis path '%s' is invalid. Error: %w ", ip.genesisPath, err) + } + + consensusCfg, err = polybft.LoadPolyBFTConfig(ip.genesisPath) + if err != nil { + return err + } + + if consensusCfg.NativeTokenConfig == nil { + return errors.New("native token configuration is undefined") + } + + // when using mintable native token, child native token on root chain gets mapped automatically + if consensusCfg.NativeTokenConfig.IsMintable && ip.rootERC20TokenAddr != "" { + return errors.New("if child chain native token is mintable, root native token must not pre-exist on root chain") + } + + if params.stakeTokenAddr == "" { + return errors.New("stake token address is not provided") + } + + return nil +} diff --git a/command/rootchain/initcontracts/result.go b/command/rootchain/deploy/result.go similarity index 69% rename from command/rootchain/initcontracts/result.go rename to command/rootchain/deploy/result.go index b268b571dd..4fcdc040ab 100644 --- a/command/rootchain/initcontracts/result.go +++ b/command/rootchain/deploy/result.go @@ -1,4 +1,4 @@ -package initcontracts +package deploy import ( "bytes" @@ -13,13 +13,17 @@ type deployContractResult struct { Name string `json:"name"` Address types.Address `json:"address"` Hash types.Hash `json:"hash"` + GasUsed uint64 `json:"gasUsed"` } -func newDeployContractsResult(name string, address types.Address, hash ethgo.Hash) *deployContractResult { +func newDeployContractsResult(name string, + address types.Address, + hash ethgo.Hash, gasUsed uint64) *deployContractResult { return &deployContractResult{ Name: name, Address: address, Hash: types.BytesToHash(hash.Bytes()), + GasUsed: gasUsed, } } @@ -28,26 +32,14 @@ func (r deployContractResult) GetOutput() string { buffer.WriteString("\n[ROOTCHAIN - DEPLOY CONTRACT]\n") - vals := make([]string, 0, 3) + vals := make([]string, 0, 4) vals = append(vals, fmt.Sprintf("Name|%s", r.Name)) vals = append(vals, fmt.Sprintf("Contract (address)|%s", r.Address)) vals = append(vals, fmt.Sprintf("Transaction (hash)|%s", r.Hash)) + vals = append(vals, fmt.Sprintf("Transaction (gas used)|%d", r.GasUsed)) buffer.WriteString(helper.FormatKV(vals)) buffer.WriteString("\n") return buffer.String() } - -type messageResult struct { - Message string `json:"message"` -} - -func (r messageResult) GetOutput() string { - var buffer bytes.Buffer - - buffer.WriteString(r.Message) - buffer.WriteString("\n") - - return buffer.String() -} diff --git a/command/rootchain/fund/fund.go b/command/rootchain/fund/fund.go index 44113dc59a..30ec7695b8 100644 --- a/command/rootchain/fund/fund.go +++ b/command/rootchain/fund/fund.go @@ -2,28 +2,28 @@ package fund import ( "fmt" - "math/big" "github.com/spf13/cobra" "github.com/umbracle/ethgo" + "golang.org/x/sync/errgroup" "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + "github.com/0xPolygon/polygon-edge/command/rootchain/helper" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" ) var ( - params fundParams - fundNumber int - jsonRPCAddress string + params fundParams ) // GetCommand returns the rootchain fund command func GetCommand() *cobra.Command { rootchainFundCmd := &cobra.Command{ Use: "fund", - Short: "Fund funds all the genesis addresses", - PreRunE: runPreRun, + Short: "Fund validator account with given tokens amount", + PreRunE: preRunCommand, Run: runCommand, } @@ -33,44 +33,50 @@ func GetCommand() *cobra.Command { } func setFlags(cmd *cobra.Command) { + cmd.Flags().StringSliceVar( + ¶ms.addresses, + addressesFlag, + nil, + "validator addresses", + ) + + cmd.Flags().StringSliceVar( + ¶ms.amounts, + amountsFlag, + nil, + "token amounts which is funded to validator on a root chain", + ) + cmd.Flags().StringVar( - ¶ms.dataDir, - dataDirFlag, - "", - "the directory for the Polygon Edge data if the local FS is used", + ¶ms.jsonRPCAddress, + jsonRPCFlag, + txrelayer.DefaultRPCAddress, + "the rootchain JSON RPC endpoint", ) cmd.Flags().StringVar( - ¶ms.configPath, - configFlag, + ¶ms.stakeTokenAddr, + helper.StakeTokenFlag, "", - "the path to the SecretsManager config file, "+ - "if omitted, the local FS secrets manager is used", + helper.StakeTokenFlagDesc, ) - cmd.Flags().IntVar( - &fundNumber, - numFlag, - 1, - "the flag indicating the number of accounts to be funded", + cmd.Flags().BoolVar( + ¶ms.mintStakeToken, + mintStakeTokenFlag, + false, + "indicates if stake token deployer should mint root tokens to given validators", ) cmd.Flags().StringVar( - &jsonRPCAddress, - jsonRPCFlag, - "http://127.0.0.1:8545", - "the JSON RPC rootchain IP address (e.g. http://127.0.0.1:8545)", + ¶ms.deployerPrivateKey, + polybftsecrets.PrivateKeyFlag, + "", + polybftsecrets.PrivateKeyFlagDesc, ) - - // Don't accept data-dir and config flags because they are related to different secrets managers. - // data-dir is about the local FS as secrets storage, config is about remote secrets manager. - cmd.MarkFlagsMutuallyExclusive(dataDirFlag, configFlag) - - // num flag should be used with data-dir flag only so it should not be used with config flag. - cmd.MarkFlagsMutuallyExclusive(numFlag, configFlag) } -func runPreRun(_ *cobra.Command, _ []string) error { +func preRunCommand(_ *cobra.Command, _ []string) error { return params.validateFlags() } @@ -78,66 +84,104 @@ func runCommand(cmd *cobra.Command, _ []string) { outputter := command.InitializeOutputter(cmd) defer outputter.WriteOutput() - paramsList := getParamsList() - resList := make(command.Results, len(paramsList)) - - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(jsonRPCAddress)) + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPCAddress)) if err != nil { outputter.SetError(fmt.Errorf("failed to initialize tx relayer: %w", err)) return } - for i, params := range paramsList { - if err := params.initSecretsManager(); err != nil { - outputter.SetError(err) - - return - } - - validatorAcc, err := params.getValidatorAccount() - if err != nil { - outputter.SetError(err) - - return - } - - fundAddr := ethgo.Address(validatorAcc) - txn := ðgo.Transaction{ - To: &fundAddr, - Value: big.NewInt(1000000000000000000), - } + deployerKey, err := helper.DecodePrivateKey(params.deployerPrivateKey) + if err != nil { + outputter.SetError(fmt.Errorf("failed to initialize deployer private key: %w", err)) - receipt, err := txRelayer.SendTransactionLocal(txn) - if err != nil { - outputter.SetError(err) + return + } - return - } + var stakeTokenAddr types.Address - resList[i] = &result{ - ValidatorAddr: validatorAcc, - TxHash: types.Hash(receipt.TransactionHash), - } + if params.mintStakeToken { + stakeTokenAddr = types.StringToAddress(params.stakeTokenAddr) } - outputter.SetCommandResult(resList) -} - -// getParamsList creates a list of initParams with num elements. -// This function basically copies the given initParams but updating dataDir by applying an index. -func getParamsList() []fundParams { - if fundNumber == 1 { - return []fundParams{params} + results := make([]command.CommandResult, len(params.addresses)) + g, ctx := errgroup.WithContext(cmd.Context()) + + for i := 0; i < len(params.addresses); i++ { + i := i + + g.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + + default: + validatorAddr := types.StringToAddress(params.addresses[i]) + fundAddr := ethgo.Address(validatorAddr) + txn := ðgo.Transaction{ + To: &fundAddr, + Value: params.amountValues[i], + } + + var receipt *ethgo.Receipt + + if params.deployerPrivateKey != "" { + receipt, err = txRelayer.SendTransaction(txn, deployerKey) + } else { + receipt, err = txRelayer.SendTransactionLocal(txn) + } + + if err != nil { + return fmt.Errorf("failed to send fund validator '%s' transaction: %w", validatorAddr, err) + } + + if receipt.Status == uint64(types.ReceiptFailed) { + return fmt.Errorf("failed to fund validator '%s'", validatorAddr) + } + + if params.mintStakeToken { + // mint tokens to validator, so he is able to send them + mintTxn, err := helper.CreateMintTxn(validatorAddr, stakeTokenAddr, params.amountValues[i]) + if err != nil { + return fmt.Errorf("failed to create mint native tokens transaction for validator '%s'. err: %w", + validatorAddr, err) + } + + receipt, err := txRelayer.SendTransaction(mintTxn, deployerKey) + if err != nil { + return fmt.Errorf("failed to send mint native tokens transaction to validator '%s'. err: %w", validatorAddr, err) + } + + if receipt.Status == uint64(types.ReceiptFailed) { + return fmt.Errorf("failed to mint native tokens to validator '%s'", validatorAddr) + } + } + + results[i] = &result{ + ValidatorAddr: validatorAddr, + TxHash: types.Hash(receipt.TransactionHash), + IsMinted: params.mintStakeToken, + } + } + + return nil + }) } - paramsList := make([]fundParams, fundNumber) - for i := 1; i <= fundNumber; i++ { - paramsList[i-1] = fundParams{ - dataDir: fmt.Sprintf("%s%d", params.dataDir, i), - configPath: params.configPath, + if err := g.Wait(); err != nil { + outputter.SetError(err) + _, _ = outputter.Write([]byte("[ROOTCHAIN FUND] Successfully funded following accounts\n")) + + for _, result := range results { + if result != nil { + // In case an error happened, some of the indices may not be populated. + // Filter those out. + outputter.SetCommandResult(result) + } } + + return } - return paramsList + outputter.SetCommandResult(command.Results(results)) } diff --git a/command/rootchain/fund/params.go b/command/rootchain/fund/params.go index 8489cf7f11..4dd10f2edd 100644 --- a/command/rootchain/fund/params.go +++ b/command/rootchain/fund/params.go @@ -2,86 +2,59 @@ package fund import ( "errors" + "math/big" - "github.com/0xPolygon/polygon-edge/secrets" - "github.com/0xPolygon/polygon-edge/secrets/helper" + cmdhelper "github.com/0xPolygon/polygon-edge/command/helper" "github.com/0xPolygon/polygon-edge/types" ) const ( - dataDirFlag = "data-dir" - configFlag = "config" - numFlag = "num" - jsonRPCFlag = "json-rpc" + addressesFlag = "addresses" + amountsFlag = "amounts" + jsonRPCFlag = "json-rpc" + mintStakeTokenFlag = "mint" ) var ( - errInvalidConfig = errors.New("invalid secrets configuration") - errInvalidParams = errors.New("no config file or data directory passed in") - errUnsupportedType = errors.New("unsupported secrets manager") + errNoAddressesProvided = errors.New("no addresses provided") + errInconsistentLength = errors.New("validator addresses and amounts must be equal length") ) type fundParams struct { - dataDir string - configPath string - - secretsManager secrets.SecretsManager - secretsConfig *secrets.SecretsManagerConfig + addresses []string + amounts []string + stakeTokenAddr string + deployerPrivateKey string + mintStakeToken bool + jsonRPCAddress string + + amountValues []*big.Int } func (fp *fundParams) validateFlags() error { - if fp.dataDir == "" && fp.configPath == "" { - return errInvalidParams + if len(fp.addresses) == 0 { + return errNoAddressesProvided } - return nil -} - -func (fp *fundParams) hasConfigPath() bool { - return fp.configPath != "" -} + if len(fp.amounts) != len(fp.addresses) { + return errInconsistentLength + } -func (fp *fundParams) initSecretsManager() error { - var err error - if fp.hasConfigPath() { - if err = fp.parseConfig(); err != nil { + for _, addr := range fp.addresses { + if err := types.IsValidAddress(addr); err != nil { return err } - - fp.secretsManager, err = helper.InitCloudSecretsManager(fp.secretsConfig) - - return err - } - - return fp.initLocalSecretsManager() -} - -func (fp *fundParams) parseConfig() error { - secretsConfig, readErr := secrets.ReadConfig(fp.configPath) - if readErr != nil { - return errInvalidConfig - } - - if !secrets.SupportedServiceManager(secretsConfig.Type) { - return errUnsupportedType } - fp.secretsConfig = secretsConfig - - return nil -} + fp.amountValues = make([]*big.Int, len(fp.amounts)) + for i, amountRaw := range fp.amounts { + amountValue, err := cmdhelper.ParseAmount(amountRaw) + if err != nil { + return err + } -func (fp *fundParams) initLocalSecretsManager() error { - local, err := helper.SetupLocalSecretsManager(fp.dataDir) - if err != nil { - return err + fp.amountValues[i] = amountValue } - fp.secretsManager = local - return nil } - -func (fp *fundParams) getValidatorAccount() (types.Address, error) { - return helper.LoadValidatorAddress(fp.secretsManager) -} diff --git a/command/rootchain/fund/result.go b/command/rootchain/fund/result.go index 608cf64907..add7a63fa5 100644 --- a/command/rootchain/fund/result.go +++ b/command/rootchain/fund/result.go @@ -11,14 +11,16 @@ import ( type result struct { ValidatorAddr types.Address `json:"address"` TxHash types.Hash `json:"tx_hash"` + IsMinted bool `json:"mint"` } func (r *result) GetOutput() string { var buffer bytes.Buffer - vals := make([]string, 0, 2) + vals := make([]string, 0, 3) vals = append(vals, fmt.Sprintf("Validator (address)|%s", r.ValidatorAddr)) vals = append(vals, fmt.Sprintf("Transaction (hash)|%s", r.TxHash)) + vals = append(vals, fmt.Sprintf("Is minted|%v", r.IsMinted)) buffer.WriteString("\n[ROOTCHAIN FUND]\n") buffer.WriteString(helper.FormatKV(vals)) diff --git a/command/rootchain/helper/metadata.go b/command/rootchain/helper/metadata.go index 257d0cacf2..442d4b7854 100644 --- a/command/rootchain/helper/metadata.go +++ b/command/rootchain/helper/metadata.go @@ -1,32 +1,67 @@ package helper import ( + "bytes" "context" - "encoding/hex" "errors" "fmt" + "math/big" + "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + polybftWallet "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" + "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" dockertypes "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/umbracle/ethgo" "github.com/umbracle/ethgo/wallet" ) +//nolint:gosec const ( - testAccountPrivKey = "aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d" - TestModeFlag = "test" + TestAccountPrivKey = "aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d" + TestModeFlag = "test" + SupernetManagerFlag = "supernet-manager" + SupernetManagerFlagDesc = "address of supernet manager contract" + StakeManagerFlag = "stake-manager" + StakeManagerFlagDesc = "address of stake manager contract" + NativeRootTokenFlag = "native-root-token" + NativeRootTokenFlagDesc = "address of native root token" + GenesisPathFlag = "genesis" + GenesisPathFlagDesc = "genesis file path, which contains chain configuration" + DefaultGenesisPath = "./genesis.json" + StakeTokenFlag = "stake-token" + StakeTokenFlagDesc = "address of ERC20 token used for staking on rootchain" ) var ( ErrRootchainNotFound = errors.New("rootchain not found") ErrRootchainPortBind = errors.New("port 8545 is not bind with localhost") errTestModeSecrets = errors.New("rootchain test mode does not imply specifying secrets parameters") - rootchainAccountKey *wallet.Key + + rootchainAccountKey *wallet.Key ) -// GetRootchainPrivateKey initializes a private key from provided raw private key -func GetRootchainPrivateKey(rawKey string) (ethgo.Key, error) { - privateKeyRaw := testAccountPrivKey +type MessageResult struct { + Message string `json:"message"` +} + +func (r MessageResult) GetOutput() string { + var buffer bytes.Buffer + + buffer.WriteString(r.Message) + buffer.WriteString("\n") + + return buffer.String() +} + +// DecodePrivateKey decodes a private key from provided raw private key +func DecodePrivateKey(rawKey string) (ethgo.Key, error) { + privateKeyRaw := TestAccountPrivKey if rawKey != "" { privateKeyRaw = rawKey } @@ -87,3 +122,156 @@ func ReadRootchainIP() (string, error) { return fmt.Sprintf("http://%s:%s", ports[0].HostIP, ports[0].HostPort), nil } + +// GetECDSAKey returns the key based on provided parameters +// If private key is provided, it will return that key +// if not, it will return the key from the secrets manager +func GetECDSAKey(privateKey, accountDir, accountConfig string) (ethgo.Key, error) { + if privateKey != "" { + key, err := DecodePrivateKey(privateKey) + if err != nil { + return nil, fmt.Errorf("failed to initialize private key: %w", err) + } + + return key, nil + } + + secretsManager, err := polybftsecrets.GetSecretsManager(accountDir, accountConfig, true) + if err != nil { + return nil, err + } + + return polybftWallet.GetEcdsaFromSecret(secretsManager) +} + +// GetValidatorInfo queries SupernetManager smart contract on root +// and retrieves validator info for given address +func GetValidatorInfo(validatorAddr ethgo.Address, supernetManagerAddr, stakeManagerAddr types.Address, + chainID int64, txRelayer txrelayer.TxRelayer) (*polybft.ValidatorInfo, error) { + caller := ethgo.Address(contracts.SystemCaller) + getValidatorMethod := contractsapi.CustomSupernetManager.Abi.GetMethod("getValidator") + + encode, err := getValidatorMethod.Encode([]interface{}{validatorAddr}) + if err != nil { + return nil, err + } + + response, err := txRelayer.Call(caller, ethgo.Address(supernetManagerAddr), encode) + if err != nil { + return nil, err + } + + byteResponse, err := hex.DecodeHex(response) + if err != nil { + return nil, fmt.Errorf("unable to decode hex response, %w", err) + } + + decoded, err := getValidatorMethod.Outputs.Decode(byteResponse) + if err != nil { + return nil, err + } + + decodedOutputsMap, ok := decoded.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("could not convert decoded outputs to map") + } + + innerMap, ok := decodedOutputsMap["0"].(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("could not convert decoded outputs map to inner map") + } + + //nolint:forcetypeassert + validatorInfo := &polybft.ValidatorInfo{ + Address: validatorAddr, + IsActive: innerMap["isActive"].(bool), + IsWhitelisted: innerMap["isWhitelisted"].(bool), + } + + stakeOfFn := &contractsapi.StakeOfStakeManagerFn{ + ID: new(big.Int).SetInt64(chainID), + Validator: types.Address(validatorAddr), + } + + encode, err = stakeOfFn.EncodeAbi() + if err != nil { + return nil, err + } + + response, err = txRelayer.Call(caller, ethgo.Address(stakeManagerAddr), encode) + if err != nil { + return nil, err + } + + stake, err := types.ParseUint256orHex(&response) + if err != nil { + return nil, err + } + + validatorInfo.Stake = stake + + return validatorInfo, nil +} + +// CreateMintTxn encodes parameters for mint function on rootchain token contract +func CreateMintTxn(receiver, erc20TokenAddr types.Address, amount *big.Int) (*ethgo.Transaction, error) { + mintFn := &contractsapi.MintRootERC20Fn{ + To: receiver, + Amount: amount, + } + + input, err := mintFn.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode provided parameters: %w", err) + } + + addr := ethgo.Address(erc20TokenAddr) + + return ðgo.Transaction{ + To: &addr, + Input: input, + }, nil +} + +// CreateApproveERC20Txn sends approve transaction +// to ERC20 token for spender so that it is able to spend given tokens +func CreateApproveERC20Txn(amount *big.Int, + spender, erc20TokenAddr types.Address) (*ethgo.Transaction, error) { + approveFnParams := &contractsapi.ApproveRootERC20Fn{ + Spender: spender, + Amount: amount, + } + + input, err := approveFnParams.EncodeAbi() + if err != nil { + return nil, fmt.Errorf("failed to encode parameters for RootERC20.approve. error: %w", err) + } + + addr := ethgo.Address(erc20TokenAddr) + + return ðgo.Transaction{ + To: &addr, + Input: input, + }, nil +} + +// SendTransaction sends provided transaction +func SendTransaction(txRelayer txrelayer.TxRelayer, addr ethgo.Address, input []byte, contractName string, + deployerKey ethgo.Key) (*ethgo.Receipt, error) { + txn := ðgo.Transaction{ + To: &addr, + Input: input, + } + + receipt, err := txRelayer.SendTransaction(txn, deployerKey) + if err != nil { + return nil, fmt.Errorf("failed to send transaction to %s contract (%s). error: %w", + contractName, txn.To.Address(), err) + } + + if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) { + return nil, fmt.Errorf("transaction execution failed on %s contract", contractName) + } + + return receipt, nil +} diff --git a/command/rootchain/initcontracts/init_contracts.go b/command/rootchain/initcontracts/init_contracts.go deleted file mode 100644 index faf6d943cc..0000000000 --- a/command/rootchain/initcontracts/init_contracts.go +++ /dev/null @@ -1,442 +0,0 @@ -package initcontracts - -import ( - "fmt" - "math/big" - - "github.com/spf13/cobra" - "github.com/umbracle/ethgo" - "github.com/umbracle/ethgo/jsonrpc" - - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/command/rootchain/helper" - "github.com/0xPolygon/polygon-edge/consensus/polybft" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" - "github.com/0xPolygon/polygon-edge/contracts" - "github.com/0xPolygon/polygon-edge/txrelayer" - "github.com/0xPolygon/polygon-edge/types" -) - -const ( - contractsDeploymentTitle = "[ROOTCHAIN - CONTRACTS DEPLOYMENT]" - - stateSenderName = "StateSender" - checkpointManagerName = "CheckpointManager" - blsName = "BLS" - bn256G2Name = "BN256G2" - exitHelperName = "ExitHelper" - rootERC20PredicateName = "RootERC20Predicate" - rootERC20Name = "RootERC20" - erc20TemplateName = "ERC20Template" -) - -var ( - params initContractsParams - - // metadataPopulatorMap maps rootchain contract names to callback - // which populates appropriate field in the RootchainMetadata - metadataPopulatorMap = map[string]func(*polybft.RootchainConfig, types.Address){ - stateSenderName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { - rootchainConfig.StateSenderAddress = addr - }, - checkpointManagerName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { - rootchainConfig.CheckpointManagerAddress = addr - }, - blsName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { - rootchainConfig.BLSAddress = addr - }, - bn256G2Name: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { - rootchainConfig.BN256G2Address = addr - }, - exitHelperName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { - rootchainConfig.ExitHelperAddress = addr - }, - rootERC20PredicateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { - rootchainConfig.RootERC20PredicateAddress = addr - }, - rootERC20Name: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { - rootchainConfig.RootNativeERC20Address = addr - }, - erc20TemplateName: func(rootchainConfig *polybft.RootchainConfig, addr types.Address) { - rootchainConfig.ERC20TemplateAddress = addr - }, - } -) - -// GetCommand returns the rootchain init-contracts command -func GetCommand() *cobra.Command { - cmd := &cobra.Command{ - Use: "init-contracts", - Short: "Deploys and initializes required smart contracts on the rootchain", - PreRunE: runPreRun, - Run: runCommand, - } - - cmd.Flags().StringVar( - ¶ms.manifestPath, - manifestPathFlag, - defaultManifestPath, - "manifest file path, which contains metadata", - ) - - cmd.Flags().StringVar( - ¶ms.deployerKey, - deployerKeyFlag, - "", - "Hex encoded private key of the account which deploys rootchain contracts", - ) - - cmd.Flags().StringVar( - ¶ms.jsonRPCAddress, - jsonRPCFlag, - txrelayer.DefaultRPCAddress, - "the JSON RPC rootchain IP address", - ) - - cmd.Flags().StringVar( - ¶ms.rootERC20TokenAddr, - rootchainERC20Flag, - "", - "existing root chain ERC20 token address", - ) - - cmd.Flags().BoolVar( - ¶ms.isTestMode, - helper.TestModeFlag, - false, - "test indicates whether rootchain contracts deployer is hardcoded test account"+ - " (otherwise provided secrets are used to resolve deployer account)", - ) - - cmd.MarkFlagsMutuallyExclusive(helper.TestModeFlag, deployerKeyFlag) - - return cmd -} - -func runPreRun(_ *cobra.Command, _ []string) error { - return params.validateFlags() -} - -func runCommand(cmd *cobra.Command, _ []string) { - outputter := command.InitializeOutputter(cmd) - defer outputter.WriteOutput() - - outputter.WriteCommandResult(&messageResult{ - Message: fmt.Sprintf("%s started...", contractsDeploymentTitle), - }) - - client, err := jsonrpc.NewClient(params.jsonRPCAddress) - if err != nil { - outputter.SetError(fmt.Errorf("failed to initialize JSON RPC client for provided IP address: %s: %w", - params.jsonRPCAddress, err)) - - return - } - - manifest, err := polybft.LoadManifest(params.manifestPath) - if err != nil { - outputter.SetError(fmt.Errorf("failed to read manifest: %w", err)) - - return - } - - if manifest.RootchainConfig != nil { - code, err := client.Eth().GetCode(ethgo.Address(manifest.RootchainConfig.StateSenderAddress), ethgo.Latest) - if err != nil { - outputter.SetError(fmt.Errorf("failed to check if rootchain contracts are deployed: %w", err)) - - return - } else if code != "0x" { - outputter.SetCommandResult(&messageResult{ - Message: fmt.Sprintf("%s contracts are already deployed. Aborting.", contractsDeploymentTitle), - }) - - return - } - } - - if err := deployContracts(outputter, client, manifest); err != nil { - outputter.SetError(fmt.Errorf("failed to deploy rootchain contracts: %w", err)) - - return - } - - outputter.SetCommandResult(&messageResult{ - Message: fmt.Sprintf("%s finished. All contracts are successfully deployed and initialized.", - contractsDeploymentTitle), - }) -} - -func deployContracts(outputter command.OutputFormatter, client *jsonrpc.Client, - manifest *polybft.Manifest) error { - // if the bridge contract is not created, we have to deploy all the contracts - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(client)) - if err != nil { - return fmt.Errorf("failed to initialize tx relayer: %w", err) - } - - deployerKey, err := helper.GetRootchainPrivateKey(params.deployerKey) - if err != nil { - return fmt.Errorf("failed to initialize deployer key: %w", err) - } - - if params.isTestMode { - deployerAddr := deployerKey.Address() - txn := ðgo.Transaction{To: &deployerAddr, Value: big.NewInt(1000000000000000000)} - - _, err = txRelayer.SendTransactionLocal(txn) - if err != nil { - return err - } - } - - type contractInfo struct { - name string - artifact *artifact.Artifact - } - - deployContracts := []*contractInfo{ - { - name: "StateSender", - artifact: contractsapi.StateSender, - }, - { - name: "CheckpointManager", - artifact: contractsapi.CheckpointManager, - }, - { - name: "BLS", - artifact: contractsapi.BLS, - }, - { - name: "BN256G2", - artifact: contractsapi.BLS256, - }, - { - name: "ExitHelper", - artifact: contractsapi.ExitHelper, - }, - { - name: "RootERC20Predicate", - artifact: contractsapi.RootERC20Predicate, - }, - { - name: "ERC20Template", - artifact: contractsapi.ChildERC20, - }, - } - rootchainConfig := &polybft.RootchainConfig{} - manifest.RootchainConfig = rootchainConfig - - if params.rootERC20TokenAddr != "" { - // use existing root chain ERC20 token - addr := types.StringToAddress(params.rootERC20TokenAddr) - - code, err := client.Eth().GetCode(ethgo.Address(addr), ethgo.Latest) - if err != nil { - return fmt.Errorf("failed to check is root chain ERC20 token deployed: %w", err) - } else if code == "0x" { - return fmt.Errorf("root chain ERC20 token is not deployed on provided address %s", params.rootERC20TokenAddr) - } - - populatorFn, ok := metadataPopulatorMap["RootERC20"] - if !ok { - return fmt.Errorf("root chain metadata populator not registered for contract 'RootERC20'") - } - - populatorFn(manifest.RootchainConfig, addr) - } else { - // deploy MockERC20 as default root chain ERC20 token - deployContracts = append(deployContracts, &contractInfo{name: "RootERC20", artifact: contractsapi.RootERC20}) - } - - for _, contract := range deployContracts { - txn := ðgo.Transaction{ - To: nil, // contract deployment - Input: contract.artifact.Bytecode, - } - - receipt, err := txRelayer.SendTransaction(txn, deployerKey) - if err != nil { - return err - } - - if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) { - return fmt.Errorf("deployment of %s contract failed", contract.name) - } - - contractAddr := types.Address(receipt.ContractAddress) - - populatorFn, ok := metadataPopulatorMap[contract.name] - if !ok { - return fmt.Errorf("rootchain metadata populator not registered for contract '%s'", contract.name) - } - - populatorFn(manifest.RootchainConfig, contractAddr) - - outputter.WriteCommandResult(newDeployContractsResult(contract.name, contractAddr, receipt.TransactionHash)) - } - - if err := manifest.Save(params.manifestPath); err != nil { - return fmt.Errorf("failed to save manifest data: %w", err) - } - - // init CheckpointManager - if err := initializeCheckpointManager(outputter, txRelayer, manifest, deployerKey); err != nil { - return err - } - - outputter.WriteCommandResult(&messageResult{ - Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, checkpointManagerName), - }) - - // init ExitHelper - if err := initializeExitHelper(txRelayer, rootchainConfig, deployerKey); err != nil { - return err - } - - outputter.WriteCommandResult(&messageResult{ - Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, exitHelperName), - }) - - // init RootERC20Predicate - if err := initializeRootERC20Predicate(txRelayer, rootchainConfig, deployerKey); err != nil { - return err - } - - outputter.WriteCommandResult(&messageResult{ - Message: fmt.Sprintf("%s %s contract is initialized", contractsDeploymentTitle, rootERC20PredicateName), - }) - - return nil -} - -// initializeCheckpointManager invokes initialize function on "CheckpointManager" smart contract -func initializeCheckpointManager( - o command.OutputFormatter, - txRelayer txrelayer.TxRelayer, - manifest *polybft.Manifest, - deployerKey ethgo.Key) error { - validatorSet, err := validatorSetToABISlice(o, manifest.GenesisValidators) - if err != nil { - return fmt.Errorf("failed to convert validators to map: %w", err) - } - - initialize := contractsapi.InitializeCheckpointManagerFn{ - ChainID_: big.NewInt(manifest.ChainID), - NewBls: manifest.RootchainConfig.BLSAddress, - NewBn256G2: manifest.RootchainConfig.BN256G2Address, - NewValidatorSet: validatorSet, - } - - initCheckpointInput, err := initialize.EncodeAbi() - if err != nil { - return fmt.Errorf("failed to encode parameters for CheckpointManager.initialize. error: %w", err) - } - - addr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) - txn := ðgo.Transaction{ - To: &addr, - Input: initCheckpointInput, - } - - return sendTransaction(txRelayer, txn, checkpointManagerName, deployerKey) -} - -// initializeExitHelper invokes initialize function on "ExitHelper" smart contract -func initializeExitHelper(txRelayer txrelayer.TxRelayer, rootchainConfig *polybft.RootchainConfig, - deployerKey ethgo.Key) error { - input, err := contractsapi.ExitHelper.Abi.GetMethod("initialize"). - Encode([]interface{}{rootchainConfig.CheckpointManagerAddress}) - if err != nil { - return fmt.Errorf("failed to encode parameters for ExitHelper.initialize. error: %w", err) - } - - addr := ethgo.Address(rootchainConfig.ExitHelperAddress) - txn := ðgo.Transaction{ - To: &addr, - Input: input, - } - - return sendTransaction(txRelayer, txn, exitHelperName, deployerKey) -} - -// initializeRootERC20Predicate invokes initialize function on "RootERC20Predicate" smart contract -func initializeRootERC20Predicate(txRelayer txrelayer.TxRelayer, rootchainConfig *polybft.RootchainConfig, - deployerKey ethgo.Key) error { - rootERC20PredicateParams := &contractsapi.InitializeRootERC20PredicateFn{ - NewStateSender: rootchainConfig.StateSenderAddress, - NewExitHelper: rootchainConfig.ExitHelperAddress, - NewChildERC20Predicate: contracts.ChildERC20PredicateContract, - NewChildTokenTemplate: rootchainConfig.ERC20TemplateAddress, - NativeTokenRootAddress: rootchainConfig.RootNativeERC20Address, - } - - input, err := rootERC20PredicateParams.EncodeAbi() - if err != nil { - return fmt.Errorf("failed to encode parameters for RootERC20Predicate.initialize. error: %w", err) - } - - addr := ethgo.Address(rootchainConfig.RootERC20PredicateAddress) - txn := ðgo.Transaction{ - To: &addr, - Input: input, - } - - return sendTransaction(txRelayer, txn, rootERC20PredicateName, deployerKey) -} - -// sendTransaction sends provided transaction -func sendTransaction(txRelayer txrelayer.TxRelayer, txn *ethgo.Transaction, contractName string, - deployerKey ethgo.Key) error { - receipt, err := txRelayer.SendTransaction(txn, deployerKey) - if err != nil { - return fmt.Errorf("failed to send transaction to %s contract (%s). error: %w", contractName, txn.To.Address(), err) - } - - if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) { - return fmt.Errorf("transaction execution failed on %s contract", contractName) - } - - return nil -} - -// validatorSetToABISlice converts given validators to generic map -// which is used for ABI encoding validator set being sent to the rootchain contract -func validatorSetToABISlice(o command.OutputFormatter, - validators []*polybft.Validator) ([]*contractsapi.Validator, error) { - accSet := make(polybft.AccountSet, len(validators)) - - if _, err := o.Write([]byte(fmt.Sprintf("%s [VALIDATORS]\n", contractsDeploymentTitle))); err != nil { - return nil, err - } - - for i, validator := range validators { - if _, err := o.Write([]byte(fmt.Sprintf("%v\n", validator))); err != nil { - return nil, err - } - - blsKey, err := validator.UnmarshalBLSPublicKey() - if err != nil { - return nil, err - } - - accSet[i] = &polybft.ValidatorMetadata{ - Address: validator.Address, - BlsKey: blsKey, - VotingPower: new(big.Int).Set(validator.Stake), - } - } - - hash, err := accSet.Hash() - if err != nil { - return nil, err - } - - if _, err := o.Write([]byte(fmt.Sprintf("%s Validators hash: %s\n", contractsDeploymentTitle, hash))); err != nil { - return nil, err - } - - return accSet.ToAPIBinding(), nil -} diff --git a/command/rootchain/initcontracts/init_contracts_test.go b/command/rootchain/initcontracts/init_contracts_test.go deleted file mode 100644 index 60aeaa9a52..0000000000 --- a/command/rootchain/initcontracts/init_contracts_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package initcontracts - -import ( - "os" - "testing" - - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/command/rootchain/helper" - "github.com/0xPolygon/polygon-edge/consensus/polybft" - "github.com/stretchr/testify/require" - "github.com/umbracle/ethgo/jsonrpc" - "github.com/umbracle/ethgo/testutil" -) - -func TestDeployContracts_NoPanics(t *testing.T) { - t.Parallel() - - server := testutil.DeployTestServer(t, nil) - t.Cleanup(func() { - err := os.RemoveAll(params.manifestPath) - if err != nil { - t.Fatal(err) - } - }) - - client, err := jsonrpc.NewClient(server.HTTPAddr()) - require.NoError(t, err) - - testKey, err := helper.GetRootchainPrivateKey("") - require.NoError(t, err) - - receipt, err := server.Fund(testKey.Address()) - require.NoError(t, err) - require.Equal(t, uint64(1), receipt.Status) - - outputter := command.InitializeOutputter(GetCommand()) - - require.NotPanics(t, func() { - err = deployContracts(outputter, client, &polybft.Manifest{}) - }) - require.NoError(t, err) -} diff --git a/command/rootchain/initcontracts/params.go b/command/rootchain/initcontracts/params.go deleted file mode 100644 index 2258396ff9..0000000000 --- a/command/rootchain/initcontracts/params.go +++ /dev/null @@ -1,32 +0,0 @@ -package initcontracts - -import ( - "errors" - "fmt" - "os" -) - -const ( - manifestPathFlag = "manifest" - deployerKeyFlag = "deployer-key" - jsonRPCFlag = "json-rpc" - rootchainERC20Flag = "rootchain-erc20" - - defaultManifestPath = "./manifest.json" -) - -type initContractsParams struct { - manifestPath string - deployerKey string - jsonRPCAddress string - rootERC20TokenAddr string - isTestMode bool -} - -func (ip *initContractsParams) validateFlags() error { - if _, err := os.Stat(ip.manifestPath); errors.Is(err, os.ErrNotExist) { - return fmt.Errorf("provided manifest path '%s' doesn't exist", ip.manifestPath) - } - - return nil -} diff --git a/command/rootchain/registration/params.go b/command/rootchain/registration/params.go new file mode 100644 index 0000000000..faa1cd61ff --- /dev/null +++ b/command/rootchain/registration/params.go @@ -0,0 +1,45 @@ +package registration + +import ( + "bytes" + "fmt" + + "github.com/0xPolygon/polygon-edge/command/helper" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" +) + +type registerParams struct { + accountDir string + accountConfig string + supernetManagerAddress string + jsonRPC string +} + +func (rp *registerParams) validateFlags() error { + // validate jsonrpc address + _, err := helper.ParseJSONRPCAddress(rp.jsonRPC) + if err != nil { + return fmt.Errorf("failed to parse json rpc address. Error: %w", err) + } + + return sidechainHelper.ValidateSecretFlags(rp.accountDir, rp.accountConfig) +} + +type registerResult struct { + validatorAddress string + koskSignature string +} + +func (rr registerResult) GetOutput() string { + var buffer bytes.Buffer + + buffer.WriteString("\n[VALIDATOR REGISTRATION]\n") + + vals := make([]string, 0, 2) + vals = append(vals, fmt.Sprintf("Validator Address|%s", rr.validatorAddress)) + vals = append(vals, fmt.Sprintf("KOSK Signature|%s", rr.koskSignature)) + buffer.WriteString(helper.FormatKV(vals)) + buffer.WriteString("\n") + + return buffer.String() +} diff --git a/command/sidechain/registration/register_validator.go b/command/rootchain/registration/register_validator.go similarity index 55% rename from command/sidechain/registration/register_validator.go rename to command/rootchain/registration/register_validator.go index 7518d846a9..fcc89a95aa 100644 --- a/command/sidechain/registration/register_validator.go +++ b/command/rootchain/registration/register_validator.go @@ -8,28 +8,22 @@ import ( "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/helper" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" - "github.com/0xPolygon/polygon-edge/contracts" - "github.com/0xPolygon/polygon-edge/secrets" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" "github.com/spf13/cobra" "github.com/umbracle/ethgo" ) -var ( - stakeManager = contracts.ValidatorSetContract - stakeFn = contractsapi.ChildValidatorSet.Abi.Methods["stake"] -) - var params registerParams func GetCommand() *cobra.Command { registerCmd := &cobra.Command{ Use: "register-validator", - Short: "Registers and stake an enlisted validator", + Short: "registers a whitelisted validator to supernet manager on rootchain", PreRunE: runPreRun, RunE: runCommand, } @@ -55,17 +49,10 @@ func setFlags(cmd *cobra.Command) { ) cmd.Flags().StringVar( - ¶ms.stake, - stakeFlag, + ¶ms.supernetManagerAddress, + rootHelper.SupernetManagerFlag, "", - "stake represents amount which is going to be staked by the new validator account", - ) - - cmd.Flags().Int64Var( - ¶ms.chainID, - chainIDFlag, - command.DefaultChainID, - "the ID of the chain", + rootHelper.SupernetManagerFlagDesc, ) helper.RegisterJSONRPCFlag(cmd) @@ -92,27 +79,24 @@ func runCommand(cmd *cobra.Command, _ []string) error { return err } - newValidatorAccount, err := wallet.NewAccountFromSecret(secretsManager) + rootChainID, err := txRelayer.Client().Eth().ChainID() if err != nil { return err } - sRaw, err := secretsManager.GetSecret(secrets.ValidatorBLSSignature) - if err != nil { - return err - } - - sb, err := hex.DecodeString(string(sRaw)) + newValidatorAccount, err := wallet.NewAccountFromSecret(secretsManager) if err != nil { return err } - blsSignature, err := bls.UnmarshalSignature(sb) + koskSignature, err := bls.MakeKOSKSignature( + newValidatorAccount.Bls, newValidatorAccount.Address(), + rootChainID.Int64(), bls.DomainValidatorSet, types.StringToAddress(params.supernetManagerAddress)) if err != nil { return err } - receipt, err := registerValidator(txRelayer, newValidatorAccount, blsSignature) + receipt, err := registerValidator(txRelayer, newValidatorAccount, koskSignature) if err != nil { return err } @@ -124,20 +108,25 @@ func runCommand(cmd *cobra.Command, _ []string) error { result := ®isterResult{} foundLog := false - var newValidatorEvent contractsapi.NewValidatorEvent + var validatorRegisteredEvent contractsapi.ValidatorRegisteredEvent for _, log := range receipt.Logs { - doesMatch, err := newValidatorEvent.ParseLog(log) + doesMatch, err := validatorRegisteredEvent.ParseLog(log) + if err != nil { + return err + } + if !doesMatch { continue } + koskSignatureRaw, err := koskSignature.Marshal() if err != nil { return err } - result.validatorAddress = newValidatorEvent.Validator.String() - result.stakeResult = "No stake parameters have been submitted" - result.amount = 0 + result.koskSignature = hex.EncodeToString(koskSignatureRaw) + result.validatorAddress = validatorRegisteredEvent.Validator.String() + foundLog = true break @@ -147,74 +136,11 @@ func runCommand(cmd *cobra.Command, _ []string) error { return fmt.Errorf("could not find an appropriate log in receipt that registration happened") } - if params.stake != "" { - receipt, err = stake(txRelayer, newValidatorAccount) - if err != nil { - result.stakeResult = fmt.Sprintf("Failed to execute stake transaction: %s", err.Error()) - } else { - populateStakeResults(receipt, result) - } - } - outputter.WriteCommandResult(result) return nil } -func stake(sender txrelayer.TxRelayer, account *wallet.Account) (*ethgo.Receipt, error) { - if stakeFn == nil { - return nil, errors.New("failed to create stake ABI function") - } - - input, err := stakeFn.Encode([]interface{}{}) - if err != nil { - return nil, err - } - - stake, err := types.ParseUint256orHex(¶ms.stake) - if err != nil { - return nil, err - } - - txn := ðgo.Transaction{ - Input: input, - To: (*ethgo.Address)(&stakeManager), - Value: stake, - } - - return sender.SendTransaction(txn, account.Ecdsa) -} - -func populateStakeResults(receipt *ethgo.Receipt, result *registerResult) { - if receipt.Status != uint64(types.ReceiptSuccess) { - result.stakeResult = "Stake transaction failed" - - return - } - - // check the logs to verify stake - var stakedEvent contractsapi.StakedEvent - for _, log := range receipt.Logs { - doesMatch, err := stakedEvent.ParseLog(log) - if !doesMatch { - continue - } - - if err != nil { - result.stakeResult = "Failed to parse stake log" - - return - } - - result.amount = stakedEvent.Amount.Uint64() - result.stakeResult = "Stake succeeded" - - return - } - - result.stakeResult = "Could not find an appropriate log in receipt that stake happened" -} - func registerValidator(sender txrelayer.TxRelayer, account *wallet.Account, signature *bls.Signature) (*ethgo.Receipt, error) { sigMarshal, err := signature.ToBigInt() @@ -222,7 +148,7 @@ func registerValidator(sender txrelayer.TxRelayer, account *wallet.Account, return nil, fmt.Errorf("register validator failed: %w", err) } - registerFn := &contractsapi.RegisterChildValidatorSetFn{ + registerFn := &contractsapi.RegisterCustomSupernetManagerFn{ Signature: sigMarshal, Pubkey: account.Bls.PublicKey().ToBigInt(), } @@ -232,9 +158,10 @@ func registerValidator(sender txrelayer.TxRelayer, account *wallet.Account, return nil, fmt.Errorf("register validator failed: %w", err) } + supernetAddr := ethgo.Address(types.StringToAddress(params.supernetManagerAddress)) txn := ðgo.Transaction{ Input: input, - To: (*ethgo.Address)(&stakeManager), + To: &supernetAddr, } return sender.SendTransaction(txn, account.Ecdsa) diff --git a/command/rootchain/rootchain.go b/command/rootchain/rootchain.go index 2d7fa00f62..c49a8fcd73 100644 --- a/command/rootchain/rootchain.go +++ b/command/rootchain/rootchain.go @@ -3,8 +3,8 @@ package rootchain import ( "github.com/spf13/cobra" + "github.com/0xPolygon/polygon-edge/command/rootchain/deploy" "github.com/0xPolygon/polygon-edge/command/rootchain/fund" - "github.com/0xPolygon/polygon-edge/command/rootchain/initcontracts" "github.com/0xPolygon/polygon-edge/command/rootchain/server" ) @@ -15,18 +15,14 @@ func GetCommand() *cobra.Command { Short: "Top level rootchain helper command.", } - registerSubcommands(rootchainCmd) - - return rootchainCmd -} - -func registerSubcommands(baseCmd *cobra.Command) { - baseCmd.AddCommand( - // rootchain fund - fund.GetCommand(), + rootchainCmd.AddCommand( // rootchain server server.GetCommand(), - // init-contracts - initcontracts.GetCommand(), + // rootchain deploy + deploy.GetCommand(), + // rootchain fund + fund.GetCommand(), ) + + return rootchainCmd } diff --git a/command/rootchain/staking/params.go b/command/rootchain/staking/params.go new file mode 100644 index 0000000000..e56ec6bcbe --- /dev/null +++ b/command/rootchain/staking/params.go @@ -0,0 +1,57 @@ +package staking + +import ( + "bytes" + "fmt" + "math/big" + + "github.com/0xPolygon/polygon-edge/command/helper" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" +) + +var supernetIDFlag = "supernet-id" + +type stakeParams struct { + accountDir string + accountConfig string + stakeManagerAddr string + stakeTokenAddr string + jsonRPC string + supernetID int64 + amount string + + amountValue *big.Int +} + +func (sp *stakeParams) validateFlags() (err error) { + if sp.amountValue, err = helper.ParseAmount(sp.amount); err != nil { + return err + } + + // validate jsonrpc address + if _, err := helper.ParseJSONRPCAddress(sp.jsonRPC); err != nil { + return fmt.Errorf("failed to parse json rpc address. Error: %w", err) + } + + return sidechainHelper.ValidateSecretFlags(sp.accountDir, sp.accountConfig) +} + +type stakeResult struct { + validatorAddress string + amount *big.Int +} + +func (sr stakeResult) GetOutput() string { + var buffer bytes.Buffer + + buffer.WriteString("\n[VALIDATOR STAKE]\n") + + vals := make([]string, 0, 2) + vals = append(vals, fmt.Sprintf("Validator Address|%s", sr.validatorAddress)) + vals = append(vals, fmt.Sprintf("Amount Staked|%d", sr.amount)) + + buffer.WriteString(helper.FormatKV(vals)) + buffer.WriteString("\n") + + return buffer.String() +} diff --git a/command/sidechain/staking/stake.go b/command/rootchain/staking/stake.go similarity index 56% rename from command/sidechain/staking/stake.go rename to command/rootchain/staking/stake.go index 6ed251793d..f195d4aeb6 100644 --- a/command/sidechain/staking/stake.go +++ b/command/rootchain/staking/stake.go @@ -8,9 +8,9 @@ import ( "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/helper" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" "github.com/spf13/cobra" @@ -24,7 +24,7 @@ var ( func GetCommand() *cobra.Command { stakeCmd := &cobra.Command{ Use: "stake", - Short: "Stakes the amount sent for validator or delegates its stake to another account", + Short: "Stakes the amount sent for validator on rootchain", PreRunE: runPreRun, RunE: runCommand, } @@ -50,28 +50,34 @@ func setFlags(cmd *cobra.Command) { polybftsecrets.AccountConfigFlagDesc, ) - cmd.Flags().BoolVar( - ¶ms.self, - sidechainHelper.SelfFlag, - false, - "indicates if its a self stake action", + cmd.Flags().StringVar( + ¶ms.stakeManagerAddr, + rootHelper.StakeManagerFlag, + "", + rootHelper.StakeManagerFlagDesc, ) - cmd.Flags().Uint64Var( + cmd.Flags().StringVar( ¶ms.amount, sidechainHelper.AmountFlag, + "", + "amount to stake", + ) + + cmd.Flags().Int64Var( + ¶ms.supernetID, + supernetIDFlag, 0, - "amount to stake or delegate to another account", + "ID of supernet provided by stake manager on supernet registration", ) cmd.Flags().StringVar( - ¶ms.delegateAddress, - delegateAddressFlag, + ¶ms.stakeTokenAddr, + rootHelper.StakeTokenFlag, "", - "account address to which stake should be delegated", + rootHelper.StakeTokenFlagDesc, ) - cmd.MarkFlagsMutuallyExclusive(sidechainHelper.SelfFlag, delegateAddressFlag) cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) } @@ -96,30 +102,39 @@ func runCommand(cmd *cobra.Command, _ []string) error { return err } - var encoded []byte - if params.self { - encoded, err = contractsapi.ChildValidatorSet.Abi.Methods["stake"].Encode([]interface{}{}) - if err != nil { - return err - } - } else { - delegateToAddress := types.StringToAddress(params.delegateAddress) - encoded, err = contractsapi.ChildValidatorSet.Abi.Methods["delegate"].Encode( - []interface{}{ethgo.Address(delegateToAddress), false}) - if err != nil { - return err - } + approveTxn, err := rootHelper.CreateApproveERC20Txn(params.amountValue, + types.StringToAddress(params.stakeManagerAddr), types.StringToAddress(params.stakeTokenAddr)) + if err != nil { + return err } + receipt, err := txRelayer.SendTransaction(approveTxn, validatorAccount.Ecdsa) + if err != nil { + return err + } + + if receipt.Status == uint64(types.ReceiptFailed) { + return fmt.Errorf("approve transaction failed on block %d", receipt.BlockNumber) + } + + stakeFn := contractsapi.StakeForStakeManagerFn{ + ID: new(big.Int).SetInt64(params.supernetID), + Amount: params.amountValue, + } + + encoded, err := stakeFn.EncodeAbi() + if err != nil { + return err + } + + stakeManagerAddr := ethgo.Address(types.StringToAddress(params.stakeManagerAddr)) txn := ðgo.Transaction{ - From: validatorAccount.Ecdsa.Address(), - Input: encoded, - To: (*ethgo.Address)(&contracts.ValidatorSetContract), - Value: new(big.Int).SetUint64(params.amount), - GasPrice: sidechainHelper.DefaultGasPrice, + From: validatorAccount.Ecdsa.Address(), + Input: encoded, + To: &stakeManagerAddr, } - receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa) + receipt, err = txRelayer.SendTransaction(txn, validatorAccount.Ecdsa) if err != nil { return err } @@ -133,42 +148,30 @@ func runCommand(cmd *cobra.Command, _ []string) error { } var ( - stakedEvent contractsapi.StakedEvent - delegatedEvent contractsapi.DelegatedEvent - foundLog bool + stakeAddedEvent contractsapi.StakeAddedEvent + foundLog bool ) // check the logs to check for the result for _, log := range receipt.Logs { - doesMatch, err := stakedEvent.ParseLog(log) + doesMatch, err := stakeAddedEvent.ParseLog(log) if err != nil { return err } - if doesMatch { // its a stake function call - result.isSelfStake = true - result.amount = stakedEvent.Amount.Uint64() - foundLog = true - - break - } - - doesMatch, err = delegatedEvent.ParseLog(log) - if err != nil { - return err + if !doesMatch { + continue } - if doesMatch { - result.amount = delegatedEvent.Amount.Uint64() - result.delegatedTo = delegatedEvent.Validator.String() - foundLog = true + result.amount = stakeAddedEvent.Amount + result.validatorAddress = stakeAddedEvent.Validator.String() + foundLog = true - break - } + break } if !foundLog { - return fmt.Errorf("could not find an appropriate log in receipt that stake or delegate happened") + return fmt.Errorf("could not find an appropriate log in receipt that stake happened") } outputter.WriteCommandResult(result) diff --git a/command/rootchain/supernet/params.go b/command/rootchain/supernet/params.go new file mode 100644 index 0000000000..04c36fec39 --- /dev/null +++ b/command/rootchain/supernet/params.go @@ -0,0 +1,69 @@ +package supernet + +import ( + "bytes" + "fmt" + "os" + + "github.com/0xPolygon/polygon-edge/command/helper" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" +) + +const ( + finalizeGenesisSetFlag = "finalize-genesis-set" + enableStakingFlag = "enable-staking" +) + +type supernetParams struct { + accountDir string + accountConfig string + privateKey string + jsonRPC string + supernetManagerAddress string + stakeManagerAddress string + genesisPath string + finalizeGenesisSet bool + enableStaking bool +} + +func (sp *supernetParams) validateFlags() error { + if sp.privateKey == "" { + return sidechainHelper.ValidateSecretFlags(sp.accountDir, sp.accountConfig) + } + + if _, err := os.Stat(sp.genesisPath); err != nil { + return fmt.Errorf("provided genesis path '%s' is invalid. Error: %w ", sp.genesisPath, err) + } + + // validate jsonrpc address + _, err := helper.ParseJSONRPCAddress(sp.jsonRPC) + + return err +} + +type supernetResult struct { + isGenesisSetFinalized bool + isStakingEnabled bool +} + +func (sr supernetResult) GetOutput() string { + var ( + buffer bytes.Buffer + vals []string + ) + + buffer.WriteString("\n[SUPERNET COMMAND]\n") + + if sr.isGenesisSetFinalized { + vals = append(vals, "Genesis validator set finalized on supernet manager") + } + + if sr.isStakingEnabled { + vals = append(vals, "Staking enabled on supernet manager") + } + + buffer.WriteString(helper.FormatKV(vals)) + buffer.WriteString("\n") + + return buffer.String() +} diff --git a/command/rootchain/supernet/stakemanager/params.go b/command/rootchain/supernet/stakemanager/params.go new file mode 100644 index 0000000000..c62aa0d9c0 --- /dev/null +++ b/command/rootchain/supernet/stakemanager/params.go @@ -0,0 +1,34 @@ +package stakemanager + +import ( + "fmt" + "os" + + "github.com/0xPolygon/polygon-edge/command/helper" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" +) + +type stakeManagerDeployParams struct { + accountDir string + accountConfig string + privateKey string + jsonRPC string + genesisPath string + stakeTokenAddress string + isTestMode bool +} + +func (s *stakeManagerDeployParams) validateFlags() error { + if !s.isTestMode && s.privateKey == "" { + return sidechainHelper.ValidateSecretFlags(s.accountDir, s.accountConfig) + } + + if _, err := os.Stat(s.genesisPath); err != nil { + return fmt.Errorf("provided genesis path '%s' is invalid. Error: %w ", s.genesisPath, err) + } + + // validate jsonrpc address + _, err := helper.ParseJSONRPCAddress(s.jsonRPC) + + return err +} diff --git a/command/rootchain/supernet/stakemanager/stake_manager_deploy.go b/command/rootchain/supernet/stakemanager/stake_manager_deploy.go new file mode 100644 index 0000000000..d82746c77f --- /dev/null +++ b/command/rootchain/supernet/stakemanager/stake_manager_deploy.go @@ -0,0 +1,266 @@ +package stakemanager + +import ( + "fmt" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/helper" + "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" + "golang.org/x/sync/errgroup" +) + +var params stakeManagerDeployParams + +func GetCommand() *cobra.Command { + registerCmd := &cobra.Command{ + Use: "stake-manager-deploy", + Short: "Command for deploying stake manager contract on rootchain", + PreRunE: runPreRun, + RunE: runCommand, + } + + setFlags(registerCmd) + + return registerCmd +} + +func runPreRun(cmd *cobra.Command, _ []string) error { + params.jsonRPC = helper.GetJSONRPCAddress(cmd) + + return params.validateFlags() +} + +func setFlags(cmd *cobra.Command) { + cmd.Flags().StringVar( + ¶ms.accountDir, + polybftsecrets.AccountDirFlag, + "", + polybftsecrets.AccountDirFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.accountConfig, + polybftsecrets.AccountConfigFlag, + "", + polybftsecrets.AccountConfigFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.privateKey, + polybftsecrets.PrivateKeyFlag, + "", + polybftsecrets.PrivateKeyFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.genesisPath, + rootHelper.GenesisPathFlag, + rootHelper.DefaultGenesisPath, + rootHelper.GenesisPathFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.stakeTokenAddress, + rootHelper.StakeTokenFlag, + "", + rootHelper.StakeTokenFlagDesc, + ) + + cmd.Flags().BoolVar( + ¶ms.isTestMode, + rootHelper.TestModeFlag, + false, + "indicates if command is run in test mode. If test mode is used contract will be deployed using test account "+ + "and a test stake ERC20 token will be deployed to be used for staking", + ) + + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.PrivateKeyFlag, polybftsecrets.AccountConfigFlag) + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.PrivateKeyFlag, polybftsecrets.AccountDirFlag) + cmd.MarkFlagsMutuallyExclusive(rootHelper.TestModeFlag, polybftsecrets.PrivateKeyFlag) + cmd.MarkFlagsMutuallyExclusive(rootHelper.TestModeFlag, polybftsecrets.AccountConfigFlag) + cmd.MarkFlagsMutuallyExclusive(rootHelper.TestModeFlag, polybftsecrets.AccountDirFlag) + cmd.MarkFlagsMutuallyExclusive(rootHelper.TestModeFlag, rootHelper.StakeTokenFlag) + + helper.RegisterJSONRPCFlag(cmd) +} + +func runCommand(cmd *cobra.Command, _ []string) error { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + var ( + deployerKey ethgo.Key + err error + ) + + if params.isTestMode { + deployerKey, err = rootHelper.DecodePrivateKey("") + } else { + deployerKey, err = rootHelper.GetECDSAKey(params.privateKey, params.accountDir, params.accountConfig) + } + + if err != nil { + return fmt.Errorf("faield to get deployer key: %w", err) + } + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPC)) + if err != nil { + return fmt.Errorf("deploying stake manager failed: %w", err) + } + + if params.isTestMode { + // fund deployer so that he can deploy contracts + deployerAddr := deployerKey.Address() + txn := ðgo.Transaction{To: &deployerAddr, Value: ethgo.Ether(1)} + + if _, err = txRelayer.SendTransactionLocal(txn); err != nil { + return fmt.Errorf("faield to send local transaction: %w", err) + } + } + + var ( + stakeManagerAddress types.Address + stakeTokenAddress = types.StringToAddress(params.stakeTokenAddress) + g, ctx = errgroup.WithContext(cmd.Context()) + ) + + g.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + // deploy stake manager + contractAddress, err := deployContract(txRelayer, deployerKey, + contractsapi.StakeManager, "StakeManager") + if err != nil { + return err + } + + outputter.WriteCommandResult(&rootHelper.MessageResult{ + Message: "[STAKEMANAGER - DEPLOY] Successfully deployed StakeManager contract", + }) + + stakeManagerAddress = contractAddress + + return nil + } + }) + + if params.isTestMode { + g.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + // this is only used for testing, we are deploying a test ERC20 token to use for staking + // this should not be used in production + // deploy stake manager + contractAddress, err := deployContract(txRelayer, deployerKey, + contractsapi.RootERC20, "MockERC20StakeToken") + if err != nil { + return err + } + + outputter.WriteCommandResult(&rootHelper.MessageResult{ + Message: "[STAKEMANAGER - DEPLOY] Successfully deployed MockERC20StakeToken contract", + }) + + stakeTokenAddress = contractAddress + + return nil + } + }) + } + + if err := g.Wait(); err != nil { + return err + } + + // initialize stake manager + if err := initializeStakeManager(outputter, txRelayer, + stakeManagerAddress, stakeTokenAddress, deployerKey); err != nil { + return fmt.Errorf("could not initialize stake manager contract. Error: %w", err) + } + + // update stake manager address in genesis + chainConfig, err := chain.ImportFromFile(params.genesisPath) + if err != nil { + return fmt.Errorf("failed to read chain configuration: %w", err) + } + + consensusConfig, err := polybft.GetPolyBFTConfig(chainConfig) + if err != nil { + return fmt.Errorf("failed to retrieve consensus configuration: %w", err) + } + + if consensusConfig.Bridge == nil { + consensusConfig.Bridge = &polybft.BridgeConfig{} + } + + consensusConfig.Bridge.StakeManagerAddr = stakeManagerAddress + consensusConfig.Bridge.StakeTokenAddr = stakeTokenAddress + + // write updated chain configuration + chainConfig.Params.Engine[polybft.ConsensusName] = consensusConfig + + if err = helper.WriteGenesisConfigToDisk(chainConfig, params.genesisPath); err != nil { + return fmt.Errorf("failed to save chain configuration bridge data: %w", err) + } + + return nil +} + +// initializeStakeManager invokes initialize function on StakeManager contract +func initializeStakeManager(cmdOutput command.OutputFormatter, + txRelayer txrelayer.TxRelayer, + stakeManagerAddress types.Address, + stakeTokenAddress types.Address, + deployerKey ethgo.Key) error { + initFn := &contractsapi.InitializeStakeManagerFn{NewMatic: stakeTokenAddress} + + input, err := initFn.EncodeAbi() + if err != nil { + return err + } + + if _, err := rootHelper.SendTransaction(txRelayer, ethgo.Address(stakeManagerAddress), + input, "StakeManager", deployerKey); err != nil { + return err + } + + cmdOutput.WriteCommandResult(&rootHelper.MessageResult{ + Message: "[STAKEMANAGER - DEPLOY] StakeManager contract is initialized", + }) + + return nil +} + +func deployContract(txRelayer txrelayer.TxRelayer, deployerKey ethgo.Key, + artifact *artifact.Artifact, contractName string) (types.Address, error) { + txn := ðgo.Transaction{ + To: nil, // contract deployment + Input: artifact.Bytecode, + } + + receipt, err := txRelayer.SendTransaction(txn, deployerKey) + if err != nil { + return types.ZeroAddress, + fmt.Errorf("failed sending %s contract deploy transaction: %w", contractName, err) + } + + if receipt == nil || receipt.Status != uint64(types.ReceiptSuccess) { + return types.ZeroAddress, fmt.Errorf("deployment of %s contract failed", contractName) + } + + return types.Address(receipt.ContractAddress), nil +} diff --git a/command/rootchain/supernet/supernet.go b/command/rootchain/supernet/supernet.go new file mode 100644 index 0000000000..40f2ba7270 --- /dev/null +++ b/command/rootchain/supernet/supernet.go @@ -0,0 +1,332 @@ +package supernet + +import ( + "fmt" + "math/big" + "strings" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/genesis" + "github.com/0xPolygon/polygon-edge/command/helper" + "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" +) + +var params supernetParams + +func GetCommand() *cobra.Command { + registerCmd := &cobra.Command{ + Use: "supernet", + Short: "Supernet initialization & finalization command", + PreRunE: runPreRun, + RunE: runCommand, + } + + setFlags(registerCmd) + + return registerCmd +} + +func runPreRun(cmd *cobra.Command, _ []string) error { + params.jsonRPC = helper.GetJSONRPCAddress(cmd) + + return params.validateFlags() +} + +func setFlags(cmd *cobra.Command) { + cmd.Flags().StringVar( + ¶ms.accountDir, + polybftsecrets.AccountDirFlag, + "", + polybftsecrets.AccountDirFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.accountConfig, + polybftsecrets.AccountConfigFlag, + "", + polybftsecrets.AccountConfigFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.privateKey, + polybftsecrets.PrivateKeyFlag, + "", + polybftsecrets.PrivateKeyFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.genesisPath, + rootHelper.GenesisPathFlag, + rootHelper.DefaultGenesisPath, + rootHelper.GenesisPathFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.supernetManagerAddress, + rootHelper.SupernetManagerFlag, + "", + rootHelper.SupernetManagerFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.stakeManagerAddress, + rootHelper.StakeManagerFlag, + "", + rootHelper.StakeManagerFlagDesc, + ) + + cmd.Flags().BoolVar( + ¶ms.finalizeGenesisSet, + finalizeGenesisSetFlag, + false, + "indicates if genesis validator set should be finalized on rootchain", + ) + + cmd.Flags().BoolVar( + ¶ms.enableStaking, + enableStakingFlag, + false, + "indicates if staking will be enabled after finalization of genesis validators on rootchain", + ) + + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.PrivateKeyFlag, polybftsecrets.AccountConfigFlag) + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.PrivateKeyFlag, polybftsecrets.AccountDirFlag) + + helper.RegisterJSONRPCFlag(cmd) +} + +func runCommand(cmd *cobra.Command, _ []string) error { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + ownerKey, err := rootHelper.GetECDSAKey(params.privateKey, params.accountDir, params.accountConfig) + if err != nil { + return err + } + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPC)) + if err != nil { + return fmt.Errorf("enlist validator failed: %w", err) + } + + supernetAddr := ethgo.Address(types.StringToAddress(params.supernetManagerAddress)) + + if params.finalizeGenesisSet { + encoded, err := contractsapi.CustomSupernetManager.Abi.Methods["finalizeGenesis"].Encode([]interface{}{}) + if err != nil { + return err + } + + txn := ðgo.Transaction{ + From: ownerKey.Address(), + Input: encoded, + To: &supernetAddr, + } + + if _, err = txRelayer.Call(ownerKey.Address(), supernetAddr, encoded); err == nil { + receipt, err := txRelayer.SendTransaction(txn, ownerKey) + if err != nil { + return fmt.Errorf("finalizing genesis validator set failed. Error: %w", err) + } + + if receipt.Status == uint64(types.ReceiptFailed) { + return fmt.Errorf("finalizing genesis validator set transaction failed on block %d", receipt.BlockNumber) + } + } else if !strings.Contains(err.Error(), "execution reverted: GenesisLib: already finalized") { + return err + } + + chainConfig, err := chain.ImportFromFile(params.genesisPath) + if err != nil { + return fmt.Errorf("failed to read chain configuration: %w", err) + } + + consensusConfig, err := polybft.GetPolyBFTConfig(chainConfig) + if err != nil { + return fmt.Errorf("failed to retrieve consensus configuration: %w", err) + } + + stakeManager := types.StringToAddress(params.stakeManagerAddress) + callerAddr := types.Address(ownerKey.Address()) + + validatorMetadata := make([]*validator.ValidatorMetadata, len(consensusConfig.InitialValidatorSet)) + + // update Stake field of validators in genesis file + // based on their finalized stake on rootchain + for i, v := range consensusConfig.InitialValidatorSet { + finalizedStake, err := getFinalizedStake(callerAddr, v.Address, stakeManager, + consensusConfig.SupernetID, txRelayer) + if err != nil { + return fmt.Errorf("could not get finalized stake for validator: %v. Error: %w", v.Address, err) + } + + v.Stake = finalizedStake + + metadata, err := v.ToValidatorMetadata() + if err != nil { + return err + } + + validatorMetadata[i] = metadata + } + + // update the voting power in genesis block extra + // based on finalized stake on rootchain + genesisExtraData, err := genesis.GenerateExtraDataPolyBft(validatorMetadata) + if err != nil { + return err + } + + chainConfig.Genesis.ExtraData = genesisExtraData + chainConfig.Params.Engine[polybft.ConsensusName] = consensusConfig + + // save updated stake and genesis extra to genesis file on disk + if err := helper.WriteGenesisConfigToDisk(chainConfig, params.genesisPath); err != nil { + return fmt.Errorf("failed to save chain configuration bridge data: %w", err) + } + + // initialize CheckpointManager contract since it needs to have a valid VotingPowers of validators + if err := initializeCheckpointManager(outputter, txRelayer, + consensusConfig, chainConfig.Params.ChainID, ownerKey); err != nil { + return fmt.Errorf("could not initialize CheckpointManager with finalized genesis validator set: %w", err) + } + } + + if params.enableStaking { + encoded, err := contractsapi.CustomSupernetManager.Abi.Methods["enableStaking"].Encode([]interface{}{}) + if err != nil { + return err + } + + txn := ðgo.Transaction{ + From: ownerKey.Address(), + Input: encoded, + To: &supernetAddr, + } + + receipt, err := txRelayer.SendTransaction(txn, ownerKey) + if err != nil { + return fmt.Errorf("enabling staking on supernet manager failed. Error: %w", err) + } + + if receipt.Status == uint64(types.ReceiptFailed) { + return fmt.Errorf("enable staking transaction failed on block %d", receipt.BlockNumber) + } + } + + result := &supernetResult{ + isGenesisSetFinalized: params.finalizeGenesisSet, + isStakingEnabled: params.enableStaking, + } + + outputter.WriteCommandResult(result) + + return nil +} + +// geFinalizedStake returns finalized stake of given validator for given supernet on StakeManager +func getFinalizedStake(owner, validator, stakeManager types.Address, chainID int64, + txRelayer txrelayer.TxRelayer) (*big.Int, error) { + stakeOfFn := &contractsapi.StakeOfStakeManagerFn{ + Validator: validator, + ID: new(big.Int).SetInt64(chainID), + } + + encode, err := stakeOfFn.EncodeAbi() + if err != nil { + return nil, err + } + + response, err := txRelayer.Call(ethgo.Address(owner), ethgo.Address(stakeManager), encode) + if err != nil { + return nil, err + } + + return types.ParseUint256orHex(&response) +} + +// validatorSetToABISlice converts given validators to generic map +// which is used for ABI encoding validator set being sent to the rootchain contract +func validatorSetToABISlice(o command.OutputFormatter, + validators []*validator.GenesisValidator) ([]*contractsapi.Validator, error) { + accSet := make(validator.AccountSet, len(validators)) + + if _, err := o.Write([]byte("[VALIDATORS - CHECKPOINT MANAGER] \n")); err != nil { + return nil, err + } + + for i, val := range validators { + if _, err := o.Write([]byte(fmt.Sprintf("%v\n", val))); err != nil { + return nil, err + } + + blsKey, err := val.UnmarshalBLSPublicKey() + if err != nil { + return nil, err + } + + accSet[i] = &validator.ValidatorMetadata{ + Address: val.Address, + BlsKey: blsKey, + VotingPower: new(big.Int).Set(val.Stake), + } + } + + hash, err := accSet.Hash() + if err != nil { + return nil, err + } + + if _, err := o.Write([]byte( + fmt.Sprintf("[VALIDATORS - CHECKPOINT MANAGER] Validators hash: %s\n", hash))); err != nil { + return nil, err + } + + return accSet.ToAPIBinding(), nil +} + +// initializeCheckpointManager initializes CheckpointManager contract on rootchain +// based on finalized stake (voting power) of genesis validators on root +func initializeCheckpointManager(outputter command.OutputFormatter, + txRelayer txrelayer.TxRelayer, + consensusConfig polybft.PolyBFTConfig, chainID int64, + deployerKey ethgo.Key) error { + validatorSet, err := validatorSetToABISlice(outputter, consensusConfig.InitialValidatorSet) + if err != nil { + return fmt.Errorf("failed to convert validators to map: %w", err) + } + + initParams := &contractsapi.InitializeCheckpointManagerFn{ + ChainID_: big.NewInt(chainID), + NewBls: consensusConfig.Bridge.BLSAddress, + NewBn256G2: consensusConfig.Bridge.BN256G2Address, + NewValidatorSet: validatorSet, + } + + input, err := initParams.EncodeAbi() + if err != nil { + return fmt.Errorf("failed to encode initialization params for CheckpointManager.initialize. error: %w", err) + } + + if _, err := rootHelper.SendTransaction(txRelayer, ethgo.Address(consensusConfig.Bridge.CheckpointManagerAddr), + input, "CheckpointManager", deployerKey); err != nil { + return err + } + + outputter.WriteCommandResult( + &rootHelper.MessageResult{ + Message: fmt.Sprintf("CheckpointManager contract is initialized"), + }) + + return nil +} diff --git a/command/rootchain/validators/params.go b/command/rootchain/validators/params.go new file mode 100644 index 0000000000..cd2dab159e --- /dev/null +++ b/command/rootchain/validators/params.go @@ -0,0 +1,46 @@ +package validators + +import ( + "bytes" + "fmt" + + "github.com/0xPolygon/polygon-edge/command/helper" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" +) + +type validatorInfoParams struct { + accountDir string + accountConfig string + jsonRPC string + supernetManagerAddress string + stakeManagerAddress string + chainID int64 +} + +func (v *validatorInfoParams) validateFlags() error { + return sidechainHelper.ValidateSecretFlags(v.accountDir, v.accountConfig) +} + +type validatorsInfoResult struct { + address string + stake uint64 + active bool + whitelisted bool +} + +func (vr validatorsInfoResult) GetOutput() string { + var buffer bytes.Buffer + + buffer.WriteString("\n[VALIDATOR INFO]\n") + + vals := make([]string, 4) + vals[0] = fmt.Sprintf("Validator Address|%s", vr.address) + vals[1] = fmt.Sprintf("Stake|%v", vr.stake) + vals[2] = fmt.Sprintf("Is Whitelisted|%v", vr.whitelisted) + vals[3] = fmt.Sprintf("Is Active|%v", vr.active) + + buffer.WriteString(helper.FormatKV(vals)) + buffer.WriteString("\n") + + return buffer.String() +} diff --git a/command/sidechain/validators/validator_info.go b/command/rootchain/validators/validator_info.go similarity index 65% rename from command/sidechain/validators/validator_info.go rename to command/rootchain/validators/validator_info.go index d6af0a050a..94c1a7108b 100644 --- a/command/sidechain/validators/validator_info.go +++ b/command/rootchain/validators/validator_info.go @@ -6,8 +6,10 @@ import ( "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/helper" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" "github.com/spf13/cobra" ) @@ -44,6 +46,27 @@ func setFlags(cmd *cobra.Command) { polybftsecrets.AccountConfigFlagDesc, ) + cmd.Flags().StringVar( + ¶ms.supernetManagerAddress, + rootHelper.SupernetManagerFlag, + "", + rootHelper.SupernetManagerFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.stakeManagerAddress, + rootHelper.StakeManagerFlag, + "", + rootHelper.StakeManagerFlagDesc, + ) + + cmd.Flags().Int64Var( + ¶ms.chainID, + polybftsecrets.ChainIDFlag, + 0, + polybftsecrets.ChainIDFlagDesc, + ) + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) } @@ -68,19 +91,20 @@ func runCommand(cmd *cobra.Command, _ []string) error { } validatorAddr := validatorAccount.Ecdsa.Address() + supernetManagerAddr := types.StringToAddress(params.supernetManagerAddress) + stakeManagerAddr := types.StringToAddress(params.stakeManagerAddress) - validatorInfo, err := sidechainHelper.GetValidatorInfo(validatorAddr, txRelayer) + validatorInfo, err := rootHelper.GetValidatorInfo(validatorAddr, + supernetManagerAddr, stakeManagerAddr, params.chainID, txRelayer) if err != nil { return fmt.Errorf("failed to get validator info for %s: %w", validatorAddr, err) } outputter.WriteCommandResult(&validatorsInfoResult{ - address: validatorInfo.Address.String(), - stake: validatorInfo.Stake.Uint64(), - totalStake: validatorInfo.TotalStake.Uint64(), - commission: validatorInfo.Commission.Uint64(), - withdrawableRewards: validatorInfo.WithdrawableRewards.Uint64(), - active: validatorInfo.Active, + address: validatorInfo.Address.String(), + stake: validatorInfo.Stake.Uint64(), + active: validatorInfo.IsActive, + whitelisted: validatorInfo.IsWhitelisted, }) return nil diff --git a/command/rootchain/whitelist/params.go b/command/rootchain/whitelist/params.go new file mode 100644 index 0000000000..85c68d9ffd --- /dev/null +++ b/command/rootchain/whitelist/params.go @@ -0,0 +1,62 @@ +package whitelist + +import ( + "bytes" + "errors" + "fmt" + + "github.com/0xPolygon/polygon-edge/command/helper" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" +) + +const ( + newValidatorAddressesFlag = "addresses" +) + +var ( + errNoNewValidatorsProvided = errors.New("no new validators addresses provided") +) + +type whitelistParams struct { + accountDir string + accountConfig string + privateKey string + jsonRPC string + newValidatorAddresses []string + supernetManagerAddress string +} + +func (ep *whitelistParams) validateFlags() error { + if len(ep.newValidatorAddresses) == 0 { + return errNoNewValidatorsProvided + } + + if ep.privateKey == "" { + return sidechainHelper.ValidateSecretFlags(ep.accountDir, ep.accountConfig) + } + + // validate jsonrpc address + _, err := helper.ParseJSONRPCAddress(ep.jsonRPC) + + return err +} + +type whitelistResult struct { + newValidatorAddresses []string +} + +func (wr whitelistResult) GetOutput() string { + var buffer bytes.Buffer + + buffer.WriteString("\n[WHITELIST VALIDATORS]\n") + + vals := make([]string, len(wr.newValidatorAddresses)) + for i, addr := range wr.newValidatorAddresses { + vals[i] = fmt.Sprintf("Validator address|%s", addr) + } + + buffer.WriteString(helper.FormatKV(vals)) + buffer.WriteString("\n") + + return buffer.String() +} diff --git a/command/rootchain/whitelist/whitelist_validators.go b/command/rootchain/whitelist/whitelist_validators.go new file mode 100644 index 0000000000..6b6fbc1638 --- /dev/null +++ b/command/rootchain/whitelist/whitelist_validators.go @@ -0,0 +1,156 @@ +package whitelist + +import ( + "fmt" + "time" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/helper" + "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" +) + +var params whitelistParams + +func GetCommand() *cobra.Command { + registerCmd := &cobra.Command{ + Use: "whitelist-validators", + Short: "whitelist new validators", + PreRunE: runPreRun, + RunE: runCommand, + } + + setFlags(registerCmd) + + return registerCmd +} + +func setFlags(cmd *cobra.Command) { + cmd.Flags().StringVar( + ¶ms.accountDir, + polybftsecrets.AccountDirFlag, + "", + polybftsecrets.AccountDirFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.accountConfig, + polybftsecrets.AccountConfigFlag, + "", + polybftsecrets.AccountConfigFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.privateKey, + polybftsecrets.PrivateKeyFlag, + "", + polybftsecrets.PrivateKeyFlagDesc, + ) + + cmd.Flags().StringSliceVar( + ¶ms.newValidatorAddresses, + newValidatorAddressesFlag, + []string{}, + "account addresses of a possible validators", + ) + + cmd.Flags().StringVar( + ¶ms.supernetManagerAddress, + rootHelper.SupernetManagerFlag, + "", + rootHelper.SupernetManagerFlagDesc, + ) + + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.PrivateKeyFlag, polybftsecrets.AccountConfigFlag) + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.PrivateKeyFlag, polybftsecrets.AccountDirFlag) + + helper.RegisterJSONRPCFlag(cmd) +} + +func runPreRun(cmd *cobra.Command, _ []string) error { + params.jsonRPC = helper.GetJSONRPCAddress(cmd) + + return params.validateFlags() +} + +func runCommand(cmd *cobra.Command, _ []string) error { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + ecdsaKey, err := rootHelper.GetECDSAKey(params.privateKey, params.accountDir, params.accountConfig) + if err != nil { + return err + } + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPC), + txrelayer.WithReceiptTimeout(150*time.Millisecond)) + if err != nil { + return fmt.Errorf("whitelist validator failed. Could not create tx relayer: %w", err) + } + + whitelistFn := &contractsapi.WhitelistValidatorsCustomSupernetManagerFn{ + Validators_: stringSliceToAddressSlice(params.newValidatorAddresses), + } + + encoded, err := whitelistFn.EncodeAbi() + if err != nil { + return fmt.Errorf("whitelist validator failed. Could not abi encode whitelist function: %w", err) + } + + supernetAddr := ethgo.Address(types.StringToAddress(params.supernetManagerAddress)) + txn := ðgo.Transaction{ + From: ecdsaKey.Address(), + Input: encoded, + To: &supernetAddr, + } + + receipt, err := txRelayer.SendTransaction(txn, ecdsaKey) + if err != nil { + return fmt.Errorf("whitelist validator failed %w", err) + } + + if receipt.Status == uint64(types.ReceiptFailed) { + return fmt.Errorf("whitelist validator transaction failed on block %d", receipt.BlockNumber) + } + + var ( + whitelistEvent contractsapi.AddedToWhitelistEvent + result = &whitelistResult{} + ) + + for _, log := range receipt.Logs { + doesMatch, err := whitelistEvent.ParseLog(log) + if !doesMatch { + continue + } + + if err != nil { + return err + } + + result.newValidatorAddresses = append(result.newValidatorAddresses, whitelistEvent.Validator.String()) + } + + if len(result.newValidatorAddresses) != len(params.newValidatorAddresses) { + return fmt.Errorf("whitelist of validators did not pass successfully") + } + + outputter.WriteCommandResult(result) + + return nil +} + +func stringSliceToAddressSlice(addrs []string) []ethgo.Address { + res := make([]ethgo.Address, len(addrs)) + for indx, addr := range addrs { + res[indx] = ethgo.Address(types.StringToAddress(addr)) + } + + return res +} diff --git a/command/rootchain/withdraw/params.go b/command/rootchain/withdraw/params.go new file mode 100644 index 0000000000..71c481a5b6 --- /dev/null +++ b/command/rootchain/withdraw/params.go @@ -0,0 +1,55 @@ +package withdraw + +import ( + "bytes" + "fmt" + "math/big" + + "github.com/0xPolygon/polygon-edge/command/helper" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" +) + +var ( + addressToFlag = "to" +) + +type withdrawParams struct { + accountDir string + accountConfig string + jsonRPC string + stakeManagerAddr string + addressTo string + amount string + + amountValue *big.Int +} + +func (v *withdrawParams) validateFlags() (err error) { + if v.amountValue, err = helper.ParseAmount(v.amount); err != nil { + return err + } + + return sidechainHelper.ValidateSecretFlags(v.accountDir, v.accountConfig) +} + +type withdrawResult struct { + validatorAddress string + amount uint64 + withdrawnTo string +} + +func (wr withdrawResult) GetOutput() string { + var buffer bytes.Buffer + + buffer.WriteString("\n[WITHDRAWN AMOUNT]\n") + + vals := make([]string, 0, 3) + vals = append(vals, fmt.Sprintf("Validator Address|%s", wr.validatorAddress)) + vals = append(vals, fmt.Sprintf("Amount Withdrawn|%v", wr.amount)) + vals = append(vals, fmt.Sprintf("Withdrawn To|%s", wr.withdrawnTo)) + + buffer.WriteString(helper.FormatKV(vals)) + buffer.WriteString("\n") + + return buffer.String() +} diff --git a/command/sidechain/whitelist/whitelist_validator.go b/command/rootchain/withdraw/withdraw.go similarity index 53% rename from command/sidechain/whitelist/whitelist_validator.go rename to command/rootchain/withdraw/withdraw.go index 0a1c43811f..d64478eeaf 100644 --- a/command/sidechain/whitelist/whitelist_validator.go +++ b/command/rootchain/withdraw/withdraw.go @@ -1,4 +1,4 @@ -package whitelist +package withdraw import ( "fmt" @@ -7,28 +7,28 @@ import ( "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/helper" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" "github.com/spf13/cobra" "github.com/umbracle/ethgo" ) -var params whitelistParams +var params withdrawParams func GetCommand() *cobra.Command { - registerCmd := &cobra.Command{ - Use: "whitelist-validator", - Short: "whitelist a new validator", + withdrawCmd := &cobra.Command{ + Use: "withdraw-root", + Short: "Withdraws sender's withdrawable amount to specified address on the root chain", PreRunE: runPreRun, RunE: runCommand, } - setFlags(registerCmd) + setFlags(withdrawCmd) - return registerCmd + return withdrawCmd } func setFlags(cmd *cobra.Command) { @@ -47,10 +47,24 @@ func setFlags(cmd *cobra.Command) { ) cmd.Flags().StringVar( - ¶ms.newValidatorAddress, - newValidatorAddressFlag, + ¶ms.addressTo, + addressToFlag, "", - "account address of a possible validator", + "address where to withdraw withdrawable amount", + ) + + cmd.Flags().StringVar( + ¶ms.stakeManagerAddr, + rootHelper.StakeManagerFlag, + "", + rootHelper.StakeManagerFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.amount, + sidechainHelper.AmountFlag, + "", + "amount to withdraw", ) cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) @@ -67,50 +81,54 @@ func runCommand(cmd *cobra.Command, _ []string) error { outputter := command.InitializeOutputter(cmd) defer outputter.WriteOutput() - ownerAccount, err := sidechainHelper.GetAccount(params.accountDir, params.accountConfig) + validatorAccount, err := sidechainHelper.GetAccount(params.accountDir, params.accountConfig) if err != nil { - return fmt.Errorf("enlist validator failed: %w", err) + return err } txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPC), txrelayer.WithReceiptTimeout(150*time.Millisecond)) if err != nil { - return fmt.Errorf("enlist validator failed: %w", err) + return err } - whitelistFn := &contractsapi.AddToWhitelistChildValidatorSetFn{ - WhitelistAddreses: []ethgo.Address{ethgo.Address(types.StringToAddress(params.newValidatorAddress))}, + withdrawFn := &contractsapi.WithdrawStakeStakeManagerFn{ + To: types.StringToAddress(params.addressTo), + Amount: params.amountValue, } - encoded, err := whitelistFn.EncodeAbi() + encoded, err := withdrawFn.EncodeAbi() if err != nil { - return fmt.Errorf("enlist validator failed: %w", err) + return err } + stakeManagerAddr := ethgo.Address(types.StringToAddress(params.stakeManagerAddr)) txn := ðgo.Transaction{ - From: ownerAccount.Ecdsa.Address(), - Input: encoded, - To: (*ethgo.Address)(&contracts.ValidatorSetContract), - GasPrice: sidechainHelper.DefaultGasPrice, + From: validatorAccount.Ecdsa.Address(), + Input: encoded, + To: &stakeManagerAddr, } - receipt, err := txRelayer.SendTransaction(txn, ownerAccount.Ecdsa) + receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa) if err != nil { - return fmt.Errorf("enlist validator failed %w", err) + return err } if receipt.Status == uint64(types.ReceiptFailed) { - return fmt.Errorf("enlist validator transaction failed on block %d", receipt.BlockNumber) + return fmt.Errorf("withdraw transaction failed on block %d", receipt.BlockNumber) + } + + result := &withdrawResult{ + validatorAddress: validatorAccount.Ecdsa.Address().String(), } var ( - whitelistEvent contractsapi.AddedToWhitelistEvent - result = &enlistResult{} - foundLog = false + withdrawalEvent contractsapi.StakeWithdrawnEvent + foundLog bool ) for _, log := range receipt.Logs { - doesMatch, err := whitelistEvent.ParseLog(log) + doesMatch, err := withdrawalEvent.ParseLog(log) if !doesMatch { continue } @@ -119,14 +137,15 @@ func runCommand(cmd *cobra.Command, _ []string) error { return err } - result.newValidatorAddress = whitelistEvent.Validator.String() + result.amount = withdrawalEvent.Amount.Uint64() + result.withdrawnTo = withdrawalEvent.Recipient.String() foundLog = true break } if !foundLog { - return fmt.Errorf("could not find an appropriate log in receipt that enlistment happened") + return fmt.Errorf("could not find an appropriate log in receipt that withdrawal happened") } outputter.WriteCommandResult(result) diff --git a/command/server/config/config.go b/command/server/config/config.go index 65b22424cf..4d4beb2f12 100644 --- a/command/server/config/config.go +++ b/command/server/config/config.go @@ -25,12 +25,12 @@ type Config struct { TxPool *TxPool `json:"tx_pool" yaml:"tx_pool"` LogLevel string `json:"log_level" yaml:"log_level"` RestoreFile string `json:"restore_file" yaml:"restore_file"` - BlockTime uint64 `json:"block_time_s" yaml:"block_time_s"` Headers *Headers `json:"headers" yaml:"headers"` LogFilePath string `json:"log_to" yaml:"log_to"` JSONRPCBatchRequestLimit uint64 `json:"json_rpc_batch_request_limit" yaml:"json_rpc_batch_request_limit"` JSONRPCBlockRangeLimit uint64 `json:"json_rpc_block_range_limit" yaml:"json_rpc_block_range_limit"` JSONLogFormat bool `json:"json_log_format" yaml:"json_log_format"` + CorsAllowedOrigins []string `json:"cors_allowed_origins" yaml:"cors_allowed_origins"` Relayer bool `json:"relayer" yaml:"relayer"` NumBlockConfirmations uint64 `json:"num_block_confirmations" yaml:"num_block_confirmations"` @@ -65,9 +65,6 @@ type Headers struct { } const ( - // DefaultBlockTime minimum block generation time in seconds - DefaultBlockTime uint64 = 2 - // BlockTimeMultiplierForTimeout Multiplier to get IBFT timeout from block time // timeout is calculated when IBFT timeout is not specified BlockTimeMultiplierForTimeout uint64 = 5 @@ -111,7 +108,6 @@ func DefaultConfig() *Config { }, LogLevel: "INFO", RestoreFile: "", - BlockTime: DefaultBlockTime, Headers: &Headers{ AccessControlAllowOrigins: []string{"*"}, }, diff --git a/command/server/init.go b/command/server/init.go index f7e9a8e069..353fbf9bde 100644 --- a/command/server/init.go +++ b/command/server/init.go @@ -19,7 +19,6 @@ import ( ) var ( - errInvalidBlockTime = errors.New("invalid block time specified") errDataDirectoryUndefined = errors.New("data directory not defined") ) @@ -50,10 +49,6 @@ func (p *serverParams) initRawParams() error { return err } - if err := p.initBlockTime(); err != nil { - return err - } - if p.isDevMode { p.initDevMode() } @@ -66,14 +61,6 @@ func (p *serverParams) initRawParams() error { return p.initAddresses() } -func (p *serverParams) initBlockTime() error { - if p.rawConfig.BlockTime < 1 { - return errInvalidBlockTime - } - - return nil -} - func (p *serverParams) initDataDirLocation() error { if p.rawConfig.DataDir == "" { return errDataDirectoryUndefined diff --git a/command/server/params.go b/command/server/params.go index ea5e09dc79..67beee7600 100644 --- a/command/server/params.go +++ b/command/server/params.go @@ -33,7 +33,6 @@ const ( blockGasTargetFlag = "block-gas-target" secretsConfigFlag = "secrets-config" restoreFlag = "restore" - blockTimeFlag = "block-time" devIntervalFlag = "dev-interval" devFlag = "dev" corsOriginFlag = "access-control-allow-origins" @@ -82,8 +81,6 @@ type serverParams struct { devInterval uint64 isDevMode bool - corsAllowedOrigins []string - ibftBaseTimeoutLegacy uint64 genesisConfig *chain.Chain @@ -152,7 +149,7 @@ func (p *serverParams) generateConfig() *server.Config { Chain: p.genesisConfig, JSONRPC: &server.JSONRPC{ JSONRPCAddr: p.jsonRPCAddress, - AccessControlAllowOrigin: p.corsAllowedOrigins, + AccessControlAllowOrigin: p.rawConfig.CorsAllowedOrigins, BatchLengthLimit: p.rawConfig.JSONRPCBatchRequestLimit, BlockRangeLimit: p.rawConfig.JSONRPCBlockRangeLimit, }, @@ -179,7 +176,6 @@ func (p *serverParams) generateConfig() *server.Config { MaxAccountEnqueued: p.rawConfig.TxPool.MaxAccountEnqueued, SecretsManager: p.secretsConfig, RestoreFile: p.getRestoreFilePath(), - BlockTime: p.rawConfig.BlockTime, LogLevel: hclog.LevelFromString(p.rawConfig.LogLevel), JSONLogFormat: p.rawConfig.JSONLogFormat, LogFilePath: p.logFileLocation, diff --git a/command/server/server.go b/command/server/server.go index 90253583a7..b7fa6dbf2d 100644 --- a/command/server/server.go +++ b/command/server/server.go @@ -57,7 +57,7 @@ func setFlags(cmd *cobra.Command) { ¶ms.configPath, configFlag, "", - "the path to the CLI config. Supports .json and .hcl", + "the path to the CLI config. Supports .json, .hcl, .yaml, .yml", ) cmd.Flags().StringVar( @@ -185,15 +185,8 @@ func setFlags(cmd *cobra.Command) { "maximum number of enqueued transactions per account", ) - cmd.Flags().Uint64Var( - ¶ms.rawConfig.BlockTime, - blockTimeFlag, - defaultConfig.BlockTime, - "minimum block time in seconds (at least 1s)", - ) - cmd.Flags().StringArrayVar( - ¶ms.corsAllowedOrigins, + ¶ms.rawConfig.CorsAllowedOrigins, corsOriginFlag, defaultConfig.Headers.AccessControlAllowOrigins, "the CORS header indicating whether any JSON-RPC response can be shared with the specified origin", diff --git a/command/sidechain/helper.go b/command/sidechain/helper.go index 5c2c717140..969489c7f4 100644 --- a/command/sidechain/helper.go +++ b/command/sidechain/helper.go @@ -3,25 +3,21 @@ package sidechain import ( "errors" "fmt" - "math/big" "os" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" "github.com/0xPolygon/polygon-edge/consensus/polybft" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" - "github.com/0xPolygon/polygon-edge/helper/hex" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" "github.com/umbracle/ethgo" ) const ( - SelfFlag = "self" AmountFlag = "amount" - - DefaultGasPrice = 1879048192 // 0x70000000 ) func CheckIfDirectoryExist(dir string) error { @@ -60,65 +56,34 @@ func GetAccountFromDir(accountDir string) (*wallet.Account, error) { return GetAccount(accountDir, "") } -// GetValidatorInfo queries ChildValidatorSet smart contract and retrieves validator info for given address -func GetValidatorInfo(validatorAddr ethgo.Address, txRelayer txrelayer.TxRelayer) (*polybft.ValidatorInfo, error) { - getValidatorMethod := contractsapi.ChildValidatorSet.Abi.GetMethod("getValidator") - - encode, err := getValidatorMethod.Encode([]interface{}{validatorAddr}) - if err != nil { - return nil, err - } - - response, err := txRelayer.Call(ethgo.Address(contracts.SystemCaller), - ethgo.Address(contracts.ValidatorSetContract), encode) +// GetValidatorInfo queries CustomSupernetManager, StakeManager and RewardPool smart contracts +// to retrieve validator info for given address +func GetValidatorInfo(validatorAddr ethgo.Address, supernetManager, stakeManager types.Address, + chainID int64, rootRelayer, childRelayer txrelayer.TxRelayer) (*polybft.ValidatorInfo, error) { + validatorInfo, err := rootHelper.GetValidatorInfo(validatorAddr, supernetManager, stakeManager, + chainID, rootRelayer) if err != nil { return nil, err } - byteResponse, err := hex.DecodeHex(response) - if err != nil { - return nil, fmt.Errorf("unable to decode hex response, %w", err) - } + withdrawableFn := contractsapi.RewardPool.Abi.GetMethod("pendingRewards") - decoded, err := getValidatorMethod.Outputs.Decode(byteResponse) + encode, err := withdrawableFn.Encode([]interface{}{validatorAddr}) if err != nil { return nil, err } - decodedOutputsMap, ok := decoded.(map[string]interface{}) - if !ok { - return nil, fmt.Errorf("could not convert decoded outputs to map") - } - - return &polybft.ValidatorInfo{ - Address: validatorAddr.Address(), - Stake: decodedOutputsMap["stake"].(*big.Int), //nolint:forcetypeassert - TotalStake: decodedOutputsMap["totalStake"].(*big.Int), //nolint:forcetypeassert - Commission: decodedOutputsMap["commission"].(*big.Int), //nolint:forcetypeassert - WithdrawableRewards: decodedOutputsMap["withdrawableRewards"].(*big.Int), //nolint:forcetypeassert - Active: decodedOutputsMap["active"].(bool), //nolint:forcetypeassert - }, nil -} - -// GetDelegatorReward queries delegator reward for given validator and delegator addresses -func GetDelegatorReward(validatorAddr ethgo.Address, delegatorAddr ethgo.Address, - txRelayer txrelayer.TxRelayer) (*big.Int, error) { - input, err := contractsapi.ChildValidatorSet.Abi.Methods["getDelegatorReward"].Encode( - []interface{}{validatorAddr, delegatorAddr}) + response, err := childRelayer.Call(ethgo.ZeroAddress, ethgo.Address(contracts.RewardPoolContract), encode) if err != nil { - return nil, fmt.Errorf("failed to encode input parameters for getDelegatorReward fn: %w", err) + return nil, err } - response, err := txRelayer.Call(ethgo.Address(contracts.SystemCaller), - ethgo.Address(contracts.ValidatorSetContract), input) + withdrawableRewards, err := types.ParseUint256orHex(&response) if err != nil { return nil, err } - delegatorReward, err := types.ParseUint256orHex(&response) - if err != nil { - return nil, fmt.Errorf("unable to decode hex response, %w", err) - } + validatorInfo.WithdrawableRewards = withdrawableRewards - return delegatorReward, nil + return validatorInfo, nil } diff --git a/command/sidechain/registration/params.go b/command/sidechain/registration/params.go deleted file mode 100644 index bc6f5cc2bd..0000000000 --- a/command/sidechain/registration/params.go +++ /dev/null @@ -1,62 +0,0 @@ -package registration - -import ( - "bytes" - "fmt" - - "github.com/0xPolygon/polygon-edge/command/helper" - sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" - "github.com/0xPolygon/polygon-edge/types" -) - -const ( - stakeFlag = "stake" - chainIDFlag = "chain-id" -) - -type registerParams struct { - accountDir string - accountConfig string - jsonRPC string - stake string - chainID int64 -} - -func (rp *registerParams) validateFlags() error { - if err := sidechainHelper.ValidateSecretFlags(rp.accountDir, rp.accountConfig); err != nil { - return err - } - - if rp.stake != "" { - _, err := types.ParseUint256orHex(&rp.stake) - if err != nil { - return fmt.Errorf("provided stake '%s' isn't valid", rp.stake) - } - } - - return nil -} - -type registerResult struct { - validatorAddress string - stakeResult string - amount uint64 -} - -func (rr registerResult) GetOutput() string { - var buffer bytes.Buffer - - var vals []string - - buffer.WriteString("\n[REGISTRATION]\n") - - vals = make([]string, 0, 3) - vals = append(vals, fmt.Sprintf("Validator Address|%s", rr.validatorAddress)) - vals = append(vals, fmt.Sprintf("Staking Result|%s", rr.stakeResult)) - vals = append(vals, fmt.Sprintf("Amount Staked|%v", rr.amount)) - - buffer.WriteString(helper.FormatKV(vals)) - buffer.WriteString("\n") - - return buffer.String() -} diff --git a/command/sidechain/rewards/params.go b/command/sidechain/rewards/params.go new file mode 100644 index 0000000000..6672bff096 --- /dev/null +++ b/command/sidechain/rewards/params.go @@ -0,0 +1,39 @@ +package rewards + +import ( + "bytes" + "fmt" + + "github.com/0xPolygon/polygon-edge/command/helper" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" +) + +type withdrawRewardsParams struct { + accountDir string + accountConfig string + jsonRPC string +} + +type withdrawRewardResult struct { + validatorAddress string + rewardAmount uint64 +} + +func (w *withdrawRewardsParams) validateFlags() error { + return sidechainHelper.ValidateSecretFlags(w.accountDir, w.accountConfig) +} + +func (wr withdrawRewardResult) GetOutput() string { + var buffer bytes.Buffer + + buffer.WriteString("\n[WITHDRAW REWARDS]\n") + + vals := make([]string, 0, 2) + vals = append(vals, fmt.Sprintf("Validator Address|%s", wr.validatorAddress)) + vals = append(vals, fmt.Sprintf("Amount Withdrawn|%v", wr.rewardAmount)) + + buffer.WriteString(helper.FormatKV(vals)) + buffer.WriteString("\n") + + return buffer.String() +} diff --git a/command/sidechain/rewards/rewards.go b/command/sidechain/rewards/rewards.go new file mode 100644 index 0000000000..b46c1fd45d --- /dev/null +++ b/command/sidechain/rewards/rewards.go @@ -0,0 +1,120 @@ +package rewards + +import ( + "fmt" + "time" + + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/helper" + "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" + "github.com/spf13/cobra" + "github.com/umbracle/ethgo" +) + +var params withdrawRewardsParams + +func GetCommand() *cobra.Command { + unstakeCmd := &cobra.Command{ + Use: "withdraw-rewards", + Short: "Withdraws pending rewards on child chain for given validator", + PreRunE: runPreRun, + RunE: runCommand, + } + + helper.RegisterJSONRPCFlag(unstakeCmd) + setFlags(unstakeCmd) + + return unstakeCmd +} + +func setFlags(cmd *cobra.Command) { + cmd.Flags().StringVar( + ¶ms.accountDir, + polybftsecrets.AccountDirFlag, + "", + polybftsecrets.AccountDirFlagDesc, + ) + + cmd.Flags().StringVar( + ¶ms.accountConfig, + polybftsecrets.AccountConfigFlag, + "", + polybftsecrets.AccountConfigFlagDesc, + ) + + cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) +} + +func runPreRun(cmd *cobra.Command, _ []string) error { + params.jsonRPC = helper.GetJSONRPCAddress(cmd) + + return params.validateFlags() +} + +func runCommand(cmd *cobra.Command, _ []string) error { + outputter := command.InitializeOutputter(cmd) + defer outputter.WriteOutput() + + validatorAccount, err := sidechainHelper.GetAccount(params.accountDir, params.accountConfig) + if err != nil { + return err + } + + validatorAddr := validatorAccount.Ecdsa.Address() + rewardPoolAddr := ethgo.Address(contracts.RewardPoolContract) + + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(params.jsonRPC), + txrelayer.WithReceiptTimeout(150*time.Millisecond)) + if err != nil { + return err + } + + encoded, err := contractsapi.RewardPool.Abi.Methods["pendingRewards"].Encode([]interface{}{validatorAddr}) + if err != nil { + return err + } + + response, err := txRelayer.Call(validatorAddr, rewardPoolAddr, encoded) + if err != nil { + return err + } + + amount, err := types.ParseUint256orHex(&response) + if err != nil { + return err + } + + encoded, err = contractsapi.RewardPool.Abi.Methods["withdrawReward"].Encode([]interface{}{}) + if err != nil { + return err + } + + txn := ðgo.Transaction{ + From: validatorAddr, + Input: encoded, + To: &rewardPoolAddr, + } + + receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa) + if err != nil { + return err + } + + if receipt.Status != uint64(types.ReceiptSuccess) { + return fmt.Errorf("withdraw transaction failed on block: %d", receipt.BlockNumber) + } + + result := &withdrawRewardResult{ + validatorAddress: validatorAccount.Ecdsa.Address().String(), + rewardAmount: amount.Uint64(), + } + + outputter.WriteCommandResult(result) + + return nil +} diff --git a/command/sidechain/staking/params.go b/command/sidechain/staking/params.go deleted file mode 100644 index 118edb8b37..0000000000 --- a/command/sidechain/staking/params.go +++ /dev/null @@ -1,59 +0,0 @@ -package staking - -import ( - "bytes" - "fmt" - - "github.com/0xPolygon/polygon-edge/command/helper" - sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" -) - -var ( - delegateAddressFlag = "delegate" -) - -type stakeParams struct { - accountDir string - accountConfig string - jsonRPC string - amount uint64 - self bool - delegateAddress string -} - -func (v *stakeParams) validateFlags() error { - return sidechainHelper.ValidateSecretFlags(v.accountDir, v.accountConfig) -} - -type stakeResult struct { - validatorAddress string - isSelfStake bool - amount uint64 - delegatedTo string -} - -func (sr stakeResult) GetOutput() string { - var buffer bytes.Buffer - - var vals []string - - if sr.isSelfStake { - buffer.WriteString("\n[SELF STAKE]\n") - - vals = make([]string, 0, 2) - vals = append(vals, fmt.Sprintf("Validator Address|%s", sr.validatorAddress)) - vals = append(vals, fmt.Sprintf("Amount Staked|%v", sr.amount)) - } else { - buffer.WriteString("\n[DELEGATED AMOUNT]\n") - - vals = make([]string, 0, 3) - vals = append(vals, fmt.Sprintf("Validator Address|%s", sr.validatorAddress)) - vals = append(vals, fmt.Sprintf("Amount Delegated|%v", sr.amount)) - vals = append(vals, fmt.Sprintf("Delegated To|%s", sr.delegatedTo)) - } - - buffer.WriteString(helper.FormatKV(vals)) - buffer.WriteString("\n") - - return buffer.String() -} diff --git a/command/sidechain/unstaking/params.go b/command/sidechain/unstaking/params.go index 695b260235..4cd0620211 100644 --- a/command/sidechain/unstaking/params.go +++ b/command/sidechain/unstaking/params.go @@ -3,6 +3,7 @@ package unstaking import ( "bytes" "fmt" + "math/big" "github.com/0xPolygon/polygon-edge/command/helper" sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" @@ -13,44 +14,35 @@ var ( ) type unstakeParams struct { - accountDir string - accountConfig string - jsonRPC string - amount uint64 - self bool - undelegateAddress string + accountDir string + accountConfig string + jsonRPC string + amount string + + amountValue *big.Int } -func (v *unstakeParams) validateFlags() error { +func (v *unstakeParams) validateFlags() (err error) { + if v.amountValue, err = helper.ParseAmount(v.amount); err != nil { + return err + } + return sidechainHelper.ValidateSecretFlags(v.accountDir, v.accountConfig) } type unstakeResult struct { validatorAddress string - isSelfUnstake bool amount uint64 - undelegatedFrom string } func (ur unstakeResult) GetOutput() string { var buffer bytes.Buffer - var vals []string + buffer.WriteString("\n[UNSTAKE]\n") - if ur.isSelfUnstake { - buffer.WriteString("\n[SELF UNSTAKE]\n") - - vals = make([]string, 0, 2) - vals = append(vals, fmt.Sprintf("Validator Address|%s", ur.validatorAddress)) - vals = append(vals, fmt.Sprintf("Amount Unstaked|%v", ur.amount)) - } else { - buffer.WriteString("\n[UNDELEGATED AMOUNT]\n") - - vals = make([]string, 0, 3) - vals = append(vals, fmt.Sprintf("Validator Address|%s", ur.validatorAddress)) - vals = append(vals, fmt.Sprintf("Amount Undelegated|%v", ur.amount)) - vals = append(vals, fmt.Sprintf("Undelegated From|%s", ur.undelegatedFrom)) - } + vals := make([]string, 0, 2) + vals = append(vals, fmt.Sprintf("Validator Address|%s", ur.validatorAddress)) + vals = append(vals, fmt.Sprintf("Amount Unstaked|%v", ur.amount)) buffer.WriteString(helper.FormatKV(vals)) buffer.WriteString("\n") diff --git a/command/sidechain/unstaking/unstake.go b/command/sidechain/unstaking/unstake.go index 57ecc7172c..f62fab1c80 100644 --- a/command/sidechain/unstaking/unstake.go +++ b/command/sidechain/unstaking/unstake.go @@ -47,28 +47,13 @@ func setFlags(cmd *cobra.Command) { polybftsecrets.AccountConfigFlagDesc, ) - cmd.Flags().BoolVar( - ¶ms.self, - sidechainHelper.SelfFlag, - false, - "indicates if its a self unstake action", - ) - - cmd.Flags().Uint64Var( + cmd.Flags().StringVar( ¶ms.amount, sidechainHelper.AmountFlag, - 0, - "amount to unstake or undelegate amount from validator", - ) - - cmd.Flags().StringVar( - ¶ms.undelegateAddress, - undelegateAddressFlag, "", - "account address from which amount will be undelegated", + "amount to unstake from validator", ) - cmd.MarkFlagsMutuallyExclusive(sidechainHelper.SelfFlag, undelegateAddressFlag) cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) } @@ -93,25 +78,19 @@ func runCommand(cmd *cobra.Command, _ []string) error { return err } - var encoded []byte - if params.self { - encoded, err = contractsapi.ChildValidatorSet.Abi.Methods["unstake"].Encode([]interface{}{params.amount}) - if err != nil { - return err - } - } else { - encoded, err = contractsapi.ChildValidatorSet.Abi.Methods["undelegate"].Encode( - []interface{}{ethgo.HexToAddress(params.undelegateAddress), params.amount}) - if err != nil { - return err - } + unstakeFn := &contractsapi.UnstakeValidatorSetFn{ + Amount: params.amountValue, + } + + encoded, err := unstakeFn.EncodeAbi() + if err != nil { + return err } txn := ðgo.Transaction{ - From: validatorAccount.Ecdsa.Address(), - Input: encoded, - To: (*ethgo.Address)(&contracts.ValidatorSetContract), - GasPrice: sidechainHelper.DefaultGasPrice, + From: validatorAccount.Ecdsa.Address(), + Input: encoded, + To: (*ethgo.Address)(&contracts.ValidatorSetContract), } receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa) @@ -119,51 +98,36 @@ func runCommand(cmd *cobra.Command, _ []string) error { return err } - if receipt.Status == uint64(types.ReceiptFailed) { - return fmt.Errorf("unstake transaction failed on block %d", receipt.BlockNumber) + if receipt.Status != uint64(types.ReceiptSuccess) { + return fmt.Errorf("unstake transaction failed on block: %d", receipt.BlockNumber) } + var ( + withdrawalRegisteredEvent contractsapi.WithdrawalRegisteredEvent + foundLog bool + ) + result := &unstakeResult{ validatorAddress: validatorAccount.Ecdsa.Address().String(), } - var ( - unstakedEvent contractsapi.UnstakedEvent - undelegatedEvent contractsapi.UndelegatedEvent - foundLog bool - ) - // check the logs to check for the result for _, log := range receipt.Logs { - doesMatch, err := unstakedEvent.ParseLog(log) - if err != nil { - return err - } - - if doesMatch { // its an unstake function call - result.isSelfUnstake = true - result.amount = unstakedEvent.Amount.Uint64() - foundLog = true - - break - } - - doesMatch, err = undelegatedEvent.ParseLog(log) + doesMatch, err := withdrawalRegisteredEvent.ParseLog(log) if err != nil { return err } if doesMatch { - result.amount = undelegatedEvent.Amount.Uint64() - result.undelegatedFrom = undelegatedEvent.Validator.String() foundLog = true + result.amount = withdrawalRegisteredEvent.Amount.Uint64() break } } if !foundLog { - return fmt.Errorf("could not find an appropriate log in receipt that unstake or undelegate happened") + return fmt.Errorf("could not find an appropriate log in receipt that unstake happened (withdrawal registered)") } outputter.WriteCommandResult(result) diff --git a/command/sidechain/validators/params.go b/command/sidechain/validators/params.go deleted file mode 100644 index a69f077d77..0000000000 --- a/command/sidechain/validators/params.go +++ /dev/null @@ -1,47 +0,0 @@ -package validators - -import ( - "bytes" - "fmt" - - "github.com/0xPolygon/polygon-edge/command/helper" - sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" -) - -type validatorInfoParams struct { - accountDir string - accountConfig string - jsonRPC string -} - -func (v *validatorInfoParams) validateFlags() error { - return sidechainHelper.ValidateSecretFlags(v.accountDir, v.accountConfig) -} - -type validatorsInfoResult struct { - address string - stake uint64 - totalStake uint64 - commission uint64 - withdrawableRewards uint64 - active bool -} - -func (vr validatorsInfoResult) GetOutput() string { - var buffer bytes.Buffer - - buffer.WriteString("\n[VALIDATOR INFO]\n") - - vals := make([]string, 0, 5) - vals = append(vals, fmt.Sprintf("Validator Address|%s", vr.address)) - vals = append(vals, fmt.Sprintf("Self Stake|%v", vr.stake)) - vals = append(vals, fmt.Sprintf("Total Stake|%v", vr.totalStake)) - vals = append(vals, fmt.Sprintf("Withdrawable Rewards|%v", vr.withdrawableRewards)) - vals = append(vals, fmt.Sprintf("Commission|%v", vr.commission)) - vals = append(vals, fmt.Sprintf("Is Active|%v", vr.active)) - - buffer.WriteString(helper.FormatKV(vals)) - buffer.WriteString("\n") - - return buffer.String() -} diff --git a/command/sidechain/whitelist/params.go b/command/sidechain/whitelist/params.go deleted file mode 100644 index 50dddcf5bc..0000000000 --- a/command/sidechain/whitelist/params.go +++ /dev/null @@ -1,43 +0,0 @@ -package whitelist - -import ( - "bytes" - "fmt" - - "github.com/0xPolygon/polygon-edge/command/helper" - sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" -) - -var ( - newValidatorAddressFlag = "address" -) - -type whitelistParams struct { - accountDir string - accountConfig string - jsonRPC string - newValidatorAddress string -} - -func (ep *whitelistParams) validateFlags() error { - return sidechainHelper.ValidateSecretFlags(ep.accountDir, ep.accountConfig) -} - -type enlistResult struct { - newValidatorAddress string -} - -func (er enlistResult) GetOutput() string { - var buffer bytes.Buffer - - var vals []string - - buffer.WriteString("\n[ENLIST VALIDATOR]\n") - - vals = append(vals, fmt.Sprintf("Validator Address|%s", er.newValidatorAddress)) - - buffer.WriteString(helper.FormatKV(vals)) - buffer.WriteString("\n") - - return buffer.String() -} diff --git a/command/sidechain/withdraw/params.go b/command/sidechain/withdraw/params.go index c51f2e8bf7..a3ffecceee 100644 --- a/command/sidechain/withdraw/params.go +++ b/command/sidechain/withdraw/params.go @@ -3,41 +3,39 @@ package withdraw import ( "bytes" "fmt" + "math/big" "github.com/0xPolygon/polygon-edge/command/helper" sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" ) -var ( - addressToFlag = "to" -) - type withdrawParams struct { accountDir string accountConfig string jsonRPC string - addressTo string } -func (v *withdrawParams) validateFlags() error { - return sidechainHelper.ValidateSecretFlags(v.accountDir, v.accountConfig) +func (w *withdrawParams) validateFlags() error { + return sidechainHelper.ValidateSecretFlags(w.accountDir, w.accountConfig) } type withdrawResult struct { validatorAddress string - amount uint64 - withdrawnTo string + amount *big.Int + exitEventID *big.Int + blockNumber uint64 } -func (wr withdrawResult) GetOutput() string { +func (r *withdrawResult) GetOutput() string { var buffer bytes.Buffer - buffer.WriteString("\n[WITHDRAWN AMOUNT]\n") + buffer.WriteString("\n[WITHDRAWAL]\n") - vals := make([]string, 0, 3) - vals = append(vals, fmt.Sprintf("Validator Address|%s", wr.validatorAddress)) - vals = append(vals, fmt.Sprintf("Amount Withdrawn|%v", wr.amount)) - vals = append(vals, fmt.Sprintf("Withdrawn To|%s", wr.withdrawnTo)) + vals := make([]string, 0, 4) + vals = append(vals, fmt.Sprintf("Validator Address|%s", r.validatorAddress)) + vals = append(vals, fmt.Sprintf("Amount Withdrawn|%d", r.amount)) + vals = append(vals, fmt.Sprintf("Exit Event ID|%d", r.exitEventID)) + vals = append(vals, fmt.Sprintf("Inclusion Block Number|%d", r.blockNumber)) buffer.WriteString(helper.FormatKV(vals)) buffer.WriteString("\n") diff --git a/command/sidechain/withdraw/withdraw.go b/command/sidechain/withdraw/withdraw.go index 2271716786..a93ec6da23 100644 --- a/command/sidechain/withdraw/withdraw.go +++ b/command/sidechain/withdraw/withdraw.go @@ -5,6 +5,7 @@ import ( "time" "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/bridge/common" "github.com/0xPolygon/polygon-edge/command/helper" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" sidechainHelper "github.com/0xPolygon/polygon-edge/command/sidechain" @@ -19,16 +20,17 @@ import ( var params withdrawParams func GetCommand() *cobra.Command { - withdrawCmd := &cobra.Command{ - Use: "withdraw", - Short: "Withdraws sender's withdrawable amount to specified address", + unstakeCmd := &cobra.Command{ + Use: "withdraw-child", + Short: "Withdraws pending withdrawals on child chain for given validator", PreRunE: runPreRun, RunE: runCommand, } - setFlags(withdrawCmd) + helper.RegisterJSONRPCFlag(unstakeCmd) + setFlags(unstakeCmd) - return withdrawCmd + return unstakeCmd } func setFlags(cmd *cobra.Command) { @@ -46,15 +48,7 @@ func setFlags(cmd *cobra.Command) { polybftsecrets.AccountConfigFlagDesc, ) - cmd.Flags().StringVar( - ¶ms.addressTo, - addressToFlag, - "", - "address where to withdraw withdrawable amount", - ) - cmd.MarkFlagsMutuallyExclusive(polybftsecrets.AccountDirFlag, polybftsecrets.AccountConfigFlag) - helper.RegisterJSONRPCFlag(cmd) } func runPreRun(cmd *cobra.Command, _ []string) error { @@ -78,17 +72,15 @@ func runCommand(cmd *cobra.Command, _ []string) error { return err } - encoded, err := contractsapi.ChildValidatorSet.Abi.Methods["withdraw"].Encode( - []interface{}{ethgo.HexToAddress(params.addressTo)}) + encoded, err := contractsapi.ValidatorSet.Abi.Methods["withdraw"].Encode([]interface{}{}) if err != nil { return err } txn := ðgo.Transaction{ - From: validatorAccount.Ecdsa.Address(), - Input: encoded, - To: (*ethgo.Address)(&contracts.ValidatorSetContract), - GasPrice: sidechainHelper.DefaultGasPrice, + From: validatorAccount.Ecdsa.Address(), + Input: encoded, + To: (*ethgo.Address)(&contracts.ValidatorSetContract), } receipt, err := txRelayer.SendTransaction(txn, validatorAccount.Ecdsa) @@ -96,12 +88,8 @@ func runCommand(cmd *cobra.Command, _ []string) error { return err } - if receipt.Status == uint64(types.ReceiptFailed) { - return fmt.Errorf("withdraw transaction failed on block %d", receipt.BlockNumber) - } - - result := &withdrawResult{ - validatorAddress: validatorAccount.Ecdsa.Address().String(), + if receipt.Status != uint64(types.ReceiptSuccess) { + return fmt.Errorf("withdraw transaction failed on block: %d", receipt.BlockNumber) } var ( @@ -109,28 +97,36 @@ func runCommand(cmd *cobra.Command, _ []string) error { foundLog bool ) + // check the logs to check for the result for _, log := range receipt.Logs { doesMatch, err := withdrawalEvent.ParseLog(log) - if !doesMatch { - continue - } - if err != nil { return err } - result.amount = withdrawalEvent.Amount.Uint64() - result.withdrawnTo = withdrawalEvent.To.String() - foundLog = true + if doesMatch { + foundLog = true - break + break + } } if !foundLog { - return fmt.Errorf("could not find an appropriate log in receipt that withdrawal happened") + return fmt.Errorf("could not find an appropriate log in receipt that withdraw happened on ValidatorSet") + } + + exitEventID, err := common.ExtractExitEventID(receipt) + if err != nil { + return fmt.Errorf("withdrawal failed: %w", err) } - outputter.WriteCommandResult(result) + outputter.WriteCommandResult( + &withdrawResult{ + validatorAddress: validatorAccount.Ecdsa.Address().String(), + amount: withdrawalEvent.Amount, + exitEventID: exitEventID, + blockNumber: receipt.BlockNumber, + }) return nil } diff --git a/command/whitelist/deployment/deployment.go b/command/whitelist/deployment/deployment.go deleted file mode 100644 index 0a350481c2..0000000000 --- a/command/whitelist/deployment/deployment.go +++ /dev/null @@ -1,66 +0,0 @@ -package deployment - -import ( - "fmt" - - "github.com/0xPolygon/polygon-edge/command" - "github.com/spf13/cobra" -) - -func GetCommand() *cobra.Command { - deploymentCmd := &cobra.Command{ - Use: "deployment", - Short: "Top level command for updating smart contract deployment whitelist. Only accepts subcommands", - PreRunE: runPreRun, - Run: runCommand, - } - - setFlags(deploymentCmd) - - return deploymentCmd -} - -func setFlags(cmd *cobra.Command) { - cmd.Flags().StringVar( - ¶ms.genesisPath, - chainFlag, - fmt.Sprintf("./%s", command.DefaultGenesisFileName), - "the genesis file to update", - ) - cmd.Flags().StringArrayVar( - ¶ms.addAddressRaw, - addAddressFlag, - []string{}, - "adds a new address to the contract deployment whitelist", - ) - - cmd.Flags().StringArrayVar( - ¶ms.removeAddressRaw, - removeAddressFlag, - []string{}, - "removes a new address from the contract deployment whitelist", - ) -} - -func runPreRun(_ *cobra.Command, _ []string) error { - return params.initRawParams() -} - -func runCommand(cmd *cobra.Command, _ []string) { - outputter := command.InitializeOutputter(cmd) - defer outputter.WriteOutput() - - if err := params.updateGenesisConfig(); err != nil { - outputter.SetError(err) - - return - } - - if err := params.overrideGenesisConfig(); err != nil { - outputter.SetError(err) - - return - } - - outputter.SetCommandResult(params.getResult()) -} diff --git a/command/whitelist/deployment/params.go b/command/whitelist/deployment/params.go deleted file mode 100644 index 6d7f4619b4..0000000000 --- a/command/whitelist/deployment/params.go +++ /dev/null @@ -1,162 +0,0 @@ -package deployment - -import ( - "fmt" - "os" - - "github.com/0xPolygon/polygon-edge/chain" - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/command/helper" - "github.com/0xPolygon/polygon-edge/helper/config" - "github.com/0xPolygon/polygon-edge/types" -) - -const ( - chainFlag = "chain" - addAddressFlag = "add" - removeAddressFlag = "remove" -) - -var ( - params = &deploymentParams{} -) - -type deploymentParams struct { - // raw addresses, entered by CLI commands - addAddressRaw []string - removeAddressRaw []string - - // addresses, converted from raw addresses - addAddresses []types.Address - removeAddresses []types.Address - - // genesis file - genesisPath string - genesisConfig *chain.Chain - - // deployment whitelist from genesis configuration - whitelist []types.Address -} - -func (p *deploymentParams) initRawParams() error { - // convert raw addresses to appropriate format - if err := p.initRawAddresses(); err != nil { - return err - } - - // init genesis configuration - if err := p.initChain(); err != nil { - return err - } - - return nil -} - -func (p *deploymentParams) initRawAddresses() error { - // convert addresses to be added from string to type.Address - p.addAddresses = unmarshallRawAddresses(p.addAddressRaw) - - // convert addresses to be removed from string to type.Address - p.removeAddresses = unmarshallRawAddresses(p.removeAddressRaw) - - return nil -} - -func (p *deploymentParams) initChain() error { - // import genesis configuration - cc, err := chain.Import(p.genesisPath) - if err != nil { - return fmt.Errorf( - "failed to load chain config from %s: %w", - p.genesisPath, - err, - ) - } - - // set genesis configuration - p.genesisConfig = cc - - return nil -} - -func (p *deploymentParams) updateGenesisConfig() error { - // Fetch contract deployment whitelist from genesis config - deploymentWhitelist, err := config.GetDeploymentWhitelist(p.genesisConfig) - if err != nil { - return err - } - - doesExist := map[types.Address]bool{} - - for _, a := range deploymentWhitelist { - doesExist[a] = true - } - - for _, a := range p.addAddresses { - doesExist[a] = true - } - - for _, a := range p.removeAddresses { - doesExist[a] = false - } - - newDeploymentWhitelist := make([]types.Address, 0) - - for addr, exists := range doesExist { - if exists { - newDeploymentWhitelist = append(newDeploymentWhitelist, addr) - } - } - - // Set whitelist in genesis configuration - whitelistConfig := config.GetWhitelist(p.genesisConfig) - - if whitelistConfig == nil { - whitelistConfig = &chain.Whitelists{} - } - - whitelistConfig.Deployment = newDeploymentWhitelist - p.genesisConfig.Params.Whitelists = whitelistConfig - - // Save whitelist for result - p.whitelist = newDeploymentWhitelist - - return nil -} - -func (p *deploymentParams) overrideGenesisConfig() error { - // Remove the current genesis configuration from the disk - if err := os.Remove(p.genesisPath); err != nil { - return err - } - - // Save the new genesis configuration - if err := helper.WriteGenesisConfigToDisk( - p.genesisConfig, - p.genesisPath, - ); err != nil { - return err - } - - return nil -} - -func (p *deploymentParams) getResult() command.CommandResult { - result := &DeploymentResult{ - AddAddresses: p.addAddresses, - RemoveAddresses: p.removeAddresses, - Whitelist: p.whitelist, - } - - return result -} - -func unmarshallRawAddresses(addresses []string) []types.Address { - marshalledAddresses := make([]types.Address, len(addresses)) - - for indx, address := range addresses { - marshalledAddresses[indx] = types.StringToAddress(address) - } - - return marshalledAddresses -} diff --git a/command/whitelist/deployment/result.go b/command/whitelist/deployment/result.go deleted file mode 100644 index 17ce4dbba3..0000000000 --- a/command/whitelist/deployment/result.go +++ /dev/null @@ -1,32 +0,0 @@ -package deployment - -import ( - "bytes" - "fmt" - - "github.com/0xPolygon/polygon-edge/types" -) - -type DeploymentResult struct { - AddAddresses []types.Address `json:"addAddress,omitempty"` - RemoveAddresses []types.Address `json:"removeAddress,omitempty"` - Whitelist []types.Address `json:"whitelist"` -} - -func (r *DeploymentResult) GetOutput() string { - var buffer bytes.Buffer - - buffer.WriteString("\n[CONTRACT DEPLOYMENT WHITELIST]\n\n") - - if len(r.AddAddresses) != 0 { - buffer.WriteString(fmt.Sprintf("Added addresses: %s,\n", r.AddAddresses)) - } - - if len(r.RemoveAddresses) != 0 { - buffer.WriteString(fmt.Sprintf("Removed addresses: %s,\n", r.RemoveAddresses)) - } - - buffer.WriteString(fmt.Sprintf("Contract deployment whitelist : %s,\n", r.Whitelist)) - - return buffer.String() -} diff --git a/command/whitelist/show/params.go b/command/whitelist/show/params.go deleted file mode 100644 index acc55ab6c7..0000000000 --- a/command/whitelist/show/params.go +++ /dev/null @@ -1,72 +0,0 @@ -package show - -import ( - "fmt" - - "github.com/0xPolygon/polygon-edge/chain" - "github.com/0xPolygon/polygon-edge/command" - "github.com/0xPolygon/polygon-edge/helper/config" - "github.com/0xPolygon/polygon-edge/types" -) - -const ( - chainFlag = "chain" -) - -var ( - params = &showParams{} -) - -type showParams struct { - // genesis file path - genesisPath string - - // deployment whitelist - whitelists Whitelists -} - -type Whitelists struct { - deployment []types.Address -} - -func (p *showParams) initRawParams() error { - // init genesis configuration - if err := p.initWhitelists(); err != nil { - return err - } - - return nil -} - -func (p *showParams) initWhitelists() error { - // import genesis configuration - genesisConfig, err := chain.Import(p.genesisPath) - if err != nil { - return fmt.Errorf( - "failed to load chain config from %s: %w", - p.genesisPath, - err, - ) - } - - // fetch whitelists - deploymentWhitelist, err := config.GetDeploymentWhitelist(genesisConfig) - if err != nil { - return err - } - - // set whitelists - p.whitelists = Whitelists{ - deployment: deploymentWhitelist, - } - - return nil -} - -func (p *showParams) getResult() command.CommandResult { - result := &ShowResult{ - Whitelists: p.whitelists, - } - - return result -} diff --git a/command/whitelist/show/result.go b/command/whitelist/show/result.go deleted file mode 100644 index fbbba91c1e..0000000000 --- a/command/whitelist/show/result.go +++ /dev/null @@ -1,20 +0,0 @@ -package show - -import ( - "bytes" - "fmt" -) - -type ShowResult struct { - Whitelists Whitelists -} - -func (r *ShowResult) GetOutput() string { - var buffer bytes.Buffer - - buffer.WriteString("\n[WHITELISTS]\n\n") - - buffer.WriteString(fmt.Sprintf("Contract deployment whitelist : %s,\n", r.Whitelists.deployment)) - - return buffer.String() -} diff --git a/command/whitelist/show/show.go b/command/whitelist/show/show.go deleted file mode 100644 index 43113aa46c..0000000000 --- a/command/whitelist/show/show.go +++ /dev/null @@ -1,41 +0,0 @@ -package show - -import ( - "fmt" - - "github.com/0xPolygon/polygon-edge/command" - "github.com/spf13/cobra" -) - -func GetCommand() *cobra.Command { - showCmd := &cobra.Command{ - Use: "show", - Short: "Displays whitelist information", - PreRunE: runPreRun, - Run: runCommand, - } - - setFlags(showCmd) - - return showCmd -} - -func setFlags(cmd *cobra.Command) { - cmd.Flags().StringVar( - ¶ms.genesisPath, - chainFlag, - fmt.Sprintf("./%s", command.DefaultGenesisFileName), - "the genesis file to update", - ) -} - -func runPreRun(_ *cobra.Command, _ []string) error { - return params.initRawParams() -} - -func runCommand(cmd *cobra.Command, _ []string) { - outputter := command.InitializeOutputter(cmd) - defer outputter.WriteOutput() - - outputter.SetCommandResult(params.getResult()) -} diff --git a/command/whitelist/whitelist.go b/command/whitelist/whitelist.go deleted file mode 100644 index 42376252f7..0000000000 --- a/command/whitelist/whitelist.go +++ /dev/null @@ -1,25 +0,0 @@ -package whitelist - -import ( - "github.com/0xPolygon/polygon-edge/command/whitelist/deployment" - "github.com/0xPolygon/polygon-edge/command/whitelist/show" - "github.com/spf13/cobra" -) - -func GetCommand() *cobra.Command { - whitelistCmd := &cobra.Command{ - Use: "whitelist", - Short: "Top level command for modifying the Polygon Edge whitelists within the config. Only accepts subcommands.", - } - - registerSubcommands(whitelistCmd) - - return whitelistCmd -} - -func registerSubcommands(baseCmd *cobra.Command) { - baseCmd.AddCommand( - deployment.GetCommand(), - show.GetCommand(), - ) -} diff --git a/consensus/consensus.go b/consensus/consensus.go index c5b49de855..9532d801f4 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -29,7 +29,7 @@ type Consensus interface { GetBlockCreator(header *types.Header) (types.Address, error) // PreCommitState a hook to be called before finalizing state transition on inserting block - PreCommitState(header *types.Header, txn *state.Transition) error + PreCommitState(block *types.Block, txn *state.Transition) error // GetSyncProgression retrieves the current sync progression, if any GetSyncProgression() *progress.Progression @@ -37,6 +37,9 @@ type Consensus interface { // GetBridgeProvider returns an instance of BridgeDataProvider GetBridgeProvider() BridgeDataProvider + // FilterExtra filters extra data in header that is not a part of block hash + FilterExtra(extra []byte) ([]byte, error) + // Initialize initializes the consensus (e.g. setup data) Initialize() error diff --git a/consensus/dev/dev.go b/consensus/dev/dev.go index 38f09648a0..8e09dde42c 100644 --- a/consensus/dev/dev.go +++ b/consensus/dev/dev.go @@ -115,10 +115,10 @@ type transitionInterface interface { Write(txn *types.Transaction) error } -func (d *Dev) writeTransactions(gasLimit uint64, transition transitionInterface) []*types.Transaction { +func (d *Dev) writeTransactions(baseFee, gasLimit uint64, transition transitionInterface) []*types.Transaction { var successful []*types.Transaction - d.txpool.Prepare() + d.txpool.Prepare(baseFee) for { tx := d.txpool.Peek() @@ -126,7 +126,7 @@ func (d *Dev) writeTransactions(gasLimit uint64, transition transitionInterface) break } - if tx.ExceedsBlockGasLimit(gasLimit) { + if tx.Gas > gasLimit { d.txpool.Drop(tx) continue @@ -173,7 +173,10 @@ func (d *Dev) writeNewBlock(parent *types.Header) error { return err } + baseFee := d.blockchain.CalculateBaseFee(parent) + header.GasLimit = gasLimit + header.BaseFee = baseFee miner, err := d.GetBlockCreator(header) if err != nil { @@ -186,10 +189,14 @@ func (d *Dev) writeNewBlock(parent *types.Header) error { return err } - txns := d.writeTransactions(gasLimit, transition) + txns := d.writeTransactions(baseFee, gasLimit, transition) // Commit the changes - _, trace, root := transition.Commit() + _, trace, root, err := transition.Commit() + if err != nil { + return fmt.Errorf("failed to commit the state changes: %w", err) + } + trace.ParentStateRoot = parent.StateRoot // write the trace @@ -249,7 +256,7 @@ func (d *Dev) GetBlockCreator(header *types.Header) (types.Address, error) { } // PreCommitState a hook to be called before finalizing state transition on inserting block -func (d *Dev) PreCommitState(_header *types.Header, _txn *state.Transition) error { +func (d *Dev) PreCommitState(_ *types.Block, _ *state.Transition) error { return nil } @@ -266,3 +273,7 @@ func (d *Dev) Close() error { func (d *Dev) GetBridgeProvider() consensus.BridgeDataProvider { return nil } + +func (d *Dev) FilterExtra(extra []byte) ([]byte, error) { + return extra, nil +} diff --git a/consensus/dummy/dummy.go b/consensus/dummy/dummy.go index fafc2dc6d6..4f552f535b 100644 --- a/consensus/dummy/dummy.go +++ b/consensus/dummy/dummy.go @@ -61,7 +61,7 @@ func (d *Dummy) GetBlockCreator(header *types.Header) (types.Address, error) { } // PreCommitState a hook to be called before finalizing state transition on inserting block -func (d *Dummy) PreCommitState(_header *types.Header, _txn *state.Transition) error { +func (d *Dummy) PreCommitState(_ *types.Block, _ *state.Transition) error { return nil } @@ -79,6 +79,10 @@ func (d *Dummy) GetBridgeProvider() consensus.BridgeDataProvider { return nil } +func (d *Dummy) FilterExtra(extra []byte) ([]byte, error) { + return extra, nil +} + func (d *Dummy) run() { d.logger.Info("started") // do nothing diff --git a/consensus/ibft/consensus_backend.go b/consensus/ibft/consensus_backend.go index 53189cbba3..b30aeaca2c 100644 --- a/consensus/ibft/consensus_backend.go +++ b/consensus/ibft/consensus_backend.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "math/big" "path/filepath" "time" @@ -142,39 +143,21 @@ func (i *backendIBFT) MaximumFaultyNodes() uint64 { return uint64(CalcMaxFaultyNodes(i.currentValidators)) } -func (i *backendIBFT) HasQuorum( - blockNumber uint64, - messages []*proto.Message, - msgType proto.MessageType, -) bool { - validators, err := i.forkManager.GetValidators(blockNumber) +// DISCLAIMER: IBFT will be deprecated so we set 1 as a voting power to all validators +func (i *backendIBFT) GetVotingPowers(height uint64) (map[string]*big.Int, error) { + validators, err := i.forkManager.GetValidators(height) if err != nil { - i.logger.Error( - "failed to get validators when calculation quorum", - "height", blockNumber, - "err", err, - ) - - return false + return nil, err } - quorum := i.quorumSize(blockNumber)(validators) - - switch msgType { - case proto.MessageType_PREPREPARE: - return len(messages) > 0 - case proto.MessageType_PREPARE: - // two cases -> first message is MessageType_PREPREPARE, and other -> MessageType_PREPREPARE is not included - if len(messages) > 0 && messages[0].Type == proto.MessageType_PREPREPARE { - return len(messages) >= quorum - } + result := make(map[string]*big.Int, validators.Len()) - return len(messages) >= quorum-1 - case proto.MessageType_COMMIT, proto.MessageType_ROUND_CHANGE: - return len(messages) >= quorum - default: - return false + for index := 0; index < validators.Len(); index++ { + strAddress := types.AddressToString(validators.At(uint64(index)).Addr()) + result[strAddress] = big.NewInt(1) // set 1 as voting power to everyone } + + return result, nil } // buildBlock builds the block, based on the passed in snapshot and parent header @@ -198,6 +181,9 @@ func (i *backendIBFT) buildBlock(parent *types.Header) (*types.Block, error) { return nil, err } + // calculate base fee + baseFee := i.blockchain.CalculateBaseFee(parent) + header.GasLimit = gasLimit if err := i.currentHooks.ModifyHeader(header, i.currentSigner.Address()); err != nil { @@ -226,16 +212,23 @@ func (i *backendIBFT) buildBlock(parent *types.Header) (*types.Block, error) { txs := i.writeTransactions( writeCtx, + baseFee, gasLimit, header.Number, transition, ) - if err := i.PreCommitState(header, transition); err != nil { + // provide dummy block instance to the PreCommitState + // (for the IBFT consensus, it is correct to have just a header, as only it is used) + if err := i.PreCommitState(&types.Block{Header: header}, transition); err != nil { return nil, err } - _, trace, root := transition.Commit() + _, trace, root, err := transition.Commit() + if err != nil { + return nil, fmt.Errorf("failed to commit the state changes: %w", err) + } + trace.ParentStateRoot = parent.StateRoot // write the trace @@ -318,11 +311,11 @@ type txExeResult struct { type transitionInterface interface { Write(txn *types.Transaction) error - WriteFailedReceipt(txn *types.Transaction) error } func (i *backendIBFT) writeTransactions( writeCtx context.Context, + baseFee, gasLimit, blockNumber uint64, transition transitionInterface, @@ -349,7 +342,7 @@ func (i *backendIBFT) writeTransactions( ) }() - i.txpool.Prepare() + i.txpool.Prepare(baseFee) write: for { @@ -397,18 +390,9 @@ func (i *backendIBFT) writeTransaction( return nil, false } - if tx.ExceedsBlockGasLimit(gasLimit) { + if tx.Gas > gasLimit { i.txpool.Drop(tx) - if err := transition.WriteFailedReceipt(tx); err != nil { - i.logger.Error( - fmt.Sprintf( - "unable to write failed receipt for transaction %s", - tx.Hash, - ), - ) - } - // continue processing return &txExeResult{tx, fail}, true } diff --git a/consensus/ibft/fork/fork.go b/consensus/ibft/fork/fork.go index cf6a4c4090..9d5695a680 100644 --- a/consensus/ibft/fork/fork.go +++ b/consensus/ibft/fork/fork.go @@ -13,10 +13,12 @@ const ( KeyType = "type" KeyTypes = "types" KeyValidatorType = "validator_type" + KeyBlockTime = "blockTime" ) var ( ErrUndefinedIBFTConfig = errors.New("IBFT config is not defined") + errInvalidBlockTime = errors.New("invalid block time provided") ) // IBFT Fork represents setting in params.engine.ibft of genesis.json @@ -26,6 +28,7 @@ type IBFTFork struct { Deployment *common.JSONNumber `json:"deployment,omitempty"` From common.JSONNumber `json:"from"` To *common.JSONNumber `json:"to,omitempty"` + BlockTime *common.Duration `json:"blockTime,omitempty"` // PoA Validators validators.Validators `json:"validators,omitempty"` @@ -42,6 +45,7 @@ func (f *IBFTFork) UnmarshalJSON(data []byte) error { Deployment *common.JSONNumber `json:"deployment,omitempty"` From common.JSONNumber `json:"from"` To *common.JSONNumber `json:"to,omitempty"` + BlockTime *common.Duration `json:"blockTime,omitempty"` Validators interface{} `json:"validators,omitempty"` MaxValidatorCount *common.JSONNumber `json:"maxValidatorCount,omitempty"` MinValidatorCount *common.JSONNumber `json:"minValidatorCount,omitempty"` @@ -55,6 +59,7 @@ func (f *IBFTFork) UnmarshalJSON(data []byte) error { f.Deployment = raw.Deployment f.From = raw.From f.To = raw.To + f.BlockTime = raw.BlockTime f.MaxValidatorCount = raw.MaxValidatorCount f.MinValidatorCount = raw.MinValidatorCount @@ -74,11 +79,7 @@ func (f *IBFTFork) UnmarshalJSON(data []byte) error { return err } - if err := json.Unmarshal(validatorsBytes, f.Validators); err != nil { - return err - } - - return nil + return json.Unmarshal(validatorsBytes, f.Validators) } // GetIBFTForks returns IBFT fork configurations from chain config @@ -98,6 +99,20 @@ func GetIBFTForks(ibftConfig map[string]interface{}) (IBFTForks, error) { } } + var blockTime *common.Duration = nil + + blockTimeGeneric, ok := ibftConfig[KeyBlockTime] + if ok { + blockTimeRaw, err := json.Marshal(blockTimeGeneric) + if err != nil { + return nil, errInvalidBlockTime + } + + if err := json.Unmarshal(blockTimeRaw, &blockTime); err != nil { + return nil, errInvalidBlockTime + } + } + return IBFTForks{ { Type: typ, @@ -105,6 +120,7 @@ func GetIBFTForks(ibftConfig map[string]interface{}) (IBFTForks, error) { ValidatorType: validatorType, From: common.JSONNumber{Value: 0}, To: nil, + BlockTime: blockTime, }, }, nil } diff --git a/consensus/ibft/fork/fork_test.go b/consensus/ibft/fork/fork_test.go index 3c8cf358cb..f77e6c5f91 100644 --- a/consensus/ibft/fork/fork_test.go +++ b/consensus/ibft/fork/fork_test.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "testing" + "time" "github.com/0xPolygon/polygon-edge/helper/common" testHelper "github.com/0xPolygon/polygon-edge/helper/tests" @@ -62,6 +63,7 @@ func TestIBFTForkUnmarshalJSON(t *testing.T) { data: fmt.Sprintf(`{ "type": "%s", "validator_type": "%s", + "blockTime": %d, "validators": [ { "Address": "%s" @@ -72,8 +74,9 @@ func TestIBFTForkUnmarshalJSON(t *testing.T) { ], "from": %d, "to": %d - }`, + }`, PoA, validators.ECDSAValidatorType, + 3000000000, types.StringToAddress("1"), types.StringToAddress("2"), 16, 20, ), @@ -86,6 +89,7 @@ func TestIBFTForkUnmarshalJSON(t *testing.T) { validators.NewECDSAValidator(types.StringToAddress("1")), validators.NewECDSAValidator(types.StringToAddress("2")), ), + BlockTime: &common.Duration{Duration: 3 * time.Second}, MaxValidatorCount: nil, MinValidatorCount: nil, }, diff --git a/consensus/ibft/fork/hooks_test.go b/consensus/ibft/fork/hooks_test.go index e650b3ee8a..db5869a557 100644 --- a/consensus/ibft/fork/hooks_test.go +++ b/consensus/ibft/fork/hooks_test.go @@ -279,6 +279,9 @@ func newTestTransition( ex := state.NewExecutor(&chain.Params{ Forks: chain.AllForksEnabled, + BurnContract: map[uint64]types.Address{ + 0: types.ZeroAddress, + }, }, st, hclog.NewNullLogger()) rootHash, err := ex.WriteGenesis(nil, types.Hash{}) diff --git a/consensus/ibft/ibft.go b/consensus/ibft/ibft.go index 4be216f3d1..5e388e4d4f 100644 --- a/consensus/ibft/ibft.go +++ b/consensus/ibft/ibft.go @@ -34,16 +34,15 @@ const ( ) var ( - ErrInvalidHookParam = errors.New("invalid IBFT hook param passed in") - ErrProposerSealByNonValidator = errors.New("proposer seal by non-validator") - ErrInvalidMixHash = errors.New("invalid mixhash") - ErrInvalidSha3Uncles = errors.New("invalid sha3 uncles") - ErrWrongDifficulty = errors.New("wrong difficulty") - ErrParentCommittedSealsNotFound = errors.New("parent committed seals not found") + ErrInvalidHookParam = errors.New("invalid IBFT hook param passed in") + ErrProposerSealByNonValidator = errors.New("proposer seal by non-validator") + ErrInvalidMixHash = errors.New("invalid mixhash") + ErrInvalidSha3Uncles = errors.New("invalid sha3 uncles") + ErrWrongDifficulty = errors.New("wrong difficulty") ) type txPoolInterface interface { - Prepare() + Prepare(uint64) Length() uint64 Peek() *types.Transaction Pop(tx *types.Transaction) @@ -491,10 +490,10 @@ func (i *backendIBFT) GetBlockCreator(header *types.Header) (types.Address, erro } // PreCommitState a hook to be called before finalizing state transition on inserting block -func (i *backendIBFT) PreCommitState(header *types.Header, txn *state.Transition) error { - hooks := i.forkManager.GetHooks(header.Number) +func (i *backendIBFT) PreCommitState(block *types.Block, txn *state.Transition) error { + hooks := i.forkManager.GetHooks(block.Number()) - return hooks.PreCommitState(header, txn) + return hooks.PreCommitState(block.Header, txn) } // GetEpoch returns the current epoch @@ -552,6 +551,11 @@ func (i *backendIBFT) GetBridgeProvider() consensus.BridgeDataProvider { return nil } +// FilterExtra is the implementation of Consensus interface +func (i *backendIBFT) FilterExtra(extra []byte) ([]byte, error) { + return extra, nil +} + // updateCurrentModules updates Signer, Hooks, and Validators // that are used at specified height // by fetching from ForkManager diff --git a/consensus/polybft/README.md b/consensus/polybft/README.md index 303db1927c..5336609bfa 100644 --- a/consensus/polybft/README.md +++ b/consensus/polybft/README.md @@ -3,90 +3,134 @@ Polybft is a consensus protocol, which runs [go-ibft](https://github.com/0xPolygon/go-ibft) consensus engine. -It has native support for running bridge, which enables running cross-chain transactions with Ethereum-compatible blockchains. +It has a native support for running bridge, which enables running cross-chain transactions with Ethereum-compatible blockchains. ## Setup local testing environment -### Precondition - 1. Build binary ```bash - go build -o polygon-edge . + $ go build -o polygon-edge . ``` 2. Init secrets - this command is used to generate account secrets (ECDSA, BLS as well as P2P networking node id). `--data-dir` denotes folder prefix names and `--num` how many accounts need to be created. **This command is for testing purposes only.** ```bash - polygon-edge polybft-secrets --data-dir test-chain- --num 4 + $ polygon-edge polybft-secrets --data-dir test-chain- --num 4 ``` -3. Start rootchain server - rootchain server is a Geth instance running in dev mode, which simulates Ethereum network. **This command is for testing purposes only.** +3. Create chain configuration - this command creates chain configuration, which is needed to run a blockchain. + It contains initial validator set as well and there are two ways to specify it: + + - all the validators information are present in local storage of single host and therefore directory if provided using `--validators-path` flag and validators folder prefix names using `--validators-prefix` flag + - for reward distribution to work, user must define a reward wallet address with its balance. Wallet address is used to distribute reward tokens from that address to validators that signed blocks in that epoch. ```bash - polygon-edge rootchain server + $ polygon-edge genesis --block-gas-limit 10000000 --epoch-size 10 \ + [--validators-path ./] [--validators-prefix test-chain-] \ + [--consensus polybft] \ + [--reward-wallet adress:amount] ``` -4. Generate manifest file - manifest file contains public validator information as well as bridge configuration. It is intermediary file, which is later used for genesis specification generation as well as rootchain contracts deployment. - - There are two ways to provide validators information: - - - all the validators information are present in local storage of single host and therefore directory if provided using `--validators-path` flag and validators folder prefix names using `--validators-prefix` flag - - ```bash - polygon-edge manifest [--validators-path ./] [--validators-prefix test-chain-] - [--path ./manifest.json] [--premine-validators 100] - ``` - - - validators information are scafollded on multiple hosts and therefore necessary information are supplied using `--validators` flag. Validator information needs to be supplied in the strictly following format: - `:::`. + - validators information are scafollded on multiple hosts and therefore necessary information are supplied using `--validators` flag. Validator information needs to be supplied in the strictly following format: + `:::`. **Note:** when specifying validators via validators flag, entire multi address must be specified. - ```bash - polygon-edge manifest + ```bash + $ polygon-edge genesis --block-gas-limit 10000000 --epoch-size 10 \ --validators /ip4/127.0.0.1/tcp/30301/p2p/16Uiu2HAmV5hqAp77untfJRorxqKmyUxgaVn8YHFjBJm9gKMms3mr:0xDcBe0024206ec42b0Ef4214Ac7B71aeae1A11af0:1cf134e02c6b2afb2ceda50bf2c9a01da367ac48f7783ee6c55444e1cab418ec0f52837b90a4d8cf944814073fc6f2bd96f35366a3846a8393e3cb0b19197cde23e2b40c6401fa27ff7d0c36779d9d097d1393cab6fc1d332f92fb3df850b78703b2989d567d1344e219f0667a1863f52f7663092276770cf513f9704b5351c4:11b18bde524f4b02258a8d196b687f8d8e9490d536718666dc7babca14eccb631c238fb79aa2b44a5a4dceccad2dd797f537008dda185d952226a814c1acf7c2 [--validators /ip4/127.0.0.1/tcp/30302/p2p/16Uiu2HAmGmidRQY5BGJPGVRF8p1pYFdfzuf1StHzXGLDizuxJxex:0x2da750eD4AE1D5A7F7c996Faec592F3d44060e90:088d92c25b5f278750534e8a902da604a1aa39b524b4511f5f47c3a386374ca3031b667beb424faef068a01cee3428a1bc8c1c8bab826f30a1ee03fbe90cb5f01abcf4abd7af3bbe83eaed6f82179b9cbdc417aad65d919b802d91c2e1aaefec27ba747158bc18a0556e39bfc9175c099dd77517a85731894bbea3d191a622bc:08dc3006352fdc01b331907fd3a68d4d68ed40329032598c1c0faa260421d66720965ace3ba29c6d6608ec1facdbf4624bca72df36c34afd4bdd753c4dfe049c] - [--path ./manifest.json] [--premine-validators 100] - ``` + ``` -5. Deploy and initialize rootchain contracts - this command deploys rootchain smart contracts and initializes them. It also updates manifest configuration with rootchain contract addresses and rootchain default sender address. +4. Start rootchain server - rootchain server is a Geth instance running in dev mode, which simulates Ethereum network. **This command is for testing purposes only.** ```bash - polygon-edge rootchain init-contracts - --data-dir | [--config ] - [--manifest ./manifest.json] - [--json-rpc http://127.0.0.1:8545] + $ polygon-edge rootchain server + ``` + +5. Deploy StakeManager - if not already deployed to rootchain. Command has a test flag used only in testing purposes which would deploy a mock ERC20 token which would be used for staking. If not used for testing, stake-token flag should be provided: + + ```bash + $ polygon-edge polybft stake-manager-deploy \ + --deployer-key \ + [--genesis ./genesis.json] \ + [--json-rpc http://127.0.0.1:8545] \ + [--stake-token 0xaddressOfStakeToken] \ [--test] ``` -6. Create chain configuration - this command creates chain configuration, which is needed to run a blockchain +6. Deploy and initialize rootchain contracts - this command deploys rootchain smart contracts and initializes them. It also updates genesis configuration with rootchain contract addresses and rootchain default sender address. ```bash - polygon-edge genesis --block-gas-limit 10000000 --epoch-size 10 - [--consensus polybft] [--bridge-json-rpc ] [--manifest ./manifest.json] + $ polygon-edge rootchain deploy \ + --deployer-key \ + --stake-manager \ + --stake-token 0xaddressOfStakeToken \ + [--genesis ./genesis.json] \ + [--json-rpc http://127.0.0.1:8545] \ + [--test] ``` 7. Fund validators on rootchain - in order for validators to be able to send transactions to Ethereum, they need to be funded in order to be able to cover gas cost. **This command is for testing purposes only.** ```bash - polygon-edge rootchain fund --data-dir test-chain- --num 4 + $ polygon-edge rootchain fund \ + --addresses 0x1234567890123456789012345678901234567890 \ + --amounts 200000000000000000000 + ``` + +8. Whitelist validators on rootchain - in order for validators to be able to be registered on the SupernetManager contract on rootchain. Note that only deployer of SupernetManager contract (the one who run the deploy command) can whitelist validators on rootchain. He can use either its hex encoded private key, or data-dir flag if he has secerets initialized: + + ```bash + $ polygon-edge polybft whitelist-validators --private-key \ + --addresses --supernet-manager + ``` + +9. Register validators on rootchain - each validator registers itself on SupernetManager. **This command is for testing purposes only.** + + ```bash + $ polygon-edge polybft register-validator --data-dir ./test-chain-1 \ + --supernet-manager + ``` + +10. Initial staking on rootchain - each validator needs to do initial staking on rootchain (StakeManager) contract. **This command is for testing purposes only.** + + ```bash + $ polygon-edge polybft stake --data-dir ./test-chain-1 --supernet-id \ + --amount \ + --stake-manager --stake-token + ``` + +11. Finalize genesis validator set on rootchain (SupernetManager) contract. This is done after all validators from genesis do initial staking on rootchain, and it's a final step that is required before starting the child chain. This needs to be done by the deployer of SupernetManager contract (the user that run the deploy command). He can use either its hex encoded private key, or data-dir flag if he has secerets initialized. If enable-staking flag is provided, validators will be able to continue staking on rootchain. If not, genesis validators will not be able update its stake or unstake, nor will newly registered validators after genesis will be able to stake tokens on the rootchain. Enabling of staking can be done through this command, or later after the child chain starts. + + ```bash + $ polygon-edge polybft supernet --private-key \ + --genesis \ + --supernet-manager \ + --stake-manager \ + --finalize-genesis --enable-staking ``` -8. Run (child chain) cluster, consisting of 4 Edge clients in this particular example +12. Run (child chain) cluster, consisting of 4 Edge clients in this particular example ```bash - polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :9545 --seal --log-level DEBUG + $ polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :9545 \ + --seal --log-level DEBUG - polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :5002 --libp2p :30302 --jsonrpc :10002 --seal --log-level DEBUG + $ polygon-edge server --data-dir ./test-chain-2 --chain genesis.json --grpc-address :5002 --libp2p :30302 --jsonrpc :10002 \ + --seal --log-level DEBUG - polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :5003 --libp2p :30303 --jsonrpc :10003 --seal --log-level DEBUG + $ polygon-edge server --data-dir ./test-chain-3 --chain genesis.json --grpc-address :5003 --libp2p :30303 --jsonrpc :10003 \ + --seal --log-level DEBUG - polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :5004 --libp2p :30304 --jsonrpc :10004 --seal --log-level DEBUG + $ polygon-edge server --data-dir ./test-chain-4 --chain genesis.json --grpc-address :5004 --libp2p :30304 --jsonrpc :10004 \ + --seal --log-level DEBUG ``` It is possible to run child chain nodes in "relayer" mode. It allows automatic execution of deposit events on behalf of users. In order to start node in relayer mode, it is necessary to supply `--relayer` flag: ```bash - polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :9545 --seal --log-level DEBUG --relayer + $ polygon-edge server --data-dir ./test-chain-1 --chain genesis.json --grpc-address :5001 --libp2p :30301 --jsonrpc :9545 \ + --seal --log-level DEBUG --relayer ``` diff --git a/consensus/polybft/block_builder.go b/consensus/polybft/block_builder.go index e6f3cd6d17..3ba2f9f251 100644 --- a/consensus/polybft/block_builder.go +++ b/consensus/polybft/block_builder.go @@ -1,6 +1,7 @@ package polybft import ( + "fmt" "time" "github.com/0xPolygon/polygon-edge/consensus" @@ -35,6 +36,9 @@ type BlockBuilderParams struct { // txPoolInterface implementation TxPool txPoolInterface + + // BaseFee is the base fee + BaseFee uint64 } func NewBlockBuilder(params *BlockBuilderParams) *BlockBuilder { @@ -82,6 +86,7 @@ func (b *BlockBuilder) Reset() error { ReceiptsRoot: types.EmptyRootHash, // this avoids needing state for now Sha3Uncles: types.EmptyUncleHash, GasLimit: b.params.GasLimit, + BaseFee: b.params.BaseFee, Timestamp: uint64(headerTime.Unix()), } @@ -108,10 +113,15 @@ func (b *BlockBuilder) Build(handler func(h *types.Header)) (*types.FullBlock, e handler(b.header) } - _, trace, root := b.state.Commit() + _, trace, stateRoot, err := b.state.Commit() + if err != nil { + return nil, fmt.Errorf("failed to commit the state changes: %w", err) + } + trace.ParentStateRoot = b.params.Parent.StateRoot - b.header.StateRoot = root + b.header.StateRoot = stateRoot b.header.GasUsed = b.state.TotalGas() + b.header.LogsBloom = types.CreateBloom(b.Receipts()) // build the block b.block = consensus.BuildBlock(consensus.BuildBlockParams{ @@ -131,10 +141,9 @@ func (b *BlockBuilder) Build(handler func(h *types.Header)) (*types.FullBlock, e // WriteTx applies given transaction to the state. If transaction apply fails, it reverts the saved snapshot. func (b *BlockBuilder) WriteTx(tx *types.Transaction) error { - if tx.ExceedsBlockGasLimit(b.params.GasLimit) { - if err := b.state.WriteFailedReceipt(tx); err != nil { - return err - } + if tx.Gas > b.params.GasLimit { + b.params.Logger.Info("Transaction gas limit exceedes block gas limit", "hash", tx.Hash, + "tx gas limit", tx.Gas, "block gas limt", b.params.GasLimit) return txpool.ErrBlockLimitExceeded } @@ -152,7 +161,7 @@ func (b *BlockBuilder) WriteTx(tx *types.Transaction) error { func (b *BlockBuilder) Fill() { blockTimer := time.NewTimer(b.params.BlockTime) - b.params.TxPool.Prepare() + b.params.TxPool.Prepare(b.params.BaseFee) write: for { select { @@ -187,8 +196,7 @@ func (b *BlockBuilder) writeTxPoolTransaction(tx *types.Transaction) (bool, erro return true, nil } - err := b.WriteTx(tx) - if err != nil { + if err := b.WriteTx(tx); err != nil { if _, ok := err.(*state.GasLimitReachedTransitionApplicationError); ok { //nolint:errorlint // stop processing return true, err diff --git a/consensus/polybft/block_builder_test.go b/consensus/polybft/block_builder_test.go new file mode 100644 index 0000000000..aa4857dbf2 --- /dev/null +++ b/consensus/polybft/block_builder_test.go @@ -0,0 +1,160 @@ +package polybft + +import ( + "math/big" + "testing" + "time" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" + "github.com/0xPolygon/polygon-edge/crypto" + "github.com/0xPolygon/polygon-edge/helper/common" + "github.com/0xPolygon/polygon-edge/state" + itrie "github.com/0xPolygon/polygon-edge/state/immutable-trie" + "github.com/0xPolygon/polygon-edge/types" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" +) + +func TestBlockBuilder_BuildBlockTxOneFailedTxAndOneTakesTooMuchGas(t *testing.T) { + t.Parallel() + + const ( + amount = 1_000 + gasPrice = 1_000 + gasLimit = 21000 + blockGasLimit = 21000 * 3 + chainID = 100 + ) + + accounts := [6]*wallet.Account{} + + for i := range accounts { + accounts[i] = generateTestAccount(t) + } + + forks := &chain.Forks{} + logger := hclog.NewNullLogger() + signer := crypto.NewSigner(forks.At(0), chainID) + + mchain := &chain.Chain{ + Params: &chain.Params{ + ChainID: chainID, + Forks: forks, + }, + } + + mstate := itrie.NewState(itrie.NewMemoryStorage()) + executor := state.NewExecutor(mchain.Params, mstate, logger) + + executor.GetHash = func(header *types.Header) func(i uint64) types.Hash { + return func(i uint64) (res types.Hash) { + return types.BytesToHash(common.EncodeUint64ToBytes(i)) + } + } + + balanceMap := map[types.Address]*chain.GenesisAccount{} + + for i, acc := range accounts { + // the third tx will fail because of insufficient balance + if i != 2 { + balanceMap[types.Address(acc.Ecdsa.Address())] = &chain.GenesisAccount{ + Balance: ethgo.Ether(1), + } + } + } + + hash, err := executor.WriteGenesis(balanceMap, types.ZeroHash) + + require.NoError(t, err) + require.NotEqual(t, types.ZeroHash, hash) + + // Gas Limit is important to be high for tx pool + parentHeader := &types.Header{StateRoot: hash, GasLimit: 1_000_000_000_000_000} + + txPool := &txPoolMock{} + txPool.On("Prepare", uint64(0)).Once() + + for i, acc := range accounts { + receiver := types.Address(acc.Ecdsa.Address()) + privateKey, err := acc.GetEcdsaPrivateKey() + + require.NoError(t, err) + + tx := &types.Transaction{ + Value: big.NewInt(amount), + GasPrice: big.NewInt(gasPrice), + Gas: gasLimit, + Nonce: 0, + To: &receiver, + } + + // fifth tx will cause filling to stop + if i == 4 { + tx.Gas = blockGasLimit - 1 + } + + tx, err = signer.SignTx(tx, privateKey) + require.NoError(t, err) + + // all tx until the fifth will be retrieved from the pool + if i <= 4 { + txPool.On("Peek").Return(tx).Once() + } + + // first two and fourth will be added to the block, third will be demoted + if i == 2 { + txPool.On("Demote", tx) + } else if i < 4 { + txPool.On("Pop", tx) + } + } + + bb := NewBlockBuilder(&BlockBuilderParams{ + BlockTime: time.Millisecond * 100, + Parent: parentHeader, + Coinbase: types.ZeroAddress, + Executor: executor, + GasLimit: blockGasLimit, + TxPool: txPool, + Logger: logger, + }) + + require.NoError(t, bb.Reset()) + + bb.Fill() + + fb, err := bb.Build(func(h *types.Header) { + // fake the logs for bloom + rs := bb.Receipts() + + if len(rs) == 3 { + rs[0].Logs = []*types.Log{ + {Address: types.StringToAddress("ff7783")}, + } + rs[1].Logs = []*types.Log{ + {Address: types.StringToAddress("03bbcc")}, + {Address: types.StringToAddress("112233")}, + } + } + }) + require.NoError(t, err) + + txPool.AssertExpectations(t) + require.Len(t, bb.txns, 3, "Should have 3 transactions but has %d", len(bb.txns)) + require.Len(t, bb.Receipts(), 3) + + // assert logs bloom + for _, r := range bb.Receipts() { + for _, l := range r.Logs { + assert.True(t, fb.Block.Header.LogsBloom.IsLogInBloom(l)) + } + } + + assert.False(t, fb.Block.Header.LogsBloom.IsLogInBloom( + &types.Log{Address: types.StringToAddress("999911117777")})) + assert.False(t, fb.Block.Header.LogsBloom.IsLogInBloom( + &types.Log{Address: types.StringToAddress("111177779999")})) +} diff --git a/consensus/polybft/blockchain_wrapper.go b/consensus/polybft/blockchain_wrapper.go index 1d6e4dd3d4..b7afd686b7 100644 --- a/consensus/polybft/blockchain_wrapper.go +++ b/consensus/polybft/blockchain_wrapper.go @@ -38,8 +38,7 @@ type blockchainBackend interface { txPool txPoolInterface, blockTime time.Duration, logger hclog.Logger) (blockBuilder, error) // ProcessBlock builds a final block from given 'block' on top of 'parent'. - ProcessBlock(parent *types.Header, block *types.Block, - callback func(*state.Transition) error) (*types.FullBlock, error) + ProcessBlock(parent *types.Header, block *types.Block) (*types.FullBlock, error) // GetStateProviderForBlock returns a reference to make queries to the state at 'block'. GetStateProviderForBlock(block *types.Header) (contract.Provider, error) @@ -60,6 +59,9 @@ type blockchainBackend interface { // GetChainID returns chain id of the current blockchain GetChainID() uint64 + + // GetReceiptsByHash retrieves receipts by hash + GetReceiptsByHash(hash types.Hash) ([]*types.Receipt, error) } var _ blockchainBackend = &blockchainWrapper{} @@ -76,17 +78,13 @@ func (p *blockchainWrapper) CurrentHeader() *types.Header { // CommitBlock commits a block to the chain func (p *blockchainWrapper) CommitBlock(block *types.FullBlock) error { - if err := p.blockchain.WriteFullBlock(block, consensusSource); err != nil { - return err - } - - return nil + return p.blockchain.WriteFullBlock(block, consensusSource) } // ProcessBlock builds a final block from given 'block' on top of 'parent' -func (p *blockchainWrapper) ProcessBlock(parent *types.Header, block *types.Block, - callback func(*state.Transition) error) (*types.FullBlock, error) { +func (p *blockchainWrapper) ProcessBlock(parent *types.Header, block *types.Block) (*types.FullBlock, error) { header := block.Header.Copy() + start := time.Now().UTC() transition, err := p.executor.BeginTxn(parent.StateRoot, header, types.BytesToAddress(header.Miner)) if err != nil { @@ -95,20 +93,20 @@ func (p *blockchainWrapper) ProcessBlock(parent *types.Header, block *types.Bloc // apply transactions from block for _, tx := range block.Transactions { - if err := transition.Write(tx); err != nil { + if err = transition.Write(tx); err != nil { return nil, fmt.Errorf("process block tx error, tx = %v, err = %w", tx.Hash, err) } } - if callback != nil { - if err := callback(transition); err != nil { - return nil, err - } + _, trace, root, err := transition.Commit() + if err != nil { + return nil, fmt.Errorf("failed to commit the state changes: %w", err) } - _, trace, root := transition.Commit() trace.ParentStateRoot = parent.StateRoot + updateBlockExecutionMetric(start) + if root != block.Header.StateRoot { return nil, fmt.Errorf("incorrect state root: (%s, %s)", root, block.Header.StateRoot) } @@ -167,6 +165,7 @@ func (p *blockchainWrapper) NewBlockBuilder( Coinbase: coinbase, Executor: p.executor, GasLimit: gasLimit, + BaseFee: p.blockchain.CalculateBaseFee(parent), TxPool: txPool, Logger: logger, }), nil @@ -185,6 +184,10 @@ func (p *blockchainWrapper) GetChainID() uint64 { return uint64(p.blockchain.Config().ChainID) } +func (p *blockchainWrapper) GetReceiptsByHash(hash types.Hash) ([]*types.Receipt, error) { + return p.blockchain.GetReceiptsByHash(hash) +} + var _ contract.Provider = &stateProvider{} type stateProvider struct { diff --git a/consensus/polybft/checkpoint_manager.go b/consensus/polybft/checkpoint_manager.go index 4b058b83f7..3544e6d4ee 100644 --- a/consensus/polybft/checkpoint_manager.go +++ b/consensus/polybft/checkpoint_manager.go @@ -9,6 +9,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/helper/hex" "github.com/0xPolygon/polygon-edge/merkle-tree" @@ -196,7 +197,7 @@ func (c *checkpointManager) encodeAndSendCheckpoint(txn *ethgo.Transaction, header *types.Header, extra *Extra, isEndOfEpoch bool) error { c.logger.Debug("send checkpoint txn...", "block number", header.Number) - nextEpochValidators := AccountSet{} + nextEpochValidators := validator.AccountSet{} if isEndOfEpoch { var err error @@ -232,7 +233,7 @@ func (c *checkpointManager) encodeAndSendCheckpoint(txn *ethgo.Transaction, // abiEncodeCheckpointBlock encodes checkpoint data into ABI format for a given header func (c *checkpointManager) abiEncodeCheckpointBlock(blockNumber uint64, blockHash types.Hash, extra *Extra, - nextValidators AccountSet) ([]byte, error) { + nextValidators validator.AccountSet) ([]byte, error) { aggs, err := bls.UnmarshalSignature(extra.Committed.AggregatedSignature) if err != nil { return nil, err diff --git a/consensus/polybft/checkpoint_manager_test.go b/consensus/polybft/checkpoint_manager_test.go index 34595a8d71..7648eba1b0 100644 --- a/consensus/polybft/checkpoint_manager_test.go +++ b/consensus/polybft/checkpoint_manager_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/umbracle/ethgo/abi" + "github.com/umbracle/ethgo/jsonrpc" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/contracts" @@ -18,9 +19,9 @@ import ( "github.com/stretchr/testify/require" "github.com/umbracle/ethgo" - "github.com/0xPolygon/polygon-edge/consensus/ibft/signer" "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" @@ -36,8 +37,8 @@ func TestCheckpointManager_SubmitCheckpoint(t *testing.T) { var aliases = []string{"A", "B", "C", "D", "E"} - validators := newTestValidatorsWithAliases(t, aliases) - validatorsMetadata := validators.getPublicIdentities() + validators := validator.NewTestValidatorsWithAliases(t, aliases) + validatorsMetadata := validators.GetPublicIdentities() txRelayerMock := newDummyTxRelayer(t) txRelayerMock.On("Call", mock.Anything, mock.Anything, mock.Anything). Return("2", error(nil)). @@ -59,9 +60,9 @@ func TestCheckpointManager_SubmitCheckpoint(t *testing.T) { signatures bls.Signatures ) - validators.iterAcct(aliases, func(t *testValidator) { + validators.IterAcct(aliases, func(t *validator.TestValidator) { bitmap.Set(idx) - signatures = append(signatures, t.mustSign(dummyMsg, bls.DomainCheckpointManager)) + signatures = append(signatures, t.MustSign(dummyMsg, bls.DomainCheckpointManager)) idx++ }) @@ -80,7 +81,7 @@ func TestCheckpointManager_SubmitCheckpoint(t *testing.T) { extra.Checkpoint = checkpoint extra.Committed = &Signature{Bitmap: bitmap, AggregatedSignature: signature} header = &types.Header{ - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + ExtraData: extra.MarshalRLPTo(nil), } epochNumber++ } else { @@ -96,7 +97,7 @@ func TestCheckpointManager_SubmitCheckpoint(t *testing.T) { blockchainMock := new(blockchainMock) blockchainMock.On("GetHeaderByNumber", mock.Anything).Return(headersMap.getHeader) - validatorAcc := validators.getValidator("A") + validatorAcc := validators.GetValidator("A") c := &checkpointManager{ key: wallet.NewEcdsaSigner(validatorAcc.Key()), rootChainRelayer: txRelayerMock, @@ -122,8 +123,8 @@ func TestCheckpointManager_abiEncodeCheckpointBlock(t *testing.T) { const epochSize = uint64(10) - currentValidators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D"}) - nextValidators := newTestValidatorsWithAliases(t, []string{"E", "F", "G", "H"}) + currentValidators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D"}) + nextValidators := validator.NewTestValidatorsWithAliases(t, []string{"E", "F", "G", "H"}) header := &types.Header{Number: 50} checkpoint := &CheckpointData{ BlockRound: 1, @@ -138,8 +139,8 @@ func TestCheckpointManager_abiEncodeCheckpointBlock(t *testing.T) { var signatures bls.Signatures - currentValidators.iterAcct(nil, func(v *testValidator) { - signatures = append(signatures, v.mustSign(proposalHash, bls.DomainCheckpointManager)) + currentValidators.IterAcct(nil, func(v *validator.TestValidator) { + signatures = append(signatures, v.MustSign(proposalHash, bls.DomainCheckpointManager)) bmp.Set(i) i++ }) @@ -152,18 +153,18 @@ func TestCheckpointManager_abiEncodeCheckpointBlock(t *testing.T) { AggregatedSignature: aggSignature, Bitmap: bmp, } - header.ExtraData = append(make([]byte, signer.IstanbulExtraVanity), extra.MarshalRLPTo(nil)...) + header.ExtraData = extra.MarshalRLPTo(nil) header.ComputeHash() backendMock := new(polybftBackendMock) - backendMock.On("GetValidators", mock.Anything, mock.Anything).Return(currentValidators.getPublicIdentities()) + backendMock.On("GetValidators", mock.Anything, mock.Anything).Return(currentValidators.GetPublicIdentities()) c := &checkpointManager{ blockchain: &blockchainMock{}, consensusBackend: backendMock, logger: hclog.NewNullLogger(), } - checkpointDataEncoded, err := c.abiEncodeCheckpointBlock(header.Number, header.Hash, extra, nextValidators.getPublicIdentities()) + checkpointDataEncoded, err := c.abiEncodeCheckpointBlock(header.Number, header.Hash, extra, nextValidators.GetPublicIdentities()) require.NoError(t, err) submit := &contractsapi.SubmitCheckpointManagerFn{} @@ -486,7 +487,7 @@ func newDummyTxRelayer(t *testing.T) *dummyTxRelayer { return &dummyTxRelayer{test: t} } -func (d dummyTxRelayer) Call(from ethgo.Address, to ethgo.Address, input []byte) (string, error) { +func (d *dummyTxRelayer) Call(from ethgo.Address, to ethgo.Address, input []byte) (string, error) { args := d.Called(from, to, input) return args.String(0), args.Error(1) @@ -507,6 +508,10 @@ func (d *dummyTxRelayer) SendTransactionLocal(txn *ethgo.Transaction) (*ethgo.Re return args.Get(0).(*ethgo.Receipt), args.Error(1) //nolint:forcetypeassert } +func (d *dummyTxRelayer) Client() *jsonrpc.Client { + return nil +} + func getBlockNumberCheckpointSubmitInput(t *testing.T, input []byte) uint64 { t.Helper() diff --git a/consensus/polybft/consensus_metrics.go b/consensus/polybft/consensus_metrics.go index 29a916abca..6173af5d5e 100644 --- a/consensus/polybft/consensus_metrics.go +++ b/consensus/polybft/consensus_metrics.go @@ -34,6 +34,7 @@ func updateBlockMetrics(currentBlock *types.Block, parentHeader *types.Header) e metrics.SetGauge([]string{consensusMetricsPrefix, "rounds"}, float32(extra.Checkpoint.BlockRound)) metrics.SetGauge([]string{consensusMetricsPrefix, "chain_head"}, float32(currentBlock.Number())) metrics.IncrCounter([]string{consensusMetricsPrefix, "block_counter"}, float32(1)) + metrics.SetGauge([]string{consensusMetricsPrefix, "block_space_used"}, float32(currentBlock.Header.GasUsed)) return nil } @@ -46,3 +47,9 @@ func updateEpochMetrics(epoch epochMetadata) { // update number of validators metrics metrics.SetGauge([]string{consensusMetricsPrefix, "validators"}, float32(epoch.Validators.Len())) } + +// updateBlockExecutionMetric updates the block execution metric +func updateBlockExecutionMetric(start time.Time) { + metrics.SetGauge([]string{consensusMetricsPrefix, "block_execution_time"}, + float32(time.Now().UTC().Sub(start).Seconds())) +} diff --git a/consensus/polybft/consensus_runtime.go b/consensus/polybft/consensus_runtime.go index ad19d0d665..7f23b1b7fd 100644 --- a/consensus/polybft/consensus_runtime.go +++ b/consensus/polybft/consensus_runtime.go @@ -11,7 +11,9 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" + "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" @@ -35,7 +37,7 @@ var ( // txPoolInterface is an abstraction of transaction pool type txPoolInterface interface { - Prepare() + Prepare(uint64) Length() uint64 Peek() *types.Transaction Pop(*types.Transaction) @@ -53,7 +55,7 @@ type epochMetadata struct { FirstBlockInEpoch uint64 // Validators is the set of validators for the epoch - Validators AccountSet + Validators validator.AccountSet } type guardedDataDTO struct { @@ -101,7 +103,7 @@ type consensusRuntime struct { lastBuiltBlock *types.Header // activeValidatorFlag indicates whether the given node is amongst currently active validator set - activeValidatorFlag uint32 + activeValidatorFlag atomic.Bool // checkpointManager represents abstraction for checkpoint submission checkpointManager CheckpointManager @@ -112,6 +114,9 @@ type consensusRuntime struct { // manager for state sync bridge transactions stateSyncManager StateSyncManager + // manager for handling validator stake change and updating validator set + stakeManager StakeManager + // logger instance logger hcf.Logger } @@ -139,6 +144,10 @@ func newConsensusRuntime(log hcf.Logger, config *runtimeConfig) (*consensusRunti return nil, err } + if err := runtime.initStakeManager(log); err != nil { + return nil, err + } + // we need to call restart epoch on runtime to initialize epoch state runtime.epoch, err = runtime.restartEpoch(runtime.lastBuiltBlock) if err != nil { @@ -157,8 +166,8 @@ func (c *consensusRuntime) close() { // if bridge is not enabled, then a dummy state sync manager will be used func (c *consensusRuntime) initStateSyncManager(logger hcf.Logger) error { if c.IsBridgeEnabled() { - stateSenderAddr := c.config.PolyBFTConfig.Bridge.BridgeAddr - stateSyncManager, err := newStateSyncManager( + stateSenderAddr := c.config.PolyBFTConfig.Bridge.StateSenderAddr + stateSyncManager := newStateSyncManager( logger.Named("state-sync-manager"), c.config.State, &stateSyncConfig{ @@ -173,10 +182,6 @@ func (c *consensusRuntime) initStateSyncManager(logger hcf.Logger) error { }, ) - if err != nil { - return err - } - c.stateSyncManager = stateSyncManager } else { c.stateSyncManager = &dummyStateSyncManager{} @@ -198,7 +203,7 @@ func (c *consensusRuntime) initCheckpointManager(logger hcf.Logger) error { c.checkpointManager = newCheckpointManager( wallet.NewEcdsaSigner(c.config.Key), defaultCheckpointsOffset, - c.config.PolyBFTConfig.Bridge.CheckpointAddr, + c.config.PolyBFTConfig.Bridge.CheckpointManagerAddr, txRelayer, c.config.blockchain, c.config.polybftBackend, @@ -211,6 +216,27 @@ func (c *consensusRuntime) initCheckpointManager(logger hcf.Logger) error { return nil } +// initStakeManager initializes stake manager +func (c *consensusRuntime) initStakeManager(logger hcf.Logger) error { + rootRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(c.config.PolyBFTConfig.Bridge.JSONRPCEndpoint)) + if err != nil { + return err + } + + c.stakeManager = newStakeManager( + logger.Named("stake-manager"), + c.state, + rootRelayer, + wallet.NewEcdsaSigner(c.config.Key), + contracts.ValidatorSetContract, + c.config.PolyBFTConfig.Bridge.CustomSupernetManagerAddr, + c.config.blockchain, + int(c.config.PolyBFTConfig.MaxValidatorSetSize), + ) + + return nil +} + // getGuardedData returns last build block, proposer snapshot and current epochMetadata in a thread-safe manner. func (c *consensusRuntime) getGuardedData() (guardedDataDTO, error) { c.lock.RLock() @@ -258,8 +284,8 @@ func (c *consensusRuntime) OnBlockInserted(fullBlock *types.FullBlock) { var ( epoch = c.epoch err error - //nolint:godox - // TODO - this will need to take inconsideration if slashing occurred (to be fixed in EVM-519) + // calculation of epoch and sprint end does not consider slashing currently + isEndOfEpoch = c.isFixedSizeOfEpochMet(fullBlock.Block.Header.Number, epoch) ) @@ -280,6 +306,11 @@ func (c *consensusRuntime) OnBlockInserted(fullBlock *types.FullBlock) { c.logger.Error("Could not update proposer calculator", "err", err) } + // handle transfer events that happened in block + if err := c.stakeManager.PostBlock(postBlock); err != nil { + c.logger.Error("failed to post block in stake manager", "err", err) + } + if isEndOfEpoch { if epoch, err = c.restartEpoch(fullBlock.Block.Header); err != nil { c.logger.Error("failed to restart epoch after block inserted", "error", err) @@ -310,7 +341,7 @@ func (c *consensusRuntime) FSM() error { parent, types.Address(c.config.Key.Address()), c.config.txPool, - c.config.PolyBFTConfig.BlockTime, + c.config.PolyBFTConfig.BlockTime.Duration, c.logger, ) @@ -318,15 +349,12 @@ func (c *consensusRuntime) FSM() error { return fmt.Errorf("cannot create block builder for fsm: %w", err) } - //nolint:godox - // TODO - recognize slashing occurred (to be fixed in EVM-519) - slash := false - pendingBlockNumber := parent.Number + 1 - isEndOfSprint := slash || c.isFixedSizeOfSprintMet(pendingBlockNumber, epoch) - isEndOfEpoch := slash || c.isFixedSizeOfEpochMet(pendingBlockNumber, epoch) + // calculation of epoch and sprint end does not consider slashing currently + isEndOfSprint := c.isFixedSizeOfSprintMet(pendingBlockNumber, epoch) + isEndOfEpoch := c.isFixedSizeOfEpochMet(pendingBlockNumber, epoch) - valSet := NewValidatorSet(epoch.Validators, c.logger) + valSet := validator.NewValidatorSet(epoch.Validators, c.logger) exitRootHash, err := c.checkpointManager.BuildEventRoot(epoch.Number) if err != nil { @@ -358,10 +386,15 @@ func (c *consensusRuntime) FSM() error { } if isEndOfEpoch { - ff.commitEpochInput, err = c.calculateCommitEpochInput(parent, epoch) + ff.commitEpochInput, ff.distributeRewardsInput, err = c.calculateCommitEpochInput(parent, epoch) if err != nil { return fmt.Errorf("cannot calculate commit epoch info: %w", err) } + + ff.newValidatorsDelta, err = c.stakeManager.UpdateValidatorSet(epoch.Number, epoch.Validators.Copy()) + if err != nil { + return fmt.Errorf("cannot update validator set on epoch ending: %w", err) + } } c.logger.Info( @@ -436,13 +469,17 @@ func (c *consensusRuntime) restartEpoch(header *types.Header) (*epochMetadata, e SystemState: systemState, NewEpochID: epochNumber, FirstBlockOfEpoch: firstBlockInEpoch, - ValidatorSet: NewValidatorSet(validatorSet, c.logger), + ValidatorSet: validator.NewValidatorSet(validatorSet, c.logger), } if err := c.stateSyncManager.PostEpoch(reqObj); err != nil { return nil, err } + if err := c.stakeManager.PostEpoch(reqObj); err != nil { + return nil, err + } + return &epochMetadata{ Number: epochNumber, Validators: validatorSet, @@ -454,13 +491,15 @@ func (c *consensusRuntime) restartEpoch(header *types.Header) (*epochMetadata, e // in the current epoch, and ending at the last block of previous epoch func (c *consensusRuntime) calculateCommitEpochInput( currentBlock *types.Header, - epoch *epochMetadata) (*contractsapi.CommitEpochChildValidatorSetFn, error) { + epoch *epochMetadata, +) (*contractsapi.CommitEpochValidatorSetFn, + *contractsapi.DistributeRewardForRewardPoolFn, error) { uptimeCounter := map[types.Address]int64{} blockHeader := currentBlock epochID := epoch.Number totalBlocks := int64(0) - getSealersForBlock := func(blockExtra *Extra, validators AccountSet) error { + getSealersForBlock := func(blockExtra *Extra, validators validator.AccountSet) error { signers, err := validators.GetFilteredValidators(blockExtra.Parent.Bitmap) if err != nil { return err @@ -477,18 +516,18 @@ func (c *consensusRuntime) calculateCommitEpochInput( blockExtra, err := GetIbftExtra(currentBlock.ExtraData) if err != nil { - return nil, err + return nil, nil, err } // calculate uptime for current epoch for blockHeader.Number > epoch.FirstBlockInEpoch { if err := getSealersForBlock(blockExtra, epoch.Validators); err != nil { - return nil, err + return nil, nil, err } blockHeader, blockExtra, err = getBlockData(blockHeader.Number-1, c.config.blockchain) if err != nil { - return nil, err + return nil, nil, err } } @@ -498,25 +537,20 @@ func (c *consensusRuntime) calculateCommitEpochInput( for i := 0; i < commitEpochLookbackSize; i++ { validators, err := c.config.polybftBackend.GetValidators(blockHeader.Number-2, nil) if err != nil { - return nil, err + return nil, nil, err } if err := getSealersForBlock(blockExtra, validators); err != nil { - return nil, err + return nil, nil, err } blockHeader, blockExtra, err = getBlockData(blockHeader.Number-1, c.config.blockchain) if err != nil { - return nil, err + return nil, nil, err } } } - uptime := &contractsapi.Uptime{ - EpochID: new(big.Int).SetUint64(epochID), - TotalBlocks: big.NewInt(totalBlocks), - } - // include the data in the uptime counter in a deterministic way addrSet := []types.Address{} @@ -524,25 +558,34 @@ func (c *consensusRuntime) calculateCommitEpochInput( addrSet = append(addrSet, addr) } + uptime := make([]*contractsapi.Uptime, len(addrSet)) + sort.Slice(addrSet, func(i, j int) bool { return bytes.Compare(addrSet[i][:], addrSet[j][:]) > 0 }) - for _, addr := range addrSet { - uptime.AddValidatorUptime(addr, uptimeCounter[addr]) + for i, addr := range addrSet { + uptime[i] = &contractsapi.Uptime{ + Validator: addr, + SignedBlocks: new(big.Int).SetInt64(uptimeCounter[addr]), + } } - commitEpoch := &contractsapi.CommitEpochChildValidatorSetFn{ + commitEpoch := &contractsapi.CommitEpochValidatorSetFn{ ID: new(big.Int).SetUint64(epochID), Epoch: &contractsapi.Epoch{ StartBlock: new(big.Int).SetUint64(epoch.FirstBlockInEpoch), EndBlock: new(big.Int).SetUint64(currentBlock.Number + 1), EpochRoot: types.Hash{}, }, - Uptime: uptime, } - return commitEpoch, nil + distributeRewards := &contractsapi.DistributeRewardForRewardPoolFn{ + EpochID: new(big.Int).SetUint64(epochID), + Uptime: uptime, + } + + return commitEpoch, distributeRewards, nil } // GenerateExitProof generates proof of exit and is a bridge endpoint store function @@ -557,16 +600,12 @@ func (c *consensusRuntime) GetStateSyncProof(stateSyncID uint64) (types.Proof, e // setIsActiveValidator updates the activeValidatorFlag field func (c *consensusRuntime) setIsActiveValidator(isActiveValidator bool) { - if isActiveValidator { - atomic.StoreUint32(&c.activeValidatorFlag, 1) - } else { - atomic.StoreUint32(&c.activeValidatorFlag, 0) - } + c.activeValidatorFlag.Store(isActiveValidator) } // isActiveValidator indicates if node is in validator set or not func (c *consensusRuntime) isActiveValidator() bool { - return atomic.LoadUint32(&c.activeValidatorFlag) == 1 + return c.activeValidatorFlag.Load() } // isFixedSizeOfEpochMet checks if epoch reached its end that was configured by its default size @@ -721,61 +760,19 @@ func (c *consensusRuntime) ID() []byte { return c.config.Key.Address().Bytes() } -// HasQuorum returns true if quorum is reached for the given blockNumber -func (c *consensusRuntime) HasQuorum( - height uint64, - messages []*proto.Message, - msgType proto.MessageType) bool { +// GetVotingPowers returns map of validators addresses and their voting powers for the specified height. +func (c *consensusRuntime) GetVotingPowers(height uint64) (map[string]*big.Int, error) { c.lock.RLock() defer c.lock.RUnlock() - // extract the addresses of all the signers of the messages - ppIncluded := false - signers := make(map[types.Address]struct{}, len(messages)) - - for _, message := range messages { - if message.Type == proto.MessageType_PREPREPARE { - ppIncluded = true - } - signers[types.BytesToAddress(message.From)] = struct{}{} + if c.fsm == nil { + return nil, errors.New("getting voting power failed - backend is not initialized") + } else if c.fsm.Height() != height { + return nil, fmt.Errorf("getting voting power failed - backend is not initialized for height %d, fsm height %d", + height, c.fsm.Height()) } - // check quorum - switch msgType { - case proto.MessageType_PREPREPARE: - return len(messages) >= 1 - case proto.MessageType_PREPARE: - if ppIncluded { - return c.fsm.validators.HasQuorum(signers) - } - - if len(messages) == 0 { - return false - } - - propAddress, err := c.fsm.proposerSnapshot.GetLatestProposer(messages[0].View.Round, height) - if err != nil { - // This can happen if e.g. node runs sequence on lower height and proposer calculator updated - // to a newer count as a consequence of inserting block from syncer - c.logger.Debug("HasQuorum has been called but proposer could not be retrieved", "error", err) - - return false - } - - if _, ok := signers[propAddress]; ok { - c.logger.Warn("HasQuorum failed - proposer is among signers but it is not expected to be") - - return false - } - - signers[propAddress] = struct{}{} // add proposer manually - - return c.fsm.validators.HasQuorum(signers) - case proto.MessageType_ROUND_CHANGE, proto.MessageType_COMMIT: - return c.fsm.validators.HasQuorum(signers) - default: - return false - } + return c.fsm.validators.GetVotingPowers(), nil } // BuildPrePrepareMessage builds a PREPREPARE message based on the passed in proposal @@ -958,7 +955,7 @@ func (c *consensusRuntime) getFirstBlockOfEpoch(epochNumber uint64, latestHeader // getSealersForBlock checks who sealed a given block and updates the counter func getSealersForBlock(sealersCounter map[types.Address]uint64, - blockExtra *Extra, validators AccountSet) error { + blockExtra *Extra, validators validator.AccountSet) error { signers, err := validators.GetFilteredValidators(blockExtra.Parent.Bitmap) if err != nil { return err diff --git a/consensus/polybft/consensus_runtime_test.go b/consensus/polybft/consensus_runtime_test.go index 6a231f538e..094c3a200f 100644 --- a/consensus/polybft/consensus_runtime_test.go +++ b/consensus/polybft/consensus_runtime_test.go @@ -13,8 +13,10 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/assert" @@ -184,7 +186,7 @@ func TestConsensusRuntime_OnBlockInserted_EndOfEpoch(t *testing.T) { ) currentEpochNumber := getEpochNumber(t, epochSize, epochSize) - validatorSet := newTestValidators(t, validatorsCount).getPublicIdentities() + validatorSet := validator.NewTestValidators(t, validatorsCount).GetPublicIdentities() header, headerMap := createTestBlocks(t, epochSize, epochSize, validatorSet) builtBlock := consensus.BuildBlock(consensus.BuildBlockParams{ Header: header, @@ -227,6 +229,7 @@ func TestConsensusRuntime_OnBlockInserted_EndOfEpoch(t *testing.T) { lastBuiltBlock: &types.Header{Number: header.Number - 1}, stateSyncManager: &dummyStateSyncManager{}, checkpointManager: &dummyCheckpointManager{}, + stakeManager: &dummyStakeManager{}, } runtime.OnBlockInserted(&types.FullBlock{Block: builtBlock}) @@ -261,7 +264,7 @@ func TestConsensusRuntime_OnBlockInserted_MiddleOfEpoch(t *testing.T) { txPool := new(txPoolMock) txPool.On("ResetWithHeaders", mock.Anything).Once() - snapshot := NewProposerSnapshot(blockNumber, []*ValidatorMetadata{}) + snapshot := NewProposerSnapshot(blockNumber, []*validator.ValidatorMetadata{}) config := &runtimeConfig{ PolyBFTConfig: &PolyBFTConfig{EpochSize: epochSize}, blockchain: blockchainMock, @@ -290,7 +293,7 @@ func TestConsensusRuntime_OnBlockInserted_MiddleOfEpoch(t *testing.T) { func TestConsensusRuntime_FSM_NotInValidatorSet(t *testing.T) { t.Parallel() - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D"}) + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D"}) snapshot := NewProposerSnapshot(1, nil) config := &runtimeConfig{ @@ -300,15 +303,15 @@ func TestConsensusRuntime_FSM_NotInValidatorSet(t *testing.T) { Key: createTestKey(t), } runtime := &consensusRuntime{ - proposerCalculator: NewProposerCalculatorFromSnapshot(snapshot, config, hclog.NewNullLogger()), - activeValidatorFlag: 1, - config: config, + proposerCalculator: NewProposerCalculatorFromSnapshot(snapshot, config, hclog.NewNullLogger()), + config: config, epoch: &epochMetadata{ Number: 1, - Validators: validators.getPublicIdentities(), + Validators: validators.GetPublicIdentities(), }, lastBuiltBlock: &types.Header{}, } + runtime.setIsActiveValidator(true) err := runtime.FSM() assert.ErrorIs(t, err, errNotAValidator) @@ -322,10 +325,10 @@ func TestConsensusRuntime_FSM_NotEndOfEpoch_NotEndOfSprint(t *testing.T) { } lastBlock := &types.Header{ Number: 1, - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + ExtraData: extra.MarshalRLPTo(nil), } - validators := newTestValidators(t, 3) + validators := validator.NewTestValidators(t, 3) blockchainMock := new(blockchainMock) blockchainMock.On("NewBlockBuilder", mock.Anything).Return(&BlockBuilder{}, nil).Once() @@ -335,17 +338,16 @@ func TestConsensusRuntime_FSM_NotEndOfEpoch_NotEndOfSprint(t *testing.T) { EpochSize: 10, SprintSize: 5, }, - Key: wallet.NewKey(validators.getPrivateIdentities()[0]), + Key: wallet.NewKey(validators.GetPrivateIdentities()[0]), blockchain: blockchainMock, } runtime := &consensusRuntime{ - proposerCalculator: NewProposerCalculatorFromSnapshot(snapshot, config, hclog.NewNullLogger()), - logger: hclog.NewNullLogger(), - activeValidatorFlag: 1, - config: config, + proposerCalculator: NewProposerCalculatorFromSnapshot(snapshot, config, hclog.NewNullLogger()), + logger: hclog.NewNullLogger(), + config: config, epoch: &epochMetadata{ Number: 1, - Validators: validators.getPublicIdentities(), + Validators: validators.GetPublicIdentities(), FirstBlockInEpoch: 1, }, lastBuiltBlock: lastBlock, @@ -353,6 +355,7 @@ func TestConsensusRuntime_FSM_NotEndOfEpoch_NotEndOfSprint(t *testing.T) { stateSyncManager: &dummyStateSyncManager{}, checkpointManager: &dummyCheckpointManager{}, } + runtime.setIsActiveValidator(true) err := runtime.FSM() require.NoError(t, err) @@ -383,8 +386,8 @@ func TestConsensusRuntime_FSM_EndOfEpoch_BuildCommitEpoch(t *testing.T) { toIndex = uint64(9) ) - validatorAccounts := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) - validators := validatorAccounts.getPublicIdentities() + validatorAccounts := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validators := validatorAccounts.GetPublicIdentities() lastBuiltBlock, headerMap := createTestBlocks(t, 9, epochSize, validators) @@ -406,7 +409,7 @@ func TestConsensusRuntime_FSM_EndOfEpoch_BuildCommitEpoch(t *testing.T) { EpochSize: epochSize, SprintSize: sprintSize, }, - Key: validatorAccounts.getValidator("A").Key(), + Key: validatorAccounts.GetValidator("A").Key(), blockchain: blockchainMock, } @@ -420,6 +423,7 @@ func TestConsensusRuntime_FSM_EndOfEpoch_BuildCommitEpoch(t *testing.T) { lastBuiltBlock: lastBuiltBlock, stateSyncManager: &dummyStateSyncManager{}, checkpointManager: &dummyCheckpointManager{}, + stakeManager: &dummyStakeManager{}, } err := runtime.FSM() @@ -441,16 +445,16 @@ func Test_NewConsensusRuntime(t *testing.T) { polyBftConfig := &PolyBFTConfig{ Bridge: &BridgeConfig{ - BridgeAddr: types.Address{0x13}, - CheckpointAddr: types.Address{0x10}, - JSONRPCEndpoint: "testEndpoint", + StateSenderAddr: types.Address{0x13}, + CheckpointManagerAddr: types.Address{0x10}, + JSONRPCEndpoint: "testEndpoint", }, EpochSize: 10, SprintSize: 10, - BlockTime: 2 * time.Second, + BlockTime: common.Duration{Duration: 2 * time.Second}, } - validators := newTestValidators(t, 3).getPublicIdentities() + validators := validator.NewTestValidators(t, 3).GetPublicIdentities() systemStateMock := new(systemStateMock) systemStateMock.On("GetEpoch").Return(uint64(1)).Once() @@ -483,8 +487,8 @@ func Test_NewConsensusRuntime(t *testing.T) { assert.Equal(t, uint64(10), runtime.config.PolyBFTConfig.SprintSize) assert.Equal(t, uint64(10), runtime.config.PolyBFTConfig.EpochSize) assert.Equal(t, "0x0000000000000000000000000000000000000101", contracts.ValidatorSetContract.String()) - assert.Equal(t, "0x1300000000000000000000000000000000000000", runtime.config.PolyBFTConfig.Bridge.BridgeAddr.String()) - assert.Equal(t, "0x1000000000000000000000000000000000000000", runtime.config.PolyBFTConfig.Bridge.CheckpointAddr.String()) + assert.Equal(t, "0x1300000000000000000000000000000000000000", runtime.config.PolyBFTConfig.Bridge.StateSenderAddr.String()) + assert.Equal(t, "0x1000000000000000000000000000000000000000", runtime.config.PolyBFTConfig.Bridge.CheckpointManagerAddr.String()) assert.True(t, runtime.IsBridgeEnabled()) systemStateMock.AssertExpectations(t) blockchainMock.AssertExpectations(t) @@ -497,7 +501,7 @@ func TestConsensusRuntime_restartEpoch_SameEpochNumberAsTheLastOne(t *testing.T) const originalBlockNumber = uint64(5) newCurrentHeader := &types.Header{Number: originalBlockNumber + 1} - validatorSet := newTestValidators(t, 3).getPublicIdentities() + validatorSet := validator.NewTestValidators(t, 3).GetPublicIdentities() systemStateMock := new(systemStateMock) systemStateMock.On("GetEpoch").Return(uint64(1), nil).Once() @@ -511,9 +515,8 @@ func TestConsensusRuntime_restartEpoch_SameEpochNumberAsTheLastOne(t *testing.T) blockchain: blockchainMock, } runtime := &consensusRuntime{ - proposerCalculator: NewProposerCalculatorFromSnapshot(snapshot, config, hclog.NewNullLogger()), - activeValidatorFlag: 1, - config: config, + proposerCalculator: NewProposerCalculatorFromSnapshot(snapshot, config, hclog.NewNullLogger()), + config: config, epoch: &epochMetadata{ Number: 1, Validators: validatorSet, @@ -523,6 +526,7 @@ func TestConsensusRuntime_restartEpoch_SameEpochNumberAsTheLastOne(t *testing.T) Number: originalBlockNumber, }, } + runtime.setIsActiveValidator(true) epoch, err := runtime.restartEpoch(newCurrentHeader) @@ -547,43 +551,45 @@ func TestConsensusRuntime_calculateCommitEpochInput_SecondEpoch(t *testing.T) { sprintSize = 5 ) - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}) + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}) polybftConfig := &PolyBFTConfig{ EpochSize: epochSize, SprintSize: sprintSize, } - lastBuiltBlock, headerMap := createTestBlocks(t, 19, epochSize, validators.getPublicIdentities()) + lastBuiltBlock, headerMap := createTestBlocks(t, 19, epochSize, validators.GetPublicIdentities()) blockchainMock := new(blockchainMock) blockchainMock.On("GetHeaderByNumber", mock.Anything).Return(headerMap.getHeader) polybftBackendMock := new(polybftBackendMock) - polybftBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.getPublicIdentities()).Twice() + polybftBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.GetPublicIdentities()).Twice() config := &runtimeConfig{ PolyBFTConfig: polybftConfig, blockchain: blockchainMock, polybftBackend: polybftBackendMock, - Key: validators.getValidator("A").Key(), + Key: validators.GetValidator("A").Key(), } consensusRuntime := &consensusRuntime{ config: config, epoch: &epochMetadata{ Number: epoch, - Validators: validators.getPublicIdentities(), + Validators: validators.GetPublicIdentities(), FirstBlockInEpoch: epochStartBlock, }, lastBuiltBlock: lastBuiltBlock, } - commitEpochInput, err := consensusRuntime.calculateCommitEpochInput(lastBuiltBlock, consensusRuntime.epoch) + commitEpochInput, distributeRewardsInput, err := consensusRuntime.calculateCommitEpochInput(lastBuiltBlock, + consensusRuntime.epoch) assert.NoError(t, err) assert.NotEmpty(t, commitEpochInput) assert.Equal(t, uint64(epoch), commitEpochInput.ID.Uint64()) assert.Equal(t, uint64(epochStartBlock), commitEpochInput.Epoch.StartBlock.Uint64()) assert.Equal(t, uint64(epochEndBlock), commitEpochInput.Epoch.EndBlock.Uint64()) + assert.Equal(t, uint64(epoch), distributeRewardsInput.EpochID.Uint64()) blockchainMock.AssertExpectations(t) polybftBackendMock.AssertExpectations(t) @@ -592,17 +598,17 @@ func TestConsensusRuntime_calculateCommitEpochInput_SecondEpoch(t *testing.T) { func TestConsensusRuntime_IsValidValidator_BasicCases(t *testing.T) { t.Parallel() - setupFn := func(t *testing.T) (*consensusRuntime, *testValidators) { + setupFn := func(t *testing.T) (*consensusRuntime, *validator.TestValidators) { t.Helper() - validatorAccounts := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validatorAccounts := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) epoch := &epochMetadata{ - Validators: validatorAccounts.getPublicIdentities("A", "B", "C", "D"), + Validators: validatorAccounts.GetPublicIdentities("A", "B", "C", "D"), } runtime := &consensusRuntime{ epoch: epoch, logger: hclog.NewNullLogger(), - fsm: &fsm{validators: NewValidatorSet(epoch.Validators, hclog.NewNullLogger())}, + fsm: &fsm{validators: validator.NewValidatorSet(epoch.Validators, hclog.NewNullLogger())}, } return runtime, validatorAccounts @@ -640,8 +646,8 @@ func TestConsensusRuntime_IsValidValidator_BasicCases(t *testing.T) { t.Parallel() runtime, validatorAccounts := setupFn(t) - signer := validatorAccounts.getValidator(c.signerAlias) - sender := validatorAccounts.getValidator(c.senderAlias) + signer := validatorAccounts.GetValidator(c.signerAlias) + sender := validatorAccounts.GetValidator(c.senderAlias) msg, err := signer.Key().SignIBFTMessage(&proto.Message{From: sender.Address().Bytes()}) require.NoError(t, err) @@ -653,18 +659,18 @@ func TestConsensusRuntime_IsValidValidator_BasicCases(t *testing.T) { func TestConsensusRuntime_IsValidValidator_TamperSignature(t *testing.T) { t.Parallel() - validatorAccounts := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validatorAccounts := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) epoch := &epochMetadata{ - Validators: validatorAccounts.getPublicIdentities("A", "B", "C", "D"), + Validators: validatorAccounts.GetPublicIdentities("A", "B", "C", "D"), } runtime := &consensusRuntime{ epoch: epoch, logger: hclog.NewNullLogger(), - fsm: &fsm{validators: NewValidatorSet(epoch.Validators, hclog.NewNullLogger())}, + fsm: &fsm{validators: validator.NewValidatorSet(epoch.Validators, hclog.NewNullLogger())}, } // provide invalid signature - sender := validatorAccounts.getValidator("A") + sender := validatorAccounts.GetValidator("A") msg := &proto.Message{ From: sender.Address().Bytes(), Signature: []byte{1, 2, 3, 4, 5}, @@ -675,16 +681,16 @@ func TestConsensusRuntime_IsValidValidator_TamperSignature(t *testing.T) { func TestConsensusRuntime_TamperMessageContent(t *testing.T) { t.Parallel() - validatorAccounts := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validatorAccounts := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) epoch := &epochMetadata{ - Validators: validatorAccounts.getPublicIdentities("A", "B", "C", "D"), + Validators: validatorAccounts.GetPublicIdentities("A", "B", "C", "D"), } runtime := &consensusRuntime{ epoch: epoch, logger: hclog.NewNullLogger(), - fsm: &fsm{validators: NewValidatorSet(epoch.Validators, hclog.NewNullLogger())}, + fsm: &fsm{validators: validator.NewValidatorSet(epoch.Validators, hclog.NewNullLogger())}, } - sender := validatorAccounts.getValidator("A") + sender := validatorAccounts.GetValidator("A") proposalHash := []byte{2, 4, 6, 8, 10} proposalSignature, err := sender.Key().SignWithDomain(proposalHash, bls.DomainCheckpointManager) require.NoError(t, err) @@ -729,7 +735,7 @@ func TestConsensusRuntime_IsValidProposalHash(t *testing.T) { block := &types.Block{ Header: &types.Header{ Number: 10, - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + ExtraData: extra.MarshalRLPTo(nil), }, } block.Header.ComputeHash() @@ -758,7 +764,7 @@ func TestConsensusRuntime_IsValidProposalHash_InvalidProposalHash(t *testing.T) block := &types.Block{ Header: &types.Header{ Number: 10, - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + ExtraData: extra.MarshalRLPTo(nil), }, } @@ -766,7 +772,7 @@ func TestConsensusRuntime_IsValidProposalHash_InvalidProposalHash(t *testing.T) require.NoError(t, err) extra.Checkpoint.BlockRound = 2 // change it so it is not the same as in proposal hash - block.Header.ExtraData = append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...) + block.Header.ExtraData = extra.MarshalRLPTo(nil) block.Header.ComputeHash() runtime := &consensusRuntime{ @@ -832,126 +838,35 @@ func TestConsensusRuntime_ID(t *testing.T) { require.NotEqual(t, runtime.ID(), key2.Address().Bytes()) } -func TestConsensusRuntime_HasQuorum(t *testing.T) { +func TestConsensusRuntime_GetVotingPowers(t *testing.T) { t.Parallel() - const round = 5 + const height = 100 - validatorAccounts := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validatorAccounts := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C"}, []uint64{1, 3, 2}) + runtime := &consensusRuntime{} - extra := &Extra{ - Checkpoint: &CheckpointData{}, - } + _, err := runtime.GetVotingPowers(height) + require.Error(t, err) - lastBuildBlock := &types.Header{ - Number: 1, - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + runtime.fsm = &fsm{ + validators: validatorAccounts.ToValidatorSet(), + parent: &types.Header{Number: height}, } - blockchainMock := new(blockchainMock) - blockchainMock.On("NewBlockBuilder", mock.Anything).Return(&BlockBuilder{}, nil).Once() - blockchainMock.On("GetHeaderByNumber", mock.Anything).Return(&types.Header{ - Number: 0, - }, true).Once() - - state := newTestState(t) - snapshot := NewProposerSnapshot(lastBuildBlock.Number+1, validatorAccounts.getPublicIdentities()) - config := &runtimeConfig{ - Key: validatorAccounts.getValidator("B").Key(), - blockchain: blockchainMock, - PolyBFTConfig: &PolyBFTConfig{EpochSize: 10, SprintSize: 5}, - } - runtime := &consensusRuntime{ - state: state, - config: config, - lastBuiltBlock: lastBuildBlock, - epoch: &epochMetadata{ - Number: 1, - Validators: validatorAccounts.getPublicIdentities()[:len(validatorAccounts.validators)-1], - }, - logger: hclog.NewNullLogger(), - proposerCalculator: NewProposerCalculatorFromSnapshot(snapshot, config, hclog.NewNullLogger()), - stateSyncManager: &dummyStateSyncManager{}, - checkpointManager: &dummyCheckpointManager{}, - } + _, err = runtime.GetVotingPowers(height) + require.Error(t, err) - require.NoError(t, runtime.FSM()) + runtime.fsm.parent.Number = height - 1 - proposer, err := snapshot.CalcProposer(round, lastBuildBlock.Number+1) + val, err := runtime.GetVotingPowers(height) require.NoError(t, err) - runtime.fsm.proposerSnapshot = snapshot - - messages := make([]*proto.Message, 0, len(validatorAccounts.validators)) - - // Unknown message type - assert.False(t, runtime.HasQuorum(lastBuildBlock.Number+1, messages, -1)) - - // invalid block number - for _, msgType := range []proto.MessageType{proto.MessageType_PREPREPARE, proto.MessageType_PREPARE, - proto.MessageType_ROUND_CHANGE, proto.MessageType_COMMIT} { - assert.False(t, runtime.HasQuorum(lastBuildBlock.Number, nil, msgType)) - } - - // MessageType_PREPREPARE - only one message is enough - messages = append(messages, &proto.Message{ - From: proposer.Bytes(), - Type: proto.MessageType_PREPREPARE, - View: &proto.View{Height: 1, Round: round}, - }) - - assert.False(t, runtime.HasQuorum(lastBuildBlock.Number+1, nil, proto.MessageType_PREPREPARE)) - assert.True(t, runtime.HasQuorum(lastBuildBlock.Number+1, messages, proto.MessageType_PREPREPARE)) - - // MessageType_PREPARE - messages = make([]*proto.Message, 0, len(validatorAccounts.validators)) - - for _, x := range validatorAccounts.validators { - address := x.Address() + addresses := validatorAccounts.GetPublicIdentities([]string{"A", "B", "C"}...).GetAddresses() - // proposer must not be included in prepare messages - if address != proposer { - messages = append(messages, &proto.Message{ - From: address[:], - Type: proto.MessageType_PREPARE, - View: &proto.View{Height: lastBuildBlock.Number + 1, Round: round}, - }) - } - } - - // enough quorum - assert.True(t, runtime.HasQuorum(lastBuildBlock.Number+1, messages, proto.MessageType_PREPARE)) - - // not enough quorum - assert.False(t, runtime.HasQuorum(lastBuildBlock.Number+1, messages[:1], proto.MessageType_PREPARE)) - - // include proposer which is not allowed - messages = append(messages, &proto.Message{ - From: proposer[:], - Type: proto.MessageType_PREPARE, - View: &proto.View{Height: lastBuildBlock.Number + 1, Round: round}, - }) - assert.False(t, runtime.HasQuorum(lastBuildBlock.Number+1, messages, proto.MessageType_PREPARE)) - - // last message is MessageType_PREPREPARE - this should be allowed - messages[len(messages)-1].Type = proto.MessageType_PREPREPARE - assert.True(t, runtime.HasQuorum(lastBuildBlock.Number+1, messages, proto.MessageType_PREPARE)) - - //proto.MessageType_ROUND_CHANGE, proto.MessageType_COMMIT - for _, msgType := range []proto.MessageType{proto.MessageType_ROUND_CHANGE, proto.MessageType_COMMIT} { - messages = make([]*proto.Message, 0, len(validatorAccounts.validators)) - - for _, x := range validatorAccounts.validators { - messages = append(messages, &proto.Message{ - From: x.Address().Bytes(), - Type: msgType, - View: &proto.View{Height: lastBuildBlock.Number + 1, Round: round}, - }) - } - - assert.True(t, runtime.HasQuorum(lastBuildBlock.Number+1, messages, msgType)) - assert.False(t, runtime.HasQuorum(lastBuildBlock.Number+1, messages[:1], msgType)) - } + assert.Equal(t, uint64(1), val[types.AddressToString(addresses[0])].Uint64()) + assert.Equal(t, uint64(3), val[types.AddressToString(addresses[1])].Uint64()) + assert.Equal(t, uint64(2), val[types.AddressToString(addresses[2])].Uint64()) } func TestConsensusRuntime_BuildRoundChangeMessage(t *testing.T) { @@ -1066,7 +981,7 @@ func TestConsensusRuntime_BuildPrepareMessage(t *testing.T) { } func createTestBlocks(t *testing.T, numberOfBlocks, defaultEpochSize uint64, - validatorSet AccountSet) (*types.Header, *testHeadersMap) { + validatorSet validator.AccountSet) (*types.Header, *testHeadersMap) { t.Helper() headerMap := &testHeadersMap{} @@ -1078,7 +993,7 @@ func createTestBlocks(t *testing.T, numberOfBlocks, defaultEpochSize uint64, genesisBlock := &types.Header{ Number: 0, - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + ExtraData: extra.MarshalRLPTo(nil), } parentHash := types.BytesToHash(big.NewInt(0).Bytes()) @@ -1108,7 +1023,7 @@ func createTestBlocks(t *testing.T, numberOfBlocks, defaultEpochSize uint64, return blockHeader, headerMap } -func createTestBitmaps(t *testing.T, validators AccountSet, numberOfBlocks uint64) map[uint64]bitmap.Bitmap { +func createTestBitmaps(t *testing.T, validators validator.AccountSet, numberOfBlocks uint64) map[uint64]bitmap.Bitmap { t.Helper() bitmaps := make(map[uint64]bitmap.Bitmap, numberOfBlocks) @@ -1135,12 +1050,12 @@ func createTestBitmaps(t *testing.T, validators AccountSet, numberOfBlocks uint6 return bitmaps } -func createTestExtraForAccounts(t *testing.T, epoch uint64, validators AccountSet, b bitmap.Bitmap) []byte { +func createTestExtraForAccounts(t *testing.T, epoch uint64, validators validator.AccountSet, b bitmap.Bitmap) []byte { t.Helper() dummySignature := [64]byte{} extraData := Extra{ - Validators: &ValidatorSetDelta{ + Validators: &validator.ValidatorSetDelta{ Added: validators, Removed: bitmap.Bitmap{}, }, @@ -1149,12 +1064,7 @@ func createTestExtraForAccounts(t *testing.T, epoch uint64, validators AccountSe Checkpoint: &CheckpointData{EpochNumber: epoch}, } - marshaled := extraData.MarshalRLPTo(nil) - result := make([]byte, ExtraVanity+len(marshaled)) - - copy(result[ExtraVanity:], marshaled) - - return result + return extraData.MarshalRLPTo(nil) } func encodeExitEvents(t *testing.T, exitEvents []*ExitEvent) [][]byte { diff --git a/consensus/polybft/contracts_initializer.go b/consensus/polybft/contracts_initializer.go index 52633865fc..16239b8f6c 100644 --- a/consensus/polybft/contracts_initializer.go +++ b/consensus/polybft/contracts_initializer.go @@ -12,83 +12,267 @@ import ( ) const ( - // safe numbers for the test - minStake = 1 - minDelegation = 1 + contractCallGasLimit = 100_000_000 ) -var ( - nativeTokenName = "Polygon" - nativeTokenSymbol = "MATIC" - nativeTokenDecimals = uint8(18) -) +// initValidatorSet initializes ValidatorSet SC +func initValidatorSet(polyBFTConfig PolyBFTConfig, transition *state.Transition) error { + initialValidators := make([]*contractsapi.ValidatorInit, len(polyBFTConfig.InitialValidatorSet)) + for i, validator := range polyBFTConfig.InitialValidatorSet { + initialValidators[i] = &contractsapi.ValidatorInit{ + Addr: validator.Address, + Stake: validator.Stake, + } + } -// getInitChildValidatorSetInput builds input parameters for ChildValidatorSet SC initialization -func getInitChildValidatorSetInput(polyBFTConfig PolyBFTConfig) ([]byte, error) { - apiValidators := make([]*contractsapi.ValidatorInit, len(polyBFTConfig.InitialValidatorSet)) + initFn := &contractsapi.InitializeValidatorSetFn{ + NewStateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewRootChainManager: polyBFTConfig.Bridge.CustomSupernetManagerAddr, + NewEpochSize: new(big.Int).SetUint64(polyBFTConfig.EpochSize), + InitialValidators: initialValidators, + } - for i, validator := range polyBFTConfig.InitialValidatorSet { - validatorData, err := validator.ToValidatorInitAPIBinding() - if err != nil { - return nil, err + input, err := initFn.EncodeAbi() + if err != nil { + return fmt.Errorf("ValidatorSet.initialize params encoding failed: %w", err) + } + + return callContract(contracts.SystemCaller, + contracts.ValidatorSetContract, input, "ValidatorSet.initialize", transition) +} + +// initRewardPool initializes RewardPool SC +func initRewardPool(polybftConfig PolyBFTConfig, transition *state.Transition) error { + initFn := &contractsapi.InitializeRewardPoolFn{ + NewRewardToken: polybftConfig.RewardConfig.TokenAddress, + NewRewardWallet: polybftConfig.RewardConfig.WalletAddress, + NewValidatorSet: contracts.ValidatorSetContract, + NewBaseReward: new(big.Int).SetUint64(polybftConfig.EpochReward), + } + + input, err := initFn.EncodeAbi() + if err != nil { + return fmt.Errorf("RewardPool.initialize params encoding failed: %w", err) + } + + return callContract(contracts.SystemCaller, + contracts.RewardPoolContract, input, "RewardPool.initialize", transition) +} + +// getInitERC20PredicateInput builds initialization input parameters for child chain ERC20Predicate SC +func getInitERC20PredicateInput(config *BridgeConfig, childChainMintable bool) ([]byte, error) { + var params contractsapi.StateTransactionInput + if childChainMintable { + params = &contractsapi.InitializeRootMintableERC20PredicateFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewChildERC20Predicate: config.ChildMintableERC20PredicateAddr, + NewChildTokenTemplate: config.ChildERC20Addr, } + } else { + params = &contractsapi.InitializeChildERC20PredicateFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewRootERC20Predicate: config.RootERC20PredicateAddr, + NewChildTokenTemplate: contracts.ChildERC20Contract, + NewNativeTokenRootAddress: config.RootNativeERC20Addr, + } + } + + return params.EncodeAbi() +} - apiValidators[i] = validatorData +// getInitERC20PredicateACLInput builds initialization input parameters for child chain ERC20PredicateAccessList SC +func getInitERC20PredicateACLInput(config *BridgeConfig, owner types.Address, + childChainMintable bool) ([]byte, error) { + var params contractsapi.StateTransactionInput + if childChainMintable { + params = &contractsapi.InitializeRootMintableERC20PredicateACLFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewChildERC20Predicate: config.ChildMintableERC20PredicateAddr, + NewChildTokenTemplate: config.ChildERC20Addr, + NewUseAllowList: owner != contracts.SystemCaller, + NewUseBlockList: owner != contracts.SystemCaller, + NewOwner: owner, + } + } else { + params = &contractsapi.InitializeChildERC20PredicateACLFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewRootERC20Predicate: config.RootERC20PredicateAddr, + NewChildTokenTemplate: contracts.ChildERC20Contract, + NewNativeTokenRootAddress: config.RootNativeERC20Addr, + NewUseAllowList: owner != contracts.SystemCaller, + NewUseBlockList: owner != contracts.SystemCaller, + NewOwner: owner, + } } - params := &contractsapi.InitializeChildValidatorSetFn{ - Init: &contractsapi.InitStruct{ - EpochReward: new(big.Int).SetUint64(polyBFTConfig.EpochReward), - MinStake: big.NewInt(minStake), - MinDelegation: big.NewInt(minDelegation), - EpochSize: new(big.Int).SetUint64(polyBFTConfig.EpochSize), - }, - NewBls: contracts.BLSContract, - Governance: polyBFTConfig.Governance, - Validators: apiValidators, + return params.EncodeAbi() +} + +// getInitERC721PredicateInput builds initialization input parameters for child chain ERC721Predicate SC +func getInitERC721PredicateInput(config *BridgeConfig, childOriginatedTokens bool) ([]byte, error) { + var params contractsapi.StateTransactionInput + if childOriginatedTokens { + params = &contractsapi.InitializeRootMintableERC721PredicateFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewChildERC721Predicate: config.ChildMintableERC721PredicateAddr, + NewChildTokenTemplate: config.ChildERC721Addr, + } + } else { + params = &contractsapi.InitializeChildERC721PredicateFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewRootERC721Predicate: config.RootERC721PredicateAddr, + NewChildTokenTemplate: contracts.ChildERC721Contract, + } } return params.EncodeAbi() } -// getInitChildERC20PredicateInput builds input parameters for ERC20Predicate SC initialization -func getInitChildERC20PredicateInput(config *BridgeConfig) ([]byte, error) { - //nolint:godox - // to be fixed with EVM-541 - // TODO: @Stefan-Ethernal Temporary workaround just to be able to run cluster in non-bridge mode, until SC is fixed - rootERC20PredicateAddr := types.StringToAddress("0xDEAD") - rootERC20Addr := types.ZeroAddress +// getInitERC721PredicateACLInput builds initialization input parameters +// for child chain ERC721PredicateAccessList SC +func getInitERC721PredicateACLInput(config *BridgeConfig, owner types.Address, + childChainMintable bool) ([]byte, error) { + var params contractsapi.StateTransactionInput + if childChainMintable { + params = &contractsapi.InitializeRootMintableERC721PredicateACLFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewChildERC721Predicate: config.ChildMintableERC721PredicateAddr, + NewChildTokenTemplate: config.ChildERC721Addr, + NewUseAllowList: owner != contracts.SystemCaller, + NewUseBlockList: owner != contracts.SystemCaller, + NewOwner: owner, + } + } else { + params = &contractsapi.InitializeChildERC721PredicateACLFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewRootERC721Predicate: config.RootERC721PredicateAddr, + NewChildTokenTemplate: contracts.ChildERC721Contract, + NewUseAllowList: owner != contracts.SystemCaller, + NewUseBlockList: owner != contracts.SystemCaller, + NewOwner: owner, + } + } - if config != nil { - rootERC20PredicateAddr = config.RootERC20PredicateAddr - rootERC20Addr = config.RootNativeERC20Addr + return params.EncodeAbi() +} + +// getInitERC1155PredicateInput builds initialization input parameters for child chain ERC1155Predicate SC +func getInitERC1155PredicateInput(config *BridgeConfig, childChainMintable bool) ([]byte, error) { + var params contractsapi.StateTransactionInput + if childChainMintable { + params = &contractsapi.InitializeRootMintableERC1155PredicateFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewChildERC1155Predicate: config.ChildMintableERC1155PredicateAddr, + NewChildTokenTemplate: config.ChildERC1155Addr, + } + } else { + params = &contractsapi.InitializeChildERC1155PredicateFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewRootERC1155Predicate: config.RootERC1155PredicateAddr, + NewChildTokenTemplate: contracts.ChildERC1155Contract, + } } - params := &contractsapi.InitializeChildERC20PredicateFn{ - NewL2StateSender: contracts.L2StateSenderContract, - NewStateReceiver: contracts.StateReceiverContract, - NewRootERC20Predicate: rootERC20PredicateAddr, - NewChildTokenTemplate: contracts.ChildERC20Contract, - NewNativeTokenRootAddress: rootERC20Addr, + return params.EncodeAbi() +} + +// getInitERC1155PredicateACLInput builds initialization input parameters +// for child chain ERC1155PredicateAccessList SC +func getInitERC1155PredicateACLInput(config *BridgeConfig, owner types.Address, + childChainMintable bool) ([]byte, error) { + var params contractsapi.StateTransactionInput + if childChainMintable { + params = &contractsapi.InitializeRootMintableERC1155PredicateACLFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewChildERC1155Predicate: config.ChildMintableERC1155PredicateAddr, + NewChildTokenTemplate: config.ChildERC1155Addr, + NewUseAllowList: owner != contracts.SystemCaller, + NewUseBlockList: owner != contracts.SystemCaller, + NewOwner: owner, + } + } else { + params = &contractsapi.InitializeChildERC1155PredicateACLFn{ + NewL2StateSender: contracts.L2StateSenderContract, + NewStateReceiver: contracts.StateReceiverContract, + NewRootERC1155Predicate: config.RootERC1155PredicateAddr, + NewChildTokenTemplate: contracts.ChildERC1155Contract, + NewUseAllowList: owner != contracts.SystemCaller, + NewUseBlockList: owner != contracts.SystemCaller, + NewOwner: owner, + } } return params.EncodeAbi() } -func initContract(to types.Address, input []byte, contractName string, transition *state.Transition) error { - result := transition.Call2(contracts.SystemCaller, to, input, - big.NewInt(0), 100_000_000) +// mintRewardTokensToWallet mints configured amount of reward tokens to reward wallet address +func mintRewardTokensToWallet(polyBFTConfig PolyBFTConfig, transition *state.Transition) error { + if isNativeRewardToken(polyBFTConfig) { + // if reward token is a native erc20 token, we don't need to mint an amount of tokens + // for given wallet address to it since this is done in premine + return nil + } + + mintFn := contractsapi.MintRootERC20Fn{ + To: polyBFTConfig.RewardConfig.WalletAddress, + Amount: polyBFTConfig.RewardConfig.WalletAmount, + } + + input, err := mintFn.EncodeAbi() + if err != nil { + return fmt.Errorf("RewardToken.mint params encoding failed: %w", err) + } + + return callContract(contracts.SystemCaller, polyBFTConfig.RewardConfig.TokenAddress, input, + "RewardToken.mint", transition) +} + +// approveRewardPoolAsSpender approves reward pool contract as reward token spender +// since reward pool distributes rewards. +func approveRewardPoolAsSpender(polyBFTConfig PolyBFTConfig, transition *state.Transition) error { + approveFn := &contractsapi.ApproveRootERC20Fn{ + Spender: contracts.RewardPoolContract, + Amount: polyBFTConfig.RewardConfig.WalletAmount, + } + + input, err := approveFn.EncodeAbi() + if err != nil { + return fmt.Errorf("RewardToken.approve params encoding failed: %w", err) + } + return callContract(polyBFTConfig.RewardConfig.WalletAddress, + polyBFTConfig.RewardConfig.TokenAddress, input, "RewardToken.approve", transition) +} + +// callContract calls given smart contract function, encoded in input parameter +func callContract(from, to types.Address, input []byte, contractName string, transition *state.Transition) error { + result := transition.Call2(from, to, input, big.NewInt(0), contractCallGasLimit) if result.Failed() { if result.Reverted() { - unpackedRevert, err := abi.UnpackRevertError(result.ReturnValue) - if err == nil { - fmt.Printf("%v.initialize %v\n", contractName, unpackedRevert) + if revertReason, err := abi.UnpackRevertError(result.ReturnValue); err == nil { + return fmt.Errorf("%s contract call was reverted: %s", contractName, revertReason) } } - return fmt.Errorf("failed to initialize %s contract. Reason: %w", contractName, result.Err) + return fmt.Errorf("%s contract call failed: %w", contractName, result.Err) } return nil } + +// isNativeRewardToken returns true in case a native token is used as a reward token as well +func isNativeRewardToken(cfg PolyBFTConfig) bool { + return cfg.RewardConfig.TokenAddress == contracts.NativeERC20TokenContract +} diff --git a/consensus/polybft/contractsapi/artifacts-gen/main.go b/consensus/polybft/contractsapi/artifacts-gen/main.go index cedd7164b4..0f6b6ad12b 100644 --- a/consensus/polybft/contractsapi/artifacts-gen/main.go +++ b/consensus/polybft/contractsapi/artifacts-gen/main.go @@ -6,9 +6,15 @@ import ( "os" "path" "runtime" + "strings" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" "github.com/dave/jennifer/jen" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" +) + +const ( + extension = ".sol" ) func main() { @@ -23,10 +29,6 @@ func main() { Path string Name string }{ - { - "child/ChildValidatorSet.sol", - "ChildValidatorSet", - }, { "child/L2StateSender.sol", "L2StateSender", @@ -51,6 +53,58 @@ func main() { "child/ChildERC20Predicate.sol", "ChildERC20Predicate", }, + { + "child/ChildERC20PredicateAccessList.sol", + "ChildERC20PredicateACL", + }, + { + "child/RootMintableERC20Predicate.sol", + "RootMintableERC20Predicate", + }, + { + "child/RootMintableERC20PredicateAccessList.sol", + "RootMintableERC20PredicateACL", + }, + { + "child/ChildERC721.sol", + "ChildERC721", + }, + { + "child/ChildERC721Predicate.sol", + "ChildERC721Predicate", + }, + { + "child/ChildERC721PredicateAccessList.sol", + "ChildERC721PredicateACL", + }, + { + "child/RootMintableERC721Predicate.sol", + "RootMintableERC721Predicate", + }, + { + "child/RootMintableERC721PredicateAccessList.sol", + "RootMintableERC721PredicateACL", + }, + { + "child/ChildERC1155.sol", + "ChildERC1155", + }, + { + "child/ChildERC1155Predicate.sol", + "ChildERC1155Predicate", + }, + { + "child/ChildERC1155PredicateAccessList.sol", + "ChildERC1155PredicateACL", + }, + { + "child/RootMintableERC1155Predicate.sol", + "RootMintableERC1155Predicate", + }, + { + "child/RootMintableERC1155PredicateAccessList.sol", + "RootMintableERC1155PredicateACL", + }, { "child/System.sol", "System", @@ -79,18 +133,66 @@ func main() { "root/StateSender.sol", "StateSender", }, + { + "mocks/MockERC20.sol", + "MockERC20", + }, { "root/RootERC20Predicate.sol", "RootERC20Predicate", }, { - "mocks/MockERC20.sol", - "MockERC20", + "root/ChildMintableERC20Predicate.sol", + "ChildMintableERC20Predicate", + }, + { + "mocks/MockERC721.sol", + "MockERC721", + }, + { + "root/RootERC721Predicate.sol", + "RootERC721Predicate", + }, + { + "root/ChildMintableERC721Predicate.sol", + "ChildMintableERC721Predicate", + }, + { + "mocks/MockERC1155.sol", + "MockERC1155", + }, + { + "root/RootERC1155Predicate.sol", + "RootERC1155Predicate", + }, + { + "root/ChildMintableERC1155Predicate.sol", + "ChildMintableERC1155Predicate", + }, + { + "root/staking/CustomSupernetManager.sol", + "CustomSupernetManager", + }, + { + "root/staking/StakeManager.sol", + "StakeManager", + }, + { + "child/validator/RewardPool.sol", + "RewardPool", + }, + { + "child/validator/ValidatorSet.sol", + "ValidatorSet", + }, + { + "child/EIP1559Burn.sol", + "EIP1559Burn", }, } for _, v := range readContracts { - artifactBytes, err := artifact.ReadArtifactData(scpath, v.Path, v.Name) + artifactBytes, err := artifact.ReadArtifactData(scpath, v.Path, getContractName(v.Path)) if err != nil { log.Fatal(err) } @@ -108,3 +210,11 @@ func main() { log.Fatal(err) } } + +// getContractName extracts smart contract name from provided path +func getContractName(path string) string { + pathSegments := strings.Split(path, string([]rune{os.PathSeparator})) + nameSegment := pathSegments[len(pathSegments)-1] + + return strings.Split(nameSegment, extension)[0] +} diff --git a/consensus/polybft/contractsapi/bindings-gen/main.go b/consensus/polybft/contractsapi/bindings-gen/main.go index dbcdb51719..a30981d991 100644 --- a/consensus/polybft/contractsapi/bindings-gen/main.go +++ b/consensus/polybft/contractsapi/bindings-gen/main.go @@ -29,14 +29,16 @@ type generatedData struct { func main() { cases := []struct { - contractName string - artifact *artifact.Artifact - functions []string - events []string + contractName string + artifact *artifact.Artifact + generateConstructor bool + functions []string + events []string }{ { "StateReceiver", gensc.StateReceiver, + false, []string{ "commit", "execute", @@ -46,28 +48,10 @@ func main() { "NewCommitment", }, }, - { - "ChildValidatorSet", - gensc.ChildValidatorSet, - []string{ - "commitEpoch", - "initialize", - "addToWhitelist", - "register", - }, - []string{ - "NewValidator", - "Staked", - "Delegated", - "Unstaked", - "Undelegated", - "AddedToWhitelist", - "Withdrawal", - }, - }, { "StateSender", gensc.StateSender, + false, []string{ "syncState", }, @@ -78,6 +62,7 @@ func main() { { "L2StateSender", gensc.L2StateSender, + false, []string{}, []string{ "L2StateSynced", @@ -86,6 +71,7 @@ func main() { { "CheckpointManager", gensc.CheckpointManager, + false, []string{ "submit", "initialize", @@ -96,7 +82,9 @@ func main() { { "ExitHelper", gensc.ExitHelper, + false, []string{ + "initialize", "exit", }, []string{}, @@ -104,15 +92,45 @@ func main() { { "ChildERC20Predicate", gensc.ChildERC20Predicate, + false, []string{ "initialize", "withdrawTo", }, []string{}, }, + { + "ChildERC20PredicateACL", + gensc.ChildERC20PredicateACL, + false, + []string{ + "initialize", + "withdrawTo", + }, + []string{}, + }, + { + "RootMintableERC20Predicate", + gensc.RootMintableERC20Predicate, + false, + []string{ + "initialize", + }, + []string{}, + }, + { + "RootMintableERC20PredicateACL", + gensc.RootMintableERC20PredicateACL, + false, + []string{ + "initialize", + }, + []string{}, + }, { "NativeERC20", gensc.NativeERC20, + false, []string{ "initialize", }, @@ -121,6 +139,7 @@ func main() { { "NativeERC20Mintable", gensc.NativeERC20Mintable, + false, []string{ "initialize", }, @@ -129,26 +148,272 @@ func main() { { "RootERC20Predicate", gensc.RootERC20Predicate, + false, []string{ "initialize", "depositTo", }, - []string{}, + []string{ + "TokenMapped", + }, + }, + { + "ChildMintableERC20Predicate", + gensc.ChildMintableERC20Predicate, + false, + []string{ + "initialize", + }, + []string{ + "MintableTokenMapped", + }, }, { "RootERC20", gensc.RootERC20, + false, []string{ + "balanceOf", "approve", "mint", }, []string{}, }, + { + "RootERC1155Predicate", + gensc.RootERC1155Predicate, + false, + []string{ + "initialize", + "depositBatch", + }, + []string{}, + }, + { + "ChildMintableERC1155Predicate", + gensc.ChildMintableERC1155Predicate, + false, + []string{ + "initialize", + }, + []string{}, + }, + { + "RootERC1155", + gensc.RootERC1155, + false, + []string{ + "setApprovalForAll", + "mintBatch", + "balanceOf", + }, + []string{}, + }, + { + "ChildERC1155Predicate", + gensc.ChildERC1155Predicate, + false, + []string{ + "initialize", + "withdrawBatch", + }, + []string{}, + }, + { + "ChildERC1155PredicateACL", + gensc.ChildERC1155PredicateACL, + false, + []string{ + "initialize", + "withdrawBatch", + }, + []string{}, + }, + { + "RootMintableERC1155Predicate", + gensc.RootMintableERC1155Predicate, + false, + []string{ + "initialize", + }, + []string{}, + }, + { + "RootMintableERC1155PredicateACL", + gensc.RootMintableERC1155PredicateACL, + false, + []string{ + "initialize", + }, + []string{ + "L2MintableTokenMapped", + }, + }, + { + "ChildERC1155", + gensc.ChildERC1155, + false, + []string{ + "initialize", + "balanceOf", + }, + []string{}, + }, + { + "RootERC721Predicate", + gensc.RootERC721Predicate, + false, + []string{ + "initialize", + "depositBatch", + }, + []string{}, + }, + { + "ChildMintableERC721Predicate", + gensc.ChildMintableERC721Predicate, + false, + []string{ + "initialize", + }, + []string{}, + }, + { + "RootERC721", + gensc.RootERC721, + false, + []string{ + "setApprovalForAll", + "mint", + }, + []string{}, + }, + { + "ChildERC721Predicate", + gensc.ChildERC721Predicate, + false, + []string{ + "initialize", + "withdrawBatch", + }, + []string{}, + }, + { + "ChildERC721PredicateACL", + gensc.ChildERC721PredicateACL, + false, + []string{ + "initialize", + "withdrawBatch", + }, + []string{}, + }, + { + "RootMintableERC721Predicate", + gensc.RootMintableERC721Predicate, + false, + []string{ + "initialize", + }, + []string{}, + }, + { + "RootMintableERC721PredicateACL", + gensc.RootMintableERC721PredicateACL, + false, + []string{ + "initialize", + }, + []string{}, + }, + { + "ChildERC721", + gensc.ChildERC721, + false, + []string{ + "initialize", + "ownerOf", + }, + []string{}, + }, + { + "CustomSupernetManager", + gensc.CustomSupernetManager, + false, + []string{ + "initialize", + "whitelistValidators", + "register", + "getValidator", + }, + []string{ + "ValidatorRegistered", + "AddedToWhitelist", + }, + }, + { + "StakeManager", + gensc.StakeManager, + false, + []string{ + "initialize", + "registerChildChain", + "stakeFor", + "releaseStakeOf", + "withdrawStake", + "stakeOf", + }, + []string{ + "ChildManagerRegistered", + "StakeAdded", + "StakeWithdrawn", + }, + }, + { + "ValidatorSet", + gensc.ValidatorSet, + false, + []string{ + "commitEpoch", + "unstake", + "initialize", + }, + []string{ + "Transfer", + "WithdrawalRegistered", + "Withdrawal", + }, + }, + { + "RewardPool", + gensc.RewardPool, + false, + []string{ + "initialize", + "distributeRewardFor", + }, + []string{}, + }, + { + "EIP1559Burn", + gensc.EIP1559Burn, + false, + []string{ + "initialize", + }, + []string{}, + }, } generatedData := &generatedData{} for _, c := range cases { + if c.generateConstructor { + if err := generateConstructor(generatedData, c.contractName, c.artifact.Abi.Constructor); err != nil { + log.Fatal(err) + } + } + for _, method := range c.functions { if err := generateFunction(generatedData, c.contractName, c.artifact.Abi.Methods[method]); err != nil { log.Fatal(err) @@ -376,6 +641,52 @@ func ({{.Sig}} *{{.TName}}) ParseLog(log *ethgo.Log) (bool, error) { return nil } +// generateConstruct generates stubs for a smart contract constructor +func generateConstructor(generatedData *generatedData, + contractName string, constructor *abi.Method) error { + methodName := fmt.Sprintf(functionNameFormat, strings.Title(contractName+"Constructor")) + res := []string{} + + _, err := generateType(generatedData, methodName, constructor.Inputs, &res) + if err != nil { + return err + } + + // write encode/decode functions + tmplStr := ` +{{range .Structs}} + {{.}} +{{ end }} + +func ({{.Sig}} *{{.TName}}) Sig() []byte { + return {{.ContractName}}.Abi.Constructor.ID() +} + +func ({{.Sig}} *{{.TName}}) EncodeAbi() ([]byte, error) { + return {{.ContractName}}.Abi.Constructor.Inputs.Encode({{.Sig}}) +} + +func ({{.Sig}} *{{.TName}}) DecodeAbi(buf []byte) error { + return decodeMethod({{.ContractName}}.Abi.Constructor, buf, {{.Sig}}) +}` + + inputs := map[string]interface{}{ + "Structs": res, + "Sig": strings.ToLower(string(methodName[0])), + "ContractName": contractName, + "TName": strings.Title(methodName), + } + + renderedString, err := renderTmpl(tmplStr, inputs) + if err != nil { + return err + } + + generatedData.resultString = append(generatedData.resultString, renderedString) + + return nil +} + // generateFunction generates code for smart contract function and its parameters func generateFunction(generatedData *generatedData, contractName string, method *abi.Method) error { methodName := fmt.Sprintf(functionNameFormat, strings.Title(method.Name+contractName)) diff --git a/consensus/polybft/contractsapi/contractsapi.go b/consensus/polybft/contractsapi/contractsapi.go index dea0cf7a84..3b8dddfdf8 100644 --- a/consensus/polybft/contractsapi/contractsapi.go +++ b/consensus/polybft/contractsapi/contractsapi.go @@ -121,306 +121,6 @@ func (n *NewCommitmentEvent) ParseLog(log *ethgo.Log) (bool, error) { return true, decodeEvent(StateReceiver.Abi.Events["NewCommitment"], log, n) } -type Epoch struct { - StartBlock *big.Int `abi:"startBlock"` - EndBlock *big.Int `abi:"endBlock"` - EpochRoot types.Hash `abi:"epochRoot"` -} - -var EpochABIType = abi.MustNewType("tuple(uint256 startBlock,uint256 endBlock,bytes32 epochRoot)") - -func (e *Epoch) EncodeAbi() ([]byte, error) { - return EpochABIType.Encode(e) -} - -func (e *Epoch) DecodeAbi(buf []byte) error { - return decodeStruct(EpochABIType, buf, &e) -} - -type UptimeData struct { - Validator types.Address `abi:"validator"` - SignedBlocks *big.Int `abi:"signedBlocks"` -} - -var UptimeDataABIType = abi.MustNewType("tuple(address validator,uint256 signedBlocks)") - -func (u *UptimeData) EncodeAbi() ([]byte, error) { - return UptimeDataABIType.Encode(u) -} - -func (u *UptimeData) DecodeAbi(buf []byte) error { - return decodeStruct(UptimeDataABIType, buf, &u) -} - -type Uptime struct { - EpochID *big.Int `abi:"epochId"` - UptimeData []*UptimeData `abi:"uptimeData"` - TotalBlocks *big.Int `abi:"totalBlocks"` -} - -var UptimeABIType = abi.MustNewType("tuple(uint256 epochId,tuple(address validator,uint256 signedBlocks)[] uptimeData,uint256 totalBlocks)") - -func (u *Uptime) EncodeAbi() ([]byte, error) { - return UptimeABIType.Encode(u) -} - -func (u *Uptime) DecodeAbi(buf []byte) error { - return decodeStruct(UptimeABIType, buf, &u) -} - -type CommitEpochChildValidatorSetFn struct { - ID *big.Int `abi:"id"` - Epoch *Epoch `abi:"epoch"` - Uptime *Uptime `abi:"uptime"` -} - -func (c *CommitEpochChildValidatorSetFn) Sig() []byte { - return ChildValidatorSet.Abi.Methods["commitEpoch"].ID() -} - -func (c *CommitEpochChildValidatorSetFn) EncodeAbi() ([]byte, error) { - return ChildValidatorSet.Abi.Methods["commitEpoch"].Encode(c) -} - -func (c *CommitEpochChildValidatorSetFn) DecodeAbi(buf []byte) error { - return decodeMethod(ChildValidatorSet.Abi.Methods["commitEpoch"], buf, c) -} - -type InitStruct struct { - EpochReward *big.Int `abi:"epochReward"` - MinStake *big.Int `abi:"minStake"` - MinDelegation *big.Int `abi:"minDelegation"` - EpochSize *big.Int `abi:"epochSize"` -} - -var InitStructABIType = abi.MustNewType("tuple(uint256 epochReward,uint256 minStake,uint256 minDelegation,uint256 epochSize)") - -func (i *InitStruct) EncodeAbi() ([]byte, error) { - return InitStructABIType.Encode(i) -} - -func (i *InitStruct) DecodeAbi(buf []byte) error { - return decodeStruct(InitStructABIType, buf, &i) -} - -type ValidatorInit struct { - Addr types.Address `abi:"addr"` - Pubkey [4]*big.Int `abi:"pubkey"` - Signature [2]*big.Int `abi:"signature"` - Stake *big.Int `abi:"stake"` -} - -var ValidatorInitABIType = abi.MustNewType("tuple(address addr,uint256[4] pubkey,uint256[2] signature,uint256 stake)") - -func (v *ValidatorInit) EncodeAbi() ([]byte, error) { - return ValidatorInitABIType.Encode(v) -} - -func (v *ValidatorInit) DecodeAbi(buf []byte) error { - return decodeStruct(ValidatorInitABIType, buf, &v) -} - -type InitializeChildValidatorSetFn struct { - Init *InitStruct `abi:"init"` - Validators []*ValidatorInit `abi:"validators"` - NewBls types.Address `abi:"newBls"` - Governance types.Address `abi:"governance"` -} - -func (i *InitializeChildValidatorSetFn) Sig() []byte { - return ChildValidatorSet.Abi.Methods["initialize"].ID() -} - -func (i *InitializeChildValidatorSetFn) EncodeAbi() ([]byte, error) { - return ChildValidatorSet.Abi.Methods["initialize"].Encode(i) -} - -func (i *InitializeChildValidatorSetFn) DecodeAbi(buf []byte) error { - return decodeMethod(ChildValidatorSet.Abi.Methods["initialize"], buf, i) -} - -type AddToWhitelistChildValidatorSetFn struct { - WhitelistAddreses []ethgo.Address `abi:"whitelistAddreses"` -} - -func (a *AddToWhitelistChildValidatorSetFn) Sig() []byte { - return ChildValidatorSet.Abi.Methods["addToWhitelist"].ID() -} - -func (a *AddToWhitelistChildValidatorSetFn) EncodeAbi() ([]byte, error) { - return ChildValidatorSet.Abi.Methods["addToWhitelist"].Encode(a) -} - -func (a *AddToWhitelistChildValidatorSetFn) DecodeAbi(buf []byte) error { - return decodeMethod(ChildValidatorSet.Abi.Methods["addToWhitelist"], buf, a) -} - -type RegisterChildValidatorSetFn struct { - Signature [2]*big.Int `abi:"signature"` - Pubkey [4]*big.Int `abi:"pubkey"` -} - -func (r *RegisterChildValidatorSetFn) Sig() []byte { - return ChildValidatorSet.Abi.Methods["register"].ID() -} - -func (r *RegisterChildValidatorSetFn) EncodeAbi() ([]byte, error) { - return ChildValidatorSet.Abi.Methods["register"].Encode(r) -} - -func (r *RegisterChildValidatorSetFn) DecodeAbi(buf []byte) error { - return decodeMethod(ChildValidatorSet.Abi.Methods["register"], buf, r) -} - -type NewValidatorEvent struct { - Validator types.Address `abi:"validator"` - BlsKey [4]*big.Int `abi:"blsKey"` -} - -func (*NewValidatorEvent) Sig() ethgo.Hash { - return ChildValidatorSet.Abi.Events["NewValidator"].ID() -} - -func (*NewValidatorEvent) Encode(inputs interface{}) ([]byte, error) { - return ChildValidatorSet.Abi.Events["NewValidator"].Inputs.Encode(inputs) -} - -func (n *NewValidatorEvent) ParseLog(log *ethgo.Log) (bool, error) { - if !ChildValidatorSet.Abi.Events["NewValidator"].Match(log) { - return false, nil - } - - return true, decodeEvent(ChildValidatorSet.Abi.Events["NewValidator"], log, n) -} - -type StakedEvent struct { - Validator types.Address `abi:"validator"` - Amount *big.Int `abi:"amount"` -} - -func (*StakedEvent) Sig() ethgo.Hash { - return ChildValidatorSet.Abi.Events["Staked"].ID() -} - -func (*StakedEvent) Encode(inputs interface{}) ([]byte, error) { - return ChildValidatorSet.Abi.Events["Staked"].Inputs.Encode(inputs) -} - -func (s *StakedEvent) ParseLog(log *ethgo.Log) (bool, error) { - if !ChildValidatorSet.Abi.Events["Staked"].Match(log) { - return false, nil - } - - return true, decodeEvent(ChildValidatorSet.Abi.Events["Staked"], log, s) -} - -type DelegatedEvent struct { - Delegator types.Address `abi:"delegator"` - Validator types.Address `abi:"validator"` - Amount *big.Int `abi:"amount"` -} - -func (*DelegatedEvent) Sig() ethgo.Hash { - return ChildValidatorSet.Abi.Events["Delegated"].ID() -} - -func (*DelegatedEvent) Encode(inputs interface{}) ([]byte, error) { - return ChildValidatorSet.Abi.Events["Delegated"].Inputs.Encode(inputs) -} - -func (d *DelegatedEvent) ParseLog(log *ethgo.Log) (bool, error) { - if !ChildValidatorSet.Abi.Events["Delegated"].Match(log) { - return false, nil - } - - return true, decodeEvent(ChildValidatorSet.Abi.Events["Delegated"], log, d) -} - -type UnstakedEvent struct { - Validator types.Address `abi:"validator"` - Amount *big.Int `abi:"amount"` -} - -func (*UnstakedEvent) Sig() ethgo.Hash { - return ChildValidatorSet.Abi.Events["Unstaked"].ID() -} - -func (*UnstakedEvent) Encode(inputs interface{}) ([]byte, error) { - return ChildValidatorSet.Abi.Events["Unstaked"].Inputs.Encode(inputs) -} - -func (u *UnstakedEvent) ParseLog(log *ethgo.Log) (bool, error) { - if !ChildValidatorSet.Abi.Events["Unstaked"].Match(log) { - return false, nil - } - - return true, decodeEvent(ChildValidatorSet.Abi.Events["Unstaked"], log, u) -} - -type UndelegatedEvent struct { - Delegator types.Address `abi:"delegator"` - Validator types.Address `abi:"validator"` - Amount *big.Int `abi:"amount"` -} - -func (*UndelegatedEvent) Sig() ethgo.Hash { - return ChildValidatorSet.Abi.Events["Undelegated"].ID() -} - -func (*UndelegatedEvent) Encode(inputs interface{}) ([]byte, error) { - return ChildValidatorSet.Abi.Events["Undelegated"].Inputs.Encode(inputs) -} - -func (u *UndelegatedEvent) ParseLog(log *ethgo.Log) (bool, error) { - if !ChildValidatorSet.Abi.Events["Undelegated"].Match(log) { - return false, nil - } - - return true, decodeEvent(ChildValidatorSet.Abi.Events["Undelegated"], log, u) -} - -type AddedToWhitelistEvent struct { - Validator types.Address `abi:"validator"` -} - -func (*AddedToWhitelistEvent) Sig() ethgo.Hash { - return ChildValidatorSet.Abi.Events["AddedToWhitelist"].ID() -} - -func (*AddedToWhitelistEvent) Encode(inputs interface{}) ([]byte, error) { - return ChildValidatorSet.Abi.Events["AddedToWhitelist"].Inputs.Encode(inputs) -} - -func (a *AddedToWhitelistEvent) ParseLog(log *ethgo.Log) (bool, error) { - if !ChildValidatorSet.Abi.Events["AddedToWhitelist"].Match(log) { - return false, nil - } - - return true, decodeEvent(ChildValidatorSet.Abi.Events["AddedToWhitelist"], log, a) -} - -type WithdrawalEvent struct { - Account types.Address `abi:"account"` - To types.Address `abi:"to"` - Amount *big.Int `abi:"amount"` -} - -func (*WithdrawalEvent) Sig() ethgo.Hash { - return ChildValidatorSet.Abi.Events["Withdrawal"].ID() -} - -func (*WithdrawalEvent) Encode(inputs interface{}) ([]byte, error) { - return ChildValidatorSet.Abi.Events["Withdrawal"].Inputs.Encode(inputs) -} - -func (w *WithdrawalEvent) ParseLog(log *ethgo.Log) (bool, error) { - if !ChildValidatorSet.Abi.Events["Withdrawal"].Match(log) { - return false, nil - } - - return true, decodeEvent(ChildValidatorSet.Abi.Events["Withdrawal"], log, w) -} - type SyncStateStateSenderFn struct { Receiver types.Address `abi:"receiver"` Data []byte `abi:"data"` @@ -587,6 +287,22 @@ func (g *GetCheckpointBlockCheckpointManagerFn) DecodeAbi(buf []byte) error { return decodeMethod(CheckpointManager.Abi.Methods["getCheckpointBlock"], buf, g) } +type InitializeExitHelperFn struct { + NewCheckpointManager types.Address `abi:"newCheckpointManager"` +} + +func (i *InitializeExitHelperFn) Sig() []byte { + return ExitHelper.Abi.Methods["initialize"].ID() +} + +func (i *InitializeExitHelperFn) EncodeAbi() ([]byte, error) { + return ExitHelper.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeExitHelperFn) DecodeAbi(buf []byte) error { + return decodeMethod(ExitHelper.Abi.Methods["initialize"], buf, i) +} + type ExitExitHelperFn struct { BlockNumber *big.Int `abi:"blockNumber"` LeafIndex *big.Int `abi:"leafIndex"` @@ -644,12 +360,95 @@ func (w *WithdrawToChildERC20PredicateFn) DecodeAbi(buf []byte) error { return decodeMethod(ChildERC20Predicate.Abi.Methods["withdrawTo"], buf, w) } +type InitializeChildERC20PredicateACLFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewRootERC20Predicate types.Address `abi:"newRootERC20Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` + NewNativeTokenRootAddress types.Address `abi:"newNativeTokenRootAddress"` + NewUseAllowList bool `abi:"newUseAllowList"` + NewUseBlockList bool `abi:"newUseBlockList"` + NewOwner types.Address `abi:"newOwner"` +} + +func (i *InitializeChildERC20PredicateACLFn) Sig() []byte { + return ChildERC20PredicateACL.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildERC20PredicateACLFn) EncodeAbi() ([]byte, error) { + return ChildERC20PredicateACL.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildERC20PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC20PredicateACL.Abi.Methods["initialize"], buf, i) +} + +type WithdrawToChildERC20PredicateACLFn struct { + ChildToken types.Address `abi:"childToken"` + Receiver types.Address `abi:"receiver"` + Amount *big.Int `abi:"amount"` +} + +func (w *WithdrawToChildERC20PredicateACLFn) Sig() []byte { + return ChildERC20PredicateACL.Abi.Methods["withdrawTo"].ID() +} + +func (w *WithdrawToChildERC20PredicateACLFn) EncodeAbi() ([]byte, error) { + return ChildERC20PredicateACL.Abi.Methods["withdrawTo"].Encode(w) +} + +func (w *WithdrawToChildERC20PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC20PredicateACL.Abi.Methods["withdrawTo"], buf, w) +} + +type InitializeRootMintableERC20PredicateFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewChildERC20Predicate types.Address `abi:"newChildERC20Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeRootMintableERC20PredicateFn) Sig() []byte { + return RootMintableERC20Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRootMintableERC20PredicateFn) EncodeAbi() ([]byte, error) { + return RootMintableERC20Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRootMintableERC20PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootMintableERC20Predicate.Abi.Methods["initialize"], buf, i) +} + +type InitializeRootMintableERC20PredicateACLFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewChildERC20Predicate types.Address `abi:"newChildERC20Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` + NewUseAllowList bool `abi:"newUseAllowList"` + NewUseBlockList bool `abi:"newUseBlockList"` + NewOwner types.Address `abi:"newOwner"` +} + +func (i *InitializeRootMintableERC20PredicateACLFn) Sig() []byte { + return RootMintableERC20PredicateACL.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRootMintableERC20PredicateACLFn) EncodeAbi() ([]byte, error) { + return RootMintableERC20PredicateACL.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRootMintableERC20PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootMintableERC20PredicateACL.Abi.Methods["initialize"], buf, i) +} + type InitializeNativeERC20Fn struct { - Predicate_ types.Address `abi:"predicate_"` - RootToken_ types.Address `abi:"rootToken_"` - Name_ string `abi:"name_"` - Symbol_ string `abi:"symbol_"` - Decimals_ uint8 `abi:"decimals_"` + Predicate_ types.Address `abi:"predicate_"` + RootToken_ types.Address `abi:"rootToken_"` + Name_ string `abi:"name_"` + Symbol_ string `abi:"symbol_"` + Decimals_ uint8 `abi:"decimals_"` + TokenSupply_ *big.Int `abi:"tokenSupply_"` } func (i *InitializeNativeERC20Fn) Sig() []byte { @@ -665,12 +464,13 @@ func (i *InitializeNativeERC20Fn) DecodeAbi(buf []byte) error { } type InitializeNativeERC20MintableFn struct { - Predicate_ types.Address `abi:"predicate_"` - Owner_ types.Address `abi:"owner_"` - RootToken_ types.Address `abi:"rootToken_"` - Name_ string `abi:"name_"` - Symbol_ string `abi:"symbol_"` - Decimals_ uint8 `abi:"decimals_"` + Predicate_ types.Address `abi:"predicate_"` + Owner_ types.Address `abi:"owner_"` + RootToken_ types.Address `abi:"rootToken_"` + Name_ string `abi:"name_"` + Symbol_ string `abi:"symbol_"` + Decimals_ uint8 `abi:"decimals_"` + TokenSupply_ *big.Int `abi:"tokenSupply_"` } func (i *InitializeNativeERC20MintableFn) Sig() []byte { @@ -723,17 +523,94 @@ func (d *DepositToRootERC20PredicateFn) DecodeAbi(buf []byte) error { return decodeMethod(RootERC20Predicate.Abi.Methods["depositTo"], buf, d) } -type ApproveRootERC20Fn struct { - Spender types.Address `abi:"spender"` - Amount *big.Int `abi:"amount"` +type TokenMappedEvent struct { + RootToken types.Address `abi:"rootToken"` + ChildToken types.Address `abi:"childToken"` } -func (a *ApproveRootERC20Fn) Sig() []byte { - return RootERC20.Abi.Methods["approve"].ID() +func (*TokenMappedEvent) Sig() ethgo.Hash { + return RootERC20Predicate.Abi.Events["TokenMapped"].ID() } -func (a *ApproveRootERC20Fn) EncodeAbi() ([]byte, error) { - return RootERC20.Abi.Methods["approve"].Encode(a) +func (*TokenMappedEvent) Encode(inputs interface{}) ([]byte, error) { + return RootERC20Predicate.Abi.Events["TokenMapped"].Inputs.Encode(inputs) +} + +func (t *TokenMappedEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !RootERC20Predicate.Abi.Events["TokenMapped"].Match(log) { + return false, nil + } + + return true, decodeEvent(RootERC20Predicate.Abi.Events["TokenMapped"], log, t) +} + +type InitializeChildMintableERC20PredicateFn struct { + NewStateSender types.Address `abi:"newStateSender"` + NewExitHelper types.Address `abi:"newExitHelper"` + NewRootERC20Predicate types.Address `abi:"newRootERC20Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeChildMintableERC20PredicateFn) Sig() []byte { + return ChildMintableERC20Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildMintableERC20PredicateFn) EncodeAbi() ([]byte, error) { + return ChildMintableERC20Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildMintableERC20PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildMintableERC20Predicate.Abi.Methods["initialize"], buf, i) +} + +type MintableTokenMappedEvent struct { + RootToken types.Address `abi:"rootToken"` + ChildToken types.Address `abi:"childToken"` +} + +func (*MintableTokenMappedEvent) Sig() ethgo.Hash { + return ChildMintableERC20Predicate.Abi.Events["MintableTokenMapped"].ID() +} + +func (*MintableTokenMappedEvent) Encode(inputs interface{}) ([]byte, error) { + return ChildMintableERC20Predicate.Abi.Events["MintableTokenMapped"].Inputs.Encode(inputs) +} + +func (m *MintableTokenMappedEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !ChildMintableERC20Predicate.Abi.Events["MintableTokenMapped"].Match(log) { + return false, nil + } + + return true, decodeEvent(ChildMintableERC20Predicate.Abi.Events["MintableTokenMapped"], log, m) +} + +type BalanceOfRootERC20Fn struct { + Account types.Address `abi:"account"` +} + +func (b *BalanceOfRootERC20Fn) Sig() []byte { + return RootERC20.Abi.Methods["balanceOf"].ID() +} + +func (b *BalanceOfRootERC20Fn) EncodeAbi() ([]byte, error) { + return RootERC20.Abi.Methods["balanceOf"].Encode(b) +} + +func (b *BalanceOfRootERC20Fn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC20.Abi.Methods["balanceOf"], buf, b) +} + +type ApproveRootERC20Fn struct { + Spender types.Address `abi:"spender"` + Amount *big.Int `abi:"amount"` +} + +func (a *ApproveRootERC20Fn) Sig() []byte { + return RootERC20.Abi.Methods["approve"].ID() +} + +func (a *ApproveRootERC20Fn) EncodeAbi() ([]byte, error) { + return RootERC20.Abi.Methods["approve"].Encode(a) } func (a *ApproveRootERC20Fn) DecodeAbi(buf []byte) error { @@ -756,3 +633,1022 @@ func (m *MintRootERC20Fn) EncodeAbi() ([]byte, error) { func (m *MintRootERC20Fn) DecodeAbi(buf []byte) error { return decodeMethod(RootERC20.Abi.Methods["mint"], buf, m) } + +type InitializeRootERC1155PredicateFn struct { + NewStateSender types.Address `abi:"newStateSender"` + NewExitHelper types.Address `abi:"newExitHelper"` + NewChildERC1155Predicate types.Address `abi:"newChildERC1155Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeRootERC1155PredicateFn) Sig() []byte { + return RootERC1155Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRootERC1155PredicateFn) EncodeAbi() ([]byte, error) { + return RootERC1155Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRootERC1155PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC1155Predicate.Abi.Methods["initialize"], buf, i) +} + +type DepositBatchRootERC1155PredicateFn struct { + RootToken types.Address `abi:"rootToken"` + Receivers []ethgo.Address `abi:"receivers"` + TokenIDs []*big.Int `abi:"tokenIds"` + Amounts []*big.Int `abi:"amounts"` +} + +func (d *DepositBatchRootERC1155PredicateFn) Sig() []byte { + return RootERC1155Predicate.Abi.Methods["depositBatch"].ID() +} + +func (d *DepositBatchRootERC1155PredicateFn) EncodeAbi() ([]byte, error) { + return RootERC1155Predicate.Abi.Methods["depositBatch"].Encode(d) +} + +func (d *DepositBatchRootERC1155PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC1155Predicate.Abi.Methods["depositBatch"], buf, d) +} + +type InitializeChildMintableERC1155PredicateFn struct { + NewStateSender types.Address `abi:"newStateSender"` + NewExitHelper types.Address `abi:"newExitHelper"` + NewRootERC1155Predicate types.Address `abi:"newRootERC1155Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeChildMintableERC1155PredicateFn) Sig() []byte { + return ChildMintableERC1155Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildMintableERC1155PredicateFn) EncodeAbi() ([]byte, error) { + return ChildMintableERC1155Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildMintableERC1155PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildMintableERC1155Predicate.Abi.Methods["initialize"], buf, i) +} + +type SetApprovalForAllRootERC1155Fn struct { + Operator types.Address `abi:"operator"` + Approved bool `abi:"approved"` +} + +func (s *SetApprovalForAllRootERC1155Fn) Sig() []byte { + return RootERC1155.Abi.Methods["setApprovalForAll"].ID() +} + +func (s *SetApprovalForAllRootERC1155Fn) EncodeAbi() ([]byte, error) { + return RootERC1155.Abi.Methods["setApprovalForAll"].Encode(s) +} + +func (s *SetApprovalForAllRootERC1155Fn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC1155.Abi.Methods["setApprovalForAll"], buf, s) +} + +type MintBatchRootERC1155Fn struct { + To types.Address `abi:"to"` + IDs []*big.Int `abi:"ids"` + Amounts []*big.Int `abi:"amounts"` + Data []byte `abi:"data"` +} + +func (m *MintBatchRootERC1155Fn) Sig() []byte { + return RootERC1155.Abi.Methods["mintBatch"].ID() +} + +func (m *MintBatchRootERC1155Fn) EncodeAbi() ([]byte, error) { + return RootERC1155.Abi.Methods["mintBatch"].Encode(m) +} + +func (m *MintBatchRootERC1155Fn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC1155.Abi.Methods["mintBatch"], buf, m) +} + +type BalanceOfRootERC1155Fn struct { + Account types.Address `abi:"account"` + ID *big.Int `abi:"id"` +} + +func (b *BalanceOfRootERC1155Fn) Sig() []byte { + return RootERC1155.Abi.Methods["balanceOf"].ID() +} + +func (b *BalanceOfRootERC1155Fn) EncodeAbi() ([]byte, error) { + return RootERC1155.Abi.Methods["balanceOf"].Encode(b) +} + +func (b *BalanceOfRootERC1155Fn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC1155.Abi.Methods["balanceOf"], buf, b) +} + +type InitializeChildERC1155PredicateFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewRootERC1155Predicate types.Address `abi:"newRootERC1155Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeChildERC1155PredicateFn) Sig() []byte { + return ChildERC1155Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildERC1155PredicateFn) EncodeAbi() ([]byte, error) { + return ChildERC1155Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildERC1155PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC1155Predicate.Abi.Methods["initialize"], buf, i) +} + +type WithdrawBatchChildERC1155PredicateFn struct { + ChildToken types.Address `abi:"childToken"` + Receivers []ethgo.Address `abi:"receivers"` + TokenIDs []*big.Int `abi:"tokenIds"` + Amounts []*big.Int `abi:"amounts"` +} + +func (w *WithdrawBatchChildERC1155PredicateFn) Sig() []byte { + return ChildERC1155Predicate.Abi.Methods["withdrawBatch"].ID() +} + +func (w *WithdrawBatchChildERC1155PredicateFn) EncodeAbi() ([]byte, error) { + return ChildERC1155Predicate.Abi.Methods["withdrawBatch"].Encode(w) +} + +func (w *WithdrawBatchChildERC1155PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC1155Predicate.Abi.Methods["withdrawBatch"], buf, w) +} + +type InitializeChildERC1155PredicateACLFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewRootERC1155Predicate types.Address `abi:"newRootERC1155Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` + NewUseAllowList bool `abi:"newUseAllowList"` + NewUseBlockList bool `abi:"newUseBlockList"` + NewOwner types.Address `abi:"newOwner"` +} + +func (i *InitializeChildERC1155PredicateACLFn) Sig() []byte { + return ChildERC1155PredicateACL.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildERC1155PredicateACLFn) EncodeAbi() ([]byte, error) { + return ChildERC1155PredicateACL.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildERC1155PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC1155PredicateACL.Abi.Methods["initialize"], buf, i) +} + +type WithdrawBatchChildERC1155PredicateACLFn struct { + ChildToken types.Address `abi:"childToken"` + Receivers []ethgo.Address `abi:"receivers"` + TokenIDs []*big.Int `abi:"tokenIds"` + Amounts []*big.Int `abi:"amounts"` +} + +func (w *WithdrawBatchChildERC1155PredicateACLFn) Sig() []byte { + return ChildERC1155PredicateACL.Abi.Methods["withdrawBatch"].ID() +} + +func (w *WithdrawBatchChildERC1155PredicateACLFn) EncodeAbi() ([]byte, error) { + return ChildERC1155PredicateACL.Abi.Methods["withdrawBatch"].Encode(w) +} + +func (w *WithdrawBatchChildERC1155PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC1155PredicateACL.Abi.Methods["withdrawBatch"], buf, w) +} + +type InitializeRootMintableERC1155PredicateFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewChildERC1155Predicate types.Address `abi:"newChildERC1155Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeRootMintableERC1155PredicateFn) Sig() []byte { + return RootMintableERC1155Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRootMintableERC1155PredicateFn) EncodeAbi() ([]byte, error) { + return RootMintableERC1155Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRootMintableERC1155PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootMintableERC1155Predicate.Abi.Methods["initialize"], buf, i) +} + +type InitializeRootMintableERC1155PredicateACLFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewChildERC1155Predicate types.Address `abi:"newChildERC1155Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` + NewUseAllowList bool `abi:"newUseAllowList"` + NewUseBlockList bool `abi:"newUseBlockList"` + NewOwner types.Address `abi:"newOwner"` +} + +func (i *InitializeRootMintableERC1155PredicateACLFn) Sig() []byte { + return RootMintableERC1155PredicateACL.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRootMintableERC1155PredicateACLFn) EncodeAbi() ([]byte, error) { + return RootMintableERC1155PredicateACL.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRootMintableERC1155PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootMintableERC1155PredicateACL.Abi.Methods["initialize"], buf, i) +} + +type L2MintableTokenMappedEvent struct { + RootToken types.Address `abi:"rootToken"` + ChildToken types.Address `abi:"childToken"` +} + +func (*L2MintableTokenMappedEvent) Sig() ethgo.Hash { + return RootMintableERC1155PredicateACL.Abi.Events["L2MintableTokenMapped"].ID() +} + +func (*L2MintableTokenMappedEvent) Encode(inputs interface{}) ([]byte, error) { + return RootMintableERC1155PredicateACL.Abi.Events["L2MintableTokenMapped"].Inputs.Encode(inputs) +} + +func (l *L2MintableTokenMappedEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !RootMintableERC1155PredicateACL.Abi.Events["L2MintableTokenMapped"].Match(log) { + return false, nil + } + + return true, decodeEvent(RootMintableERC1155PredicateACL.Abi.Events["L2MintableTokenMapped"], log, l) +} + +type InitializeChildERC1155Fn struct { + RootToken_ types.Address `abi:"rootToken_"` + Uri_ string `abi:"uri_"` +} + +func (i *InitializeChildERC1155Fn) Sig() []byte { + return ChildERC1155.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildERC1155Fn) EncodeAbi() ([]byte, error) { + return ChildERC1155.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildERC1155Fn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC1155.Abi.Methods["initialize"], buf, i) +} + +type BalanceOfChildERC1155Fn struct { + Account types.Address `abi:"account"` + ID *big.Int `abi:"id"` +} + +func (b *BalanceOfChildERC1155Fn) Sig() []byte { + return ChildERC1155.Abi.Methods["balanceOf"].ID() +} + +func (b *BalanceOfChildERC1155Fn) EncodeAbi() ([]byte, error) { + return ChildERC1155.Abi.Methods["balanceOf"].Encode(b) +} + +func (b *BalanceOfChildERC1155Fn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC1155.Abi.Methods["balanceOf"], buf, b) +} + +type InitializeRootERC721PredicateFn struct { + NewStateSender types.Address `abi:"newStateSender"` + NewExitHelper types.Address `abi:"newExitHelper"` + NewChildERC721Predicate types.Address `abi:"newChildERC721Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeRootERC721PredicateFn) Sig() []byte { + return RootERC721Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRootERC721PredicateFn) EncodeAbi() ([]byte, error) { + return RootERC721Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRootERC721PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC721Predicate.Abi.Methods["initialize"], buf, i) +} + +type DepositBatchRootERC721PredicateFn struct { + RootToken types.Address `abi:"rootToken"` + Receivers []ethgo.Address `abi:"receivers"` + TokenIDs []*big.Int `abi:"tokenIds"` +} + +func (d *DepositBatchRootERC721PredicateFn) Sig() []byte { + return RootERC721Predicate.Abi.Methods["depositBatch"].ID() +} + +func (d *DepositBatchRootERC721PredicateFn) EncodeAbi() ([]byte, error) { + return RootERC721Predicate.Abi.Methods["depositBatch"].Encode(d) +} + +func (d *DepositBatchRootERC721PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC721Predicate.Abi.Methods["depositBatch"], buf, d) +} + +type InitializeChildMintableERC721PredicateFn struct { + NewStateSender types.Address `abi:"newStateSender"` + NewExitHelper types.Address `abi:"newExitHelper"` + NewRootERC721Predicate types.Address `abi:"newRootERC721Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeChildMintableERC721PredicateFn) Sig() []byte { + return ChildMintableERC721Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildMintableERC721PredicateFn) EncodeAbi() ([]byte, error) { + return ChildMintableERC721Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildMintableERC721PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildMintableERC721Predicate.Abi.Methods["initialize"], buf, i) +} + +type SetApprovalForAllRootERC721Fn struct { + Operator types.Address `abi:"operator"` + Approved bool `abi:"approved"` +} + +func (s *SetApprovalForAllRootERC721Fn) Sig() []byte { + return RootERC721.Abi.Methods["setApprovalForAll"].ID() +} + +func (s *SetApprovalForAllRootERC721Fn) EncodeAbi() ([]byte, error) { + return RootERC721.Abi.Methods["setApprovalForAll"].Encode(s) +} + +func (s *SetApprovalForAllRootERC721Fn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC721.Abi.Methods["setApprovalForAll"], buf, s) +} + +type MintRootERC721Fn struct { + To types.Address `abi:"to"` +} + +func (m *MintRootERC721Fn) Sig() []byte { + return RootERC721.Abi.Methods["mint"].ID() +} + +func (m *MintRootERC721Fn) EncodeAbi() ([]byte, error) { + return RootERC721.Abi.Methods["mint"].Encode(m) +} + +func (m *MintRootERC721Fn) DecodeAbi(buf []byte) error { + return decodeMethod(RootERC721.Abi.Methods["mint"], buf, m) +} + +type InitializeChildERC721PredicateFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewRootERC721Predicate types.Address `abi:"newRootERC721Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeChildERC721PredicateFn) Sig() []byte { + return ChildERC721Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildERC721PredicateFn) EncodeAbi() ([]byte, error) { + return ChildERC721Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildERC721PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC721Predicate.Abi.Methods["initialize"], buf, i) +} + +type WithdrawBatchChildERC721PredicateFn struct { + ChildToken types.Address `abi:"childToken"` + Receivers []ethgo.Address `abi:"receivers"` + TokenIDs []*big.Int `abi:"tokenIds"` +} + +func (w *WithdrawBatchChildERC721PredicateFn) Sig() []byte { + return ChildERC721Predicate.Abi.Methods["withdrawBatch"].ID() +} + +func (w *WithdrawBatchChildERC721PredicateFn) EncodeAbi() ([]byte, error) { + return ChildERC721Predicate.Abi.Methods["withdrawBatch"].Encode(w) +} + +func (w *WithdrawBatchChildERC721PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC721Predicate.Abi.Methods["withdrawBatch"], buf, w) +} + +type InitializeChildERC721PredicateACLFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewRootERC721Predicate types.Address `abi:"newRootERC721Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` + NewUseAllowList bool `abi:"newUseAllowList"` + NewUseBlockList bool `abi:"newUseBlockList"` + NewOwner types.Address `abi:"newOwner"` +} + +func (i *InitializeChildERC721PredicateACLFn) Sig() []byte { + return ChildERC721PredicateACL.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildERC721PredicateACLFn) EncodeAbi() ([]byte, error) { + return ChildERC721PredicateACL.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildERC721PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC721PredicateACL.Abi.Methods["initialize"], buf, i) +} + +type WithdrawBatchChildERC721PredicateACLFn struct { + ChildToken types.Address `abi:"childToken"` + Receivers []ethgo.Address `abi:"receivers"` + TokenIDs []*big.Int `abi:"tokenIds"` +} + +func (w *WithdrawBatchChildERC721PredicateACLFn) Sig() []byte { + return ChildERC721PredicateACL.Abi.Methods["withdrawBatch"].ID() +} + +func (w *WithdrawBatchChildERC721PredicateACLFn) EncodeAbi() ([]byte, error) { + return ChildERC721PredicateACL.Abi.Methods["withdrawBatch"].Encode(w) +} + +func (w *WithdrawBatchChildERC721PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC721PredicateACL.Abi.Methods["withdrawBatch"], buf, w) +} + +type InitializeRootMintableERC721PredicateFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewChildERC721Predicate types.Address `abi:"newChildERC721Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` +} + +func (i *InitializeRootMintableERC721PredicateFn) Sig() []byte { + return RootMintableERC721Predicate.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRootMintableERC721PredicateFn) EncodeAbi() ([]byte, error) { + return RootMintableERC721Predicate.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRootMintableERC721PredicateFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootMintableERC721Predicate.Abi.Methods["initialize"], buf, i) +} + +type InitializeRootMintableERC721PredicateACLFn struct { + NewL2StateSender types.Address `abi:"newL2StateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewChildERC721Predicate types.Address `abi:"newChildERC721Predicate"` + NewChildTokenTemplate types.Address `abi:"newChildTokenTemplate"` + NewUseAllowList bool `abi:"newUseAllowList"` + NewUseBlockList bool `abi:"newUseBlockList"` + NewOwner types.Address `abi:"newOwner"` +} + +func (i *InitializeRootMintableERC721PredicateACLFn) Sig() []byte { + return RootMintableERC721PredicateACL.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRootMintableERC721PredicateACLFn) EncodeAbi() ([]byte, error) { + return RootMintableERC721PredicateACL.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRootMintableERC721PredicateACLFn) DecodeAbi(buf []byte) error { + return decodeMethod(RootMintableERC721PredicateACL.Abi.Methods["initialize"], buf, i) +} + +type InitializeChildERC721Fn struct { + RootToken_ types.Address `abi:"rootToken_"` + Name_ string `abi:"name_"` + Symbol_ string `abi:"symbol_"` +} + +func (i *InitializeChildERC721Fn) Sig() []byte { + return ChildERC721.Abi.Methods["initialize"].ID() +} + +func (i *InitializeChildERC721Fn) EncodeAbi() ([]byte, error) { + return ChildERC721.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeChildERC721Fn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC721.Abi.Methods["initialize"], buf, i) +} + +type OwnerOfChildERC721Fn struct { + TokenID *big.Int `abi:"tokenId"` +} + +func (o *OwnerOfChildERC721Fn) Sig() []byte { + return ChildERC721.Abi.Methods["ownerOf"].ID() +} + +func (o *OwnerOfChildERC721Fn) EncodeAbi() ([]byte, error) { + return ChildERC721.Abi.Methods["ownerOf"].Encode(o) +} + +func (o *OwnerOfChildERC721Fn) DecodeAbi(buf []byte) error { + return decodeMethod(ChildERC721.Abi.Methods["ownerOf"], buf, o) +} + +type InitializeCustomSupernetManagerFn struct { + NewStakeManager types.Address `abi:"newStakeManager"` + NewBls types.Address `abi:"newBls"` + NewStateSender types.Address `abi:"newStateSender"` + NewMatic types.Address `abi:"newMatic"` + NewChildValidatorSet types.Address `abi:"newChildValidatorSet"` + NewExitHelper types.Address `abi:"newExitHelper"` + NewDomain string `abi:"newDomain"` +} + +func (i *InitializeCustomSupernetManagerFn) Sig() []byte { + return CustomSupernetManager.Abi.Methods["initialize"].ID() +} + +func (i *InitializeCustomSupernetManagerFn) EncodeAbi() ([]byte, error) { + return CustomSupernetManager.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeCustomSupernetManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(CustomSupernetManager.Abi.Methods["initialize"], buf, i) +} + +type WhitelistValidatorsCustomSupernetManagerFn struct { + Validators_ []ethgo.Address `abi:"validators_"` +} + +func (w *WhitelistValidatorsCustomSupernetManagerFn) Sig() []byte { + return CustomSupernetManager.Abi.Methods["whitelistValidators"].ID() +} + +func (w *WhitelistValidatorsCustomSupernetManagerFn) EncodeAbi() ([]byte, error) { + return CustomSupernetManager.Abi.Methods["whitelistValidators"].Encode(w) +} + +func (w *WhitelistValidatorsCustomSupernetManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(CustomSupernetManager.Abi.Methods["whitelistValidators"], buf, w) +} + +type RegisterCustomSupernetManagerFn struct { + Signature [2]*big.Int `abi:"signature"` + Pubkey [4]*big.Int `abi:"pubkey"` +} + +func (r *RegisterCustomSupernetManagerFn) Sig() []byte { + return CustomSupernetManager.Abi.Methods["register"].ID() +} + +func (r *RegisterCustomSupernetManagerFn) EncodeAbi() ([]byte, error) { + return CustomSupernetManager.Abi.Methods["register"].Encode(r) +} + +func (r *RegisterCustomSupernetManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(CustomSupernetManager.Abi.Methods["register"], buf, r) +} + +type GetValidatorCustomSupernetManagerFn struct { + Validator_ types.Address `abi:"validator_"` +} + +func (g *GetValidatorCustomSupernetManagerFn) Sig() []byte { + return CustomSupernetManager.Abi.Methods["getValidator"].ID() +} + +func (g *GetValidatorCustomSupernetManagerFn) EncodeAbi() ([]byte, error) { + return CustomSupernetManager.Abi.Methods["getValidator"].Encode(g) +} + +func (g *GetValidatorCustomSupernetManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(CustomSupernetManager.Abi.Methods["getValidator"], buf, g) +} + +type ValidatorRegisteredEvent struct { + Validator types.Address `abi:"validator"` + BlsKey [4]*big.Int `abi:"blsKey"` +} + +func (*ValidatorRegisteredEvent) Sig() ethgo.Hash { + return CustomSupernetManager.Abi.Events["ValidatorRegistered"].ID() +} + +func (*ValidatorRegisteredEvent) Encode(inputs interface{}) ([]byte, error) { + return CustomSupernetManager.Abi.Events["ValidatorRegistered"].Inputs.Encode(inputs) +} + +func (v *ValidatorRegisteredEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !CustomSupernetManager.Abi.Events["ValidatorRegistered"].Match(log) { + return false, nil + } + + return true, decodeEvent(CustomSupernetManager.Abi.Events["ValidatorRegistered"], log, v) +} + +type AddedToWhitelistEvent struct { + Validator types.Address `abi:"validator"` +} + +func (*AddedToWhitelistEvent) Sig() ethgo.Hash { + return CustomSupernetManager.Abi.Events["AddedToWhitelist"].ID() +} + +func (*AddedToWhitelistEvent) Encode(inputs interface{}) ([]byte, error) { + return CustomSupernetManager.Abi.Events["AddedToWhitelist"].Inputs.Encode(inputs) +} + +func (a *AddedToWhitelistEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !CustomSupernetManager.Abi.Events["AddedToWhitelist"].Match(log) { + return false, nil + } + + return true, decodeEvent(CustomSupernetManager.Abi.Events["AddedToWhitelist"], log, a) +} + +type InitializeStakeManagerFn struct { + NewMatic types.Address `abi:"newMatic"` +} + +func (i *InitializeStakeManagerFn) Sig() []byte { + return StakeManager.Abi.Methods["initialize"].ID() +} + +func (i *InitializeStakeManagerFn) EncodeAbi() ([]byte, error) { + return StakeManager.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeStakeManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(StakeManager.Abi.Methods["initialize"], buf, i) +} + +type RegisterChildChainStakeManagerFn struct { + Manager types.Address `abi:"manager"` +} + +func (r *RegisterChildChainStakeManagerFn) Sig() []byte { + return StakeManager.Abi.Methods["registerChildChain"].ID() +} + +func (r *RegisterChildChainStakeManagerFn) EncodeAbi() ([]byte, error) { + return StakeManager.Abi.Methods["registerChildChain"].Encode(r) +} + +func (r *RegisterChildChainStakeManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(StakeManager.Abi.Methods["registerChildChain"], buf, r) +} + +type StakeForStakeManagerFn struct { + ID *big.Int `abi:"id"` + Amount *big.Int `abi:"amount"` +} + +func (s *StakeForStakeManagerFn) Sig() []byte { + return StakeManager.Abi.Methods["stakeFor"].ID() +} + +func (s *StakeForStakeManagerFn) EncodeAbi() ([]byte, error) { + return StakeManager.Abi.Methods["stakeFor"].Encode(s) +} + +func (s *StakeForStakeManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(StakeManager.Abi.Methods["stakeFor"], buf, s) +} + +type ReleaseStakeOfStakeManagerFn struct { + Validator types.Address `abi:"validator"` + Amount *big.Int `abi:"amount"` +} + +func (r *ReleaseStakeOfStakeManagerFn) Sig() []byte { + return StakeManager.Abi.Methods["releaseStakeOf"].ID() +} + +func (r *ReleaseStakeOfStakeManagerFn) EncodeAbi() ([]byte, error) { + return StakeManager.Abi.Methods["releaseStakeOf"].Encode(r) +} + +func (r *ReleaseStakeOfStakeManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(StakeManager.Abi.Methods["releaseStakeOf"], buf, r) +} + +type WithdrawStakeStakeManagerFn struct { + To types.Address `abi:"to"` + Amount *big.Int `abi:"amount"` +} + +func (w *WithdrawStakeStakeManagerFn) Sig() []byte { + return StakeManager.Abi.Methods["withdrawStake"].ID() +} + +func (w *WithdrawStakeStakeManagerFn) EncodeAbi() ([]byte, error) { + return StakeManager.Abi.Methods["withdrawStake"].Encode(w) +} + +func (w *WithdrawStakeStakeManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(StakeManager.Abi.Methods["withdrawStake"], buf, w) +} + +type StakeOfStakeManagerFn struct { + Validator types.Address `abi:"validator"` + ID *big.Int `abi:"id"` +} + +func (s *StakeOfStakeManagerFn) Sig() []byte { + return StakeManager.Abi.Methods["stakeOf"].ID() +} + +func (s *StakeOfStakeManagerFn) EncodeAbi() ([]byte, error) { + return StakeManager.Abi.Methods["stakeOf"].Encode(s) +} + +func (s *StakeOfStakeManagerFn) DecodeAbi(buf []byte) error { + return decodeMethod(StakeManager.Abi.Methods["stakeOf"], buf, s) +} + +type ChildManagerRegisteredEvent struct { + ID *big.Int `abi:"id"` + Manager types.Address `abi:"manager"` +} + +func (*ChildManagerRegisteredEvent) Sig() ethgo.Hash { + return StakeManager.Abi.Events["ChildManagerRegistered"].ID() +} + +func (*ChildManagerRegisteredEvent) Encode(inputs interface{}) ([]byte, error) { + return StakeManager.Abi.Events["ChildManagerRegistered"].Inputs.Encode(inputs) +} + +func (c *ChildManagerRegisteredEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !StakeManager.Abi.Events["ChildManagerRegistered"].Match(log) { + return false, nil + } + + return true, decodeEvent(StakeManager.Abi.Events["ChildManagerRegistered"], log, c) +} + +type StakeAddedEvent struct { + ID *big.Int `abi:"id"` + Validator types.Address `abi:"validator"` + Amount *big.Int `abi:"amount"` +} + +func (*StakeAddedEvent) Sig() ethgo.Hash { + return StakeManager.Abi.Events["StakeAdded"].ID() +} + +func (*StakeAddedEvent) Encode(inputs interface{}) ([]byte, error) { + return StakeManager.Abi.Events["StakeAdded"].Inputs.Encode(inputs) +} + +func (s *StakeAddedEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !StakeManager.Abi.Events["StakeAdded"].Match(log) { + return false, nil + } + + return true, decodeEvent(StakeManager.Abi.Events["StakeAdded"], log, s) +} + +type StakeWithdrawnEvent struct { + Validator types.Address `abi:"validator"` + Recipient types.Address `abi:"recipient"` + Amount *big.Int `abi:"amount"` +} + +func (*StakeWithdrawnEvent) Sig() ethgo.Hash { + return StakeManager.Abi.Events["StakeWithdrawn"].ID() +} + +func (*StakeWithdrawnEvent) Encode(inputs interface{}) ([]byte, error) { + return StakeManager.Abi.Events["StakeWithdrawn"].Inputs.Encode(inputs) +} + +func (s *StakeWithdrawnEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !StakeManager.Abi.Events["StakeWithdrawn"].Match(log) { + return false, nil + } + + return true, decodeEvent(StakeManager.Abi.Events["StakeWithdrawn"], log, s) +} + +type Epoch struct { + StartBlock *big.Int `abi:"startBlock"` + EndBlock *big.Int `abi:"endBlock"` + EpochRoot types.Hash `abi:"epochRoot"` +} + +var EpochABIType = abi.MustNewType("tuple(uint256 startBlock,uint256 endBlock,bytes32 epochRoot)") + +func (e *Epoch) EncodeAbi() ([]byte, error) { + return EpochABIType.Encode(e) +} + +func (e *Epoch) DecodeAbi(buf []byte) error { + return decodeStruct(EpochABIType, buf, &e) +} + +type CommitEpochValidatorSetFn struct { + ID *big.Int `abi:"id"` + Epoch *Epoch `abi:"epoch"` +} + +func (c *CommitEpochValidatorSetFn) Sig() []byte { + return ValidatorSet.Abi.Methods["commitEpoch"].ID() +} + +func (c *CommitEpochValidatorSetFn) EncodeAbi() ([]byte, error) { + return ValidatorSet.Abi.Methods["commitEpoch"].Encode(c) +} + +func (c *CommitEpochValidatorSetFn) DecodeAbi(buf []byte) error { + return decodeMethod(ValidatorSet.Abi.Methods["commitEpoch"], buf, c) +} + +type UnstakeValidatorSetFn struct { + Amount *big.Int `abi:"amount"` +} + +func (u *UnstakeValidatorSetFn) Sig() []byte { + return ValidatorSet.Abi.Methods["unstake"].ID() +} + +func (u *UnstakeValidatorSetFn) EncodeAbi() ([]byte, error) { + return ValidatorSet.Abi.Methods["unstake"].Encode(u) +} + +func (u *UnstakeValidatorSetFn) DecodeAbi(buf []byte) error { + return decodeMethod(ValidatorSet.Abi.Methods["unstake"], buf, u) +} + +type ValidatorInit struct { + Addr types.Address `abi:"addr"` + Stake *big.Int `abi:"stake"` +} + +var ValidatorInitABIType = abi.MustNewType("tuple(address addr,uint256 stake)") + +func (v *ValidatorInit) EncodeAbi() ([]byte, error) { + return ValidatorInitABIType.Encode(v) +} + +func (v *ValidatorInit) DecodeAbi(buf []byte) error { + return decodeStruct(ValidatorInitABIType, buf, &v) +} + +type InitializeValidatorSetFn struct { + NewStateSender types.Address `abi:"newStateSender"` + NewStateReceiver types.Address `abi:"newStateReceiver"` + NewRootChainManager types.Address `abi:"newRootChainManager"` + NewEpochSize *big.Int `abi:"newEpochSize"` + InitialValidators []*ValidatorInit `abi:"initialValidators"` +} + +func (i *InitializeValidatorSetFn) Sig() []byte { + return ValidatorSet.Abi.Methods["initialize"].ID() +} + +func (i *InitializeValidatorSetFn) EncodeAbi() ([]byte, error) { + return ValidatorSet.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeValidatorSetFn) DecodeAbi(buf []byte) error { + return decodeMethod(ValidatorSet.Abi.Methods["initialize"], buf, i) +} + +type TransferEvent struct { + From types.Address `abi:"from"` + To types.Address `abi:"to"` + Value *big.Int `abi:"value"` +} + +func (*TransferEvent) Sig() ethgo.Hash { + return ValidatorSet.Abi.Events["Transfer"].ID() +} + +func (*TransferEvent) Encode(inputs interface{}) ([]byte, error) { + return ValidatorSet.Abi.Events["Transfer"].Inputs.Encode(inputs) +} + +func (t *TransferEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !ValidatorSet.Abi.Events["Transfer"].Match(log) { + return false, nil + } + + return true, decodeEvent(ValidatorSet.Abi.Events["Transfer"], log, t) +} + +type WithdrawalRegisteredEvent struct { + Account types.Address `abi:"account"` + Amount *big.Int `abi:"amount"` +} + +func (*WithdrawalRegisteredEvent) Sig() ethgo.Hash { + return ValidatorSet.Abi.Events["WithdrawalRegistered"].ID() +} + +func (*WithdrawalRegisteredEvent) Encode(inputs interface{}) ([]byte, error) { + return ValidatorSet.Abi.Events["WithdrawalRegistered"].Inputs.Encode(inputs) +} + +func (w *WithdrawalRegisteredEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !ValidatorSet.Abi.Events["WithdrawalRegistered"].Match(log) { + return false, nil + } + + return true, decodeEvent(ValidatorSet.Abi.Events["WithdrawalRegistered"], log, w) +} + +type WithdrawalEvent struct { + Account types.Address `abi:"account"` + Amount *big.Int `abi:"amount"` +} + +func (*WithdrawalEvent) Sig() ethgo.Hash { + return ValidatorSet.Abi.Events["Withdrawal"].ID() +} + +func (*WithdrawalEvent) Encode(inputs interface{}) ([]byte, error) { + return ValidatorSet.Abi.Events["Withdrawal"].Inputs.Encode(inputs) +} + +func (w *WithdrawalEvent) ParseLog(log *ethgo.Log) (bool, error) { + if !ValidatorSet.Abi.Events["Withdrawal"].Match(log) { + return false, nil + } + + return true, decodeEvent(ValidatorSet.Abi.Events["Withdrawal"], log, w) +} + +type InitializeRewardPoolFn struct { + NewRewardToken types.Address `abi:"newRewardToken"` + NewRewardWallet types.Address `abi:"newRewardWallet"` + NewValidatorSet types.Address `abi:"newValidatorSet"` + NewBaseReward *big.Int `abi:"newBaseReward"` +} + +func (i *InitializeRewardPoolFn) Sig() []byte { + return RewardPool.Abi.Methods["initialize"].ID() +} + +func (i *InitializeRewardPoolFn) EncodeAbi() ([]byte, error) { + return RewardPool.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeRewardPoolFn) DecodeAbi(buf []byte) error { + return decodeMethod(RewardPool.Abi.Methods["initialize"], buf, i) +} + +type Uptime struct { + Validator types.Address `abi:"validator"` + SignedBlocks *big.Int `abi:"signedBlocks"` +} + +var UptimeABIType = abi.MustNewType("tuple(address validator,uint256 signedBlocks)") + +func (u *Uptime) EncodeAbi() ([]byte, error) { + return UptimeABIType.Encode(u) +} + +func (u *Uptime) DecodeAbi(buf []byte) error { + return decodeStruct(UptimeABIType, buf, &u) +} + +type DistributeRewardForRewardPoolFn struct { + EpochID *big.Int `abi:"epochId"` + Uptime []*Uptime `abi:"uptime"` +} + +func (d *DistributeRewardForRewardPoolFn) Sig() []byte { + return RewardPool.Abi.Methods["distributeRewardFor"].ID() +} + +func (d *DistributeRewardForRewardPoolFn) EncodeAbi() ([]byte, error) { + return RewardPool.Abi.Methods["distributeRewardFor"].Encode(d) +} + +func (d *DistributeRewardForRewardPoolFn) DecodeAbi(buf []byte) error { + return decodeMethod(RewardPool.Abi.Methods["distributeRewardFor"], buf, d) +} + +type InitializeEIP1559BurnFn struct { + NewChildERC20Predicate types.Address `abi:"newChildERC20Predicate"` + NewBurnDestination types.Address `abi:"newBurnDestination"` +} + +func (i *InitializeEIP1559BurnFn) Sig() []byte { + return EIP1559Burn.Abi.Methods["initialize"].ID() +} + +func (i *InitializeEIP1559BurnFn) EncodeAbi() ([]byte, error) { + return EIP1559Burn.Abi.Methods["initialize"].Encode(i) +} + +func (i *InitializeEIP1559BurnFn) DecodeAbi(buf []byte) error { + return decodeMethod(EIP1559Burn.Abi.Methods["initialize"], buf, i) +} diff --git a/consensus/polybft/contractsapi/contractsapi_test.go b/consensus/polybft/contractsapi/contractsapi_test.go index ad10cd0881..153631d73e 100644 --- a/consensus/polybft/contractsapi/contractsapi_test.go +++ b/consensus/polybft/contractsapi/contractsapi_test.go @@ -33,22 +33,12 @@ func TestEncoding_Method(t *testing.T) { Bitmap: []byte{}, }, // empty commit epoch - &CommitEpochChildValidatorSetFn{ + &CommitEpochValidatorSetFn{ ID: big.NewInt(1), Epoch: &Epoch{ StartBlock: big.NewInt(1), EndBlock: big.NewInt(1), }, - Uptime: &Uptime{ - EpochID: big.NewInt(1), - UptimeData: []*UptimeData{ - { - Validator: types.Address{0x1}, - SignedBlocks: big.NewInt(1), - }, - }, - TotalBlocks: big.NewInt(1), - }, }, } @@ -114,27 +104,27 @@ func TestEncodingAndParsingEvent(t *testing.T) { // log matches event doesMatch, err := exitEvent.ParseLog(log) - require.True(t, doesMatch) require.NoError(t, err) + require.True(t, doesMatch) require.Equal(t, uint64(11), exitEvent.ID.Uint64()) // change exit event id log.Topics[1] = ethgo.BytesToHash(common.EncodeUint64ToBytes(22)) doesMatch, err = exitEvent.ParseLog(log) - require.True(t, doesMatch) require.NoError(t, err) + require.True(t, doesMatch) require.Equal(t, uint64(22), exitEvent.ID.Uint64()) // log does not match event log.Topics[0] = stateSyncEventAPI.Sig() doesMatch, err = exitEvent.ParseLog(log) - require.False(t, doesMatch) require.NoError(t, err) + require.False(t, doesMatch) // error on parsing log log.Topics[0] = exitEventAPI.Sig() log.Topics = log.Topics[:3] doesMatch, err = exitEvent.ParseLog(log) - require.True(t, doesMatch) require.Error(t, err) + require.True(t, doesMatch) } diff --git a/consensus/polybft/contractsapi/gen_sc_data.go b/consensus/polybft/contractsapi/gen_sc_data.go index 0815f7b848..e60b2ed2aa 100644 --- a/consensus/polybft/contractsapi/gen_sc_data.go +++ b/consensus/polybft/contractsapi/gen_sc_data.go @@ -1,19 +1,43 @@ package contractsapi // This is auto-generated file. DO NOT EDIT. -var ChildValidatorSetArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildValidatorSet\",\n \"sourceName\": \"contracts/child/ChildValidatorSet.sol\",\n \"abi\": [\n {\n \"inputs\": [],\n \"name\": \"AmountZero\",\n \"type\": \"error\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Exists\",\n \"type\": \"error\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"signer\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"InvalidSignature\",\n \"type\": \"error\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"NoTokensDelegated\",\n \"type\": \"error\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"NotFound\",\n \"type\": \"error\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"src\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"msg\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"StakeRequirement\",\n \"type\": \"error\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"AddedToWhitelist\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"oldCommission\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"newCommission\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"CommissionUpdated\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"delegator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Delegated\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"delegator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"restake\",\n \"type\": \"bool\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"DelegatorRewardClaimed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"DelegatorRewardDistributed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"key\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"pbftRound\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"DoubleSignerSlashed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"startBlock\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"endBlock\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes32\",\n \"name\": \"epochRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"NewEpoch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n }\n ],\n \"name\": \"NewValidator\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RemovedFromWhitelist\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Staked\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"delegator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Undelegated\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Unstaked\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ValidatorRewardClaimed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ValidatorRewardDistributed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Withdrawal\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"WithdrawalRegistered\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ACTIVE_VALIDATOR_SET_SIZE\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DOMAIN\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DOUBLE_SIGNING_SLASHING_PERCENT\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAX_COMMISSION\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAWAL_WAIT_PERIOD\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"whitelistAddreses\",\n \"type\": \"address[]\"\n }\n ],\n \"name\": \"addToWhitelist\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"bls\",\n \"outputs\": [\n {\n \"internalType\": \"contract IBLS\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"restake\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"claimDelegatorReward\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"claimValidatorReward\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"epochRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct Epoch\",\n \"name\": \"epoch\",\n \"type\": \"tuple\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochId\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"signedBlocks\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct UptimeData[]\",\n \"name\": \"uptimeData\",\n \"type\": \"tuple[]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"totalBlocks\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct Uptime\",\n \"name\": \"uptime\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"commitEpoch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"curEpochId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pbftRound\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"epochRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct Epoch\",\n \"name\": \"epoch\",\n \"type\": \"tuple\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochId\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"signedBlocks\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct UptimeData[]\",\n \"name\": \"uptimeData\",\n \"type\": \"tuple[]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"totalBlocks\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct Uptime\",\n \"name\": \"uptime\",\n \"type\": \"tuple\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"eventRoot\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"currentValidatorSetHash\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"nextValidatorSetHash\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"blockHash\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"bitmap\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"signature\",\n \"type\": \"bytes\"\n }\n ],\n \"internalType\": \"struct IChildValidatorSetBase.DoubleSignerSlashingInput[]\",\n \"name\": \"inputs\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"commitEpochWithDoubleSignerSlashing\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentEpochId\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"restake\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"delegate\",\n \"outputs\": [],\n \"stateMutability\": \"payable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"delegator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"delegationOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"doubleSignerSlashes\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"epochEndBlocks\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"epochReward\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"epochSize\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"epochs\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"epochRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"getCurrentValidatorSet\",\n \"outputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"\",\n \"type\": \"address[]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"delegator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"getDelegatorReward\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getEpochByBlock\",\n \"outputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"epochRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct Epoch\",\n \"name\": \"\",\n \"type\": \"tuple\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"getValidator\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"stake\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"totalStake\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"commission\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"withdrawableRewards\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"active\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"getValidatorReward\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochReward\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"minStake\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"minDelegation\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochSize\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct IChildValidatorSetBase.InitStruct\",\n \"name\": \"init\",\n \"type\": \"tuple\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"addr\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"pubkey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"stake\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct IChildValidatorSetBase.ValidatorInit[]\",\n \"name\": \"validators\",\n \"type\": \"tuple[]\"\n },\n {\n \"internalType\": \"contract IBLS\",\n \"name\": \"newBls\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"governance\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"minDelegation\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"minStake\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"pendingWithdrawals\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"pubkey\",\n \"type\": \"uint256[4]\"\n }\n ],\n \"name\": \"register\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"whitelistAddreses\",\n \"type\": \"address[]\"\n }\n ],\n \"name\": \"removeFromWhitelist\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"newCommission\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"setCommission\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"n\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"sortedValidators\",\n \"outputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"\",\n \"type\": \"address[]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stake\",\n \"outputs\": [],\n \"stateMutability\": \"payable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalActiveStake\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"activeStake\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"totalDelegationOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalStake\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"totalStakeOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"undelegate\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"unstake\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"whitelist\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"withdrawable\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50615f5b80620000216000396000f3fe6080604052600436106102ca5760003560e01c8063715018a61161017b578063a2562ddd116100d7578063e0563ab111610085578063e0563ab114610890578063e30c3978146108a6578063e3f56eaa146108c4578063ea0fee4f146108e4578063eacdc5ff146108f9578063f2fde38b1461090f578063f3f437031461092f57600080fd5b8063a2562ddd146107a4578063a2b915e2146107c4578063a77af229146107e4578063a90049d0146107f9578063ae97dde814610366578063c6b61e4c14610819578063ce513b6f1461087057600080fd5b8063947287cf11610134578063947287cf146106df57806395b0b027146106f557806397e5230d14610715578063982ef0a71461072c5780639a91e6d71461073f5780639b19251a14610754578063a15808791461078457600080fd5b8063715018a61461061057806378f619321461062557806379ba5097146106775780637f6497831461068c5780638b0e9f3f146106ac5780638da5cb5b146106c157600080fd5b80633a4b66f11161022a57806351351d53116101e357806351351d531461052b57806351cff8d91461054657806352a9674b14610566578063548db1741461059a5780635689762f146105ba578063572d356e146105da578063628da527146105f057600080fd5b80633a4b66f11461046b5780633b878c22146104735780633fd5000114610489578063410899c9146104a957806346df33d2146104c95780634d99dd161461050b57600080fd5b80632153f7fa116102875780632153f7fa1461039d578063284017f5146103bd57806328f73148146103e05780632e17de78146103f557806333378ada14610415578063355e6b4314610435578063375b3c0a1461045557600080fd5b80630209fdd0146102cf57806302985992146102fa5780631604e4161461031e5780631904bb2e146103345780631bce714d146103665780631f6590b81461037b575b600080fd5b3480156102db57600080fd5b506102e461094f565b6040516102f191906153b4565b60405180910390f35b34801561030657600080fd5b5061031060055481565b6040519081526020016102f1565b34801561032a57600080fd5b5061031060035481565b34801561034057600080fd5b5061035461034f366004615421565b610960565b6040516102f19695949392919061543e565b34801561037257600080fd5b50610310606481565b34801561038757600080fd5b5061039b610396366004615495565b610a33565b005b3480156103a957600080fd5b506102e46103b83660046154d7565b610b30565b3480156103c957600080fd5b506103d361202081565b6040516102f191906154f0565b3480156103ec57600080fd5b50610310610c3b565b34801561040157600080fd5b5061039b6104103660046154d7565b610d09565b34801561042157600080fd5b50610310610430366004615421565b610e2f565b34801561044157600080fd5b5061039b6104503660046154d7565b610e46565b34801561046157600080fd5b5061031060045481565b61039b610f11565b34801561047f57600080fd5b506103d361101081565b34801561049557600080fd5b506103106104a43660046154d7565b610ff0565b3480156104b557600080fd5b5061039b6104c4366004615516565b611011565b3480156104d557600080fd5b506104e96104e43660046154d7565b61121f565b60408051825181526020808401519082015291810151908201526060016102f1565b34801561051757600080fd5b5061039b61052636600461556d565b611297565b34801561053757600080fd5b506103d36002600160a01b0381565b34801561055257600080fd5b5061039b610561366004615421565b6113a2565b34801561057257600080fd5b506103107ffd10bf199d0185af9cce2005e6acc8d19924428058ac3374e16f18c97569b4ee81565b3480156105a657600080fd5b5061039b6105b53660046155dd565b6114d2565b3480156105c657600080fd5b506103106105d536600461561e565b61152b565b3480156105e657600080fd5b5061031060005481565b3480156105fc57600080fd5b5061031061060b36600461561e565b61154b565b34801561061c57600080fd5b5061039b611562565b34801561063157600080fd5b5061066761064036600461564c565b61013e60209081526000938452604080852082529284528284209052825290205460ff1681565b60405190151581526020016102f1565b34801561068357600080fd5b5061039b611576565b34801561069857600080fd5b5061039b6106a73660046155dd565b6115ed565b3480156106b857600080fd5b50600954610310565b3480156106cd57600080fd5b506076546001600160a01b03166103d3565b3480156106eb57600080fd5b5061031061520881565b34801561070157600080fd5b506006546103d3906001600160a01b031681565b34801561072157600080fd5b50610310620249f081565b61039b61073a366004615693565b611641565b34801561074b57600080fd5b5061039b61169d565b34801561076057600080fd5b5061066761076f366004615421565b60106020526000908152604090205460ff1681565b34801561079057600080fd5b5061039b61079f3660046156c1565b611702565b3480156107b057600080fd5b5061039b6107bf366004615770565b6119d0565b3480156107d057600080fd5b506103106107df366004615421565b611d5e565b3480156107f057600080fd5b50610310600a81565b34801561080557600080fd5b5061039b610814366004615693565b611d72565b34801561082557600080fd5b506108556108343660046154d7565b600f6020526000908152604090208054600182015460029092015490919083565b604080519384526020840192909252908201526060016102f1565b34801561087c57600080fd5b5061031061088b366004615421565b611e13565b34801561089c57600080fd5b506103d361203081565b3480156108b257600080fd5b5060a8546001600160a01b03166103d3565b3480156108d057600080fd5b506103106108df366004615421565b611e41565b3480156108f057600080fd5b50610310600181565b34801561090557600080fd5b5061031060015481565b34801561091b57600080fd5b5061039b61092a366004615421565b611e4e565b34801561093b57600080fd5b5061031061094a366004615421565b611ebf565b606061095b6064610b30565b905090565b610968615329565b6000808080808061097a600789611ee6565b604080516101208101909152908160a081018260048282826020028201915b8154815260200190600101908083116109995750505091835250506004820154602080830191909152600583015460408301526006830154606083015260079283015460ff1615156080909201919091528251908301519099509750909150610a029089611f04565b546020820151610a12919061581f565b94508060400151935080606001519250806080015191505091939550919395565b3360009081526010602052604090205460ff16610a845760405163973d02cb60e01b815260206004820152600960248201526815d2125511531254d560ba1b60448201526064015b60405180910390fd5b610a8f338383611f22565b604080516101208101909152610ae29033908060a0810185600482826080808284376000920182905250928452505060208201819052604082018190526060820152600160809091015260079190611fd7565b610aeb33612380565b336001600160a01b03167fcab5c47e498c5b85fd42d656842253cfe070f7648c3a198275347b47dec5d27b82604051610b249190615832565b60405180910390a25050565b60606000600760010154831115610b4957600854610b4b565b825b90506000816001600160401b03811115610b6757610b67615841565b604051908082528060200260200182016040528015610b90578160200160208202803683370190505b50905081600003610ba2579392505050565b6000610bae60076123c9565b90508082600081518110610bc457610bc4615857565b6001600160a01b039092166020928302919091019091015260015b83811015610c3157610bf260078361242a565b915081838281518110610c0757610c07615857565b6001600160a01b039092166020928302919091019091015280610c298161586d565b915050610bdf565b5090949350505050565b60008060076001015460641115610c5457600854610c57565b60645b905080600003610c6957600091505090565b6000610c7560076123c9565b9050610c82600782611f04565b54610c8e600783611ee6565b60040154610c9c919061581f565b610ca6908461581f565b925060015b82811015610d0357610cbe60078361242a565b9150610ccb600783611f04565b54610cd7600784611ee6565b60040154610ce5919061581f565b610cef908561581f565b935080610cfb8161586d565b915050610cab565b50505090565b6000610d16600c3361252c565b336000908152600a6020526040902060070154610d339190615886565b90506000610d4083612588565b905081811315610d63576040516396906e6360e01b8152600401610a7b906158c0565b6000610d6f8284615905565b905060045481128015610d8157508015155b15610d9f576040516396906e6360e01b8152600401610a7b90615945565b610da761169d565b610dc233610db784600019615968565b600c9190600061259b565b80600003610dea576000610dd7600733611ee6565b600701805460ff19169115159190911790555b610df433856126a2565b60405184815233907f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759060200160405180910390a250505050565b6000610e3c600783611ee6565b6006015492915050565b610e51600733611ee6565b6007015460ff16610e755760405163973d02cb60e01b8152600401610a7b90615998565b6064811115610ebb5760405162461bcd60e51b815260206004820152601260248201527124a72b20a624a22fa1a7a6a6a4a9a9a4a7a760711b6044820152606401610a7b565b6000610ec8600733611ee6565b6005810154604080519182526020820185905291925033917f6e500db30ce535d38852e318f333e9be41a3fec6c65d234ebb06203c896db9a5910160405180910390a260050155565b610f1c600733611ee6565b6007015460ff16610f405760405163973d02cb60e01b8152600401610a7b90615998565b6000610f4d600c3361252c565b336000908152600a6020526040902060070154610f6a9190615886565b905060045481610f7934612588565b610f839190615886565b1215610fa2576040516396906e6360e01b8152600401610a7b906159bb565b610faa61169d565b610fb8600c3334600061259b565b60405134815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9060200160405180910390a250565b6002818154811061100057600080fd5b600091825260209091200154905081565b336002600160a01b03146110385760405163973d02cb60e01b8152600401610a7b906159e9565b60018054600091826110498361586d565b91905055905080841461106e5760405162461bcd60e51b8152600401610a7b90615a0d565b82356020840135116110925760405162461bcd60e51b8152600401610a7b90615a3a565b6000546110a484356020860135615a67565b6110af90600161581f565b6110b99190615a90565b156111145760405162461bcd60e51b815260206004820152602560248201527f45504f43485f4d5553545f42455f444956495349424c455f42595f45504f43486044820152645f53495a4560d81b6064820152608401610a7b565b8235600f6000611125600185615a67565b8152602001908152602001600020600101546001611143919061581f565b146111605760405162461bcd60e51b8152600401610a7b90615aa4565b6000818152600f602090815260408083209186013560018084018290558735845591870135600280850191909155805492830181559093527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace01919091556111c8848461270e565b6111d06128df565b83602001358460000135867f0ce8712c4dee4bd5a691f0bc1c39594671591e77395f8ebf6a3fb5f63fbea66a876040013560405161121091815260200190565b60405180910390a45050505050565b6040805160608101825260008082526020820181905291810182905290611247600284612c12565b9050600f600061125883600161581f565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050915050919050565b60006112a4600784611f04565b905060006112b28233612cc7565b9050808311156112d5576040516396906e6360e01b8152600401610a7b90615aee565b6112e0823385612d13565b60006112ec8483615a67565b9050600554811080156112fe57508015155b1561131c576040516396906e6360e01b8152600401610a7b90615b25565b611327856000611d72565b600061133285612588565b905061135086600061134684600019615968565b600c92919061259b565b61135a33866126a2565b6040518581526001600160a01b0387169033907f4d10bd049775c77bd7f255195afba5088028ecb3c7c277d393ccff7934f2f92c9060200160405180910390a3505050505050565b6113aa612de8565b6001600160a01b0381166113c0576113c0615b48565b336000908152600e6020526040812060015490919081906113e2908490612e41565b80855560405182815291935091506001600160a01b0385169033907f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b63989060200160405180910390a36000846001600160a01b03168360405160006040518083038185875af1925050503d8060008114611477576040519150601f19603f3d011682016040523d82523d6000602084013e61147c565b606091505b50509050806114c15760405162461bcd60e51b815260206004820152601160248201527015d2551211149055d05317d19052531151607a1b6044820152606401610a7b565b505050506114cf600160da55565b50565b6114da612eba565b60005b81811015611526576115148383838181106114fa576114fa615857565b905060200201602081019061150f9190615421565b612380565b8061151e8161586d565b9150506114dd565b505050565b60006115428261153c600786611f04565b90612f14565b90505b92915050565b60006115428261155c600786611f04565b90612cc7565b61156a612eba565b6115746000612f43565b565b60a85433906001600160a01b031681146115e45760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610a7b565b6114cf81612f43565b6115f5612eba565b60005b818110156115265761162f83838381811061161557611615615857565b905060200201602081019061162a9190615421565b612f5c565b806116398161586d565b9150506115f8565b600061164e600784611f04565b6005549091503461165f8333612cc7565b611669919061581f565b1015611688576040516396906e6360e01b8152600401610a7b90615b5e565b6116928383611d72565b611526338434612fa8565b60006116aa600733611ee6565b600681015490915060008190036116bf575050565b600060068301556116d033826126a2565b60405181815233907f378c825c0ac073cbae19612eb73cde31c0972f0c8ba2dedb659840f32550df2b90602001610b24565b604354610100900460ff16158080156117225750604354600160ff909116105b8061173c5750303b15801561173c575060435460ff166001145b61179f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610a7b565b6043805460ff1916600117905580156117c2576043805461ff0019166101001790555b336002600160a01b03146117e95760405163973d02cb60e01b8152600401610a7b906159e9565b6001805560608601356000556117fe82612f43565b611806613073565b853560035560208601356004556040860135600555600680546001600160a01b0319166001600160a01b03851617905560005b848110156119815760006040518060a0016040528088888581811061186057611860615857565b905061010002016020016004806020026040519081016040528092919082600460200280828437600092019190915250505081526020018888858181106118a9576118a9615857565b9050610100020160e00135815260200160008152602001600081526020016001151581525090506119058787848181106118e5576118e5615857565b6118fc926020610100909202019081019150615421565b60079083611fd7565b61196e87878481811061191a5761191a615857565b611931926020610100909202019081019150615421565b88888581811061194357611943615857565b9050610100020160a00189898681811061195f5761195f615857565b90506101000201602001611f22565b50806119798161586d565b915050611839565b5080156119c8576043805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b8060028110156119f25760405162461bcd60e51b8152600401610a7b90615b8f565b6119fc83836130a2565b611a3f5760405162461bcd60e51b8152602060048201526014602482015273424c4f434b484153485f4e4f545f554e4951554560601b6044820152606401610a7b565b60005b81811015611bd957611bd14689868685818110611a6157611a61615857565b9050602002810190611a739190615bb7565b608001358a888887818110611a8a57611a8a615857565b9050602002810190611a9c9190615bb7565b35898988818110611aaf57611aaf615857565b9050602002810190611ac19190615bb7565b602001358a8a89818110611ad757611ad7615857565b9050602002810190611ae99190615bb7565b604001358b8b8a818110611aff57611aff615857565b9050602002810190611b119190615bb7565b604080516020810199909952880196909652606087810195909552608087019390935260a086019190915260c085015260e084015201356101008201526101200160405160208183030381529060405280519060200120858584818110611b7a57611b7a615857565b9050602002810190611b8c9190615bb7565b611b9a9060c0810190615bd7565b878786818110611bac57611bac615857565b9050602002810190611bbe9190615bb7565b611bcc9060a0810190615bd7565b613158565b600101611a42565b506000606460076001015410611bf0576064611bf4565b6008545b90506000611c0182610b30565b90506000826001600160401b03811115611c1d57611c1d615841565b604051908082528060200260200182016040528015611c46578160200160208202803683370190505b50905060005b83811015611d44576000805b86811015611d3a57611c9b898983818110611c7557611c75615857565b9050602002810190611c879190615bb7565b611c959060a0810190615bd7565b8561325c565b15611cae5781611caa8161586d565b9250505b6001821115611d2857611cff858481518110611ccc57611ccc615857565b60200260200101518a8a84818110611ce657611ce6615857565b9050602002810190611cf89190615bb7565b358e6132c6565b6001848481518110611d1357611d13615857565b91151560209283029190910190910152611d3a565b80611d328161586d565b915050611c58565b5050600101611c4c565b50611d518b89898461349d565b5050505050505050505050565b6000611d6b600783611f04565b5492915050565b6000611d7f600784611f04565b90506000611d8d823361383a565b905080600003611d9d5750505050565b8215611db357611dae338583612fa8565b611dbd565b611dbd33826126a2565b821515846001600160a01b0316336001600160a01b03167f6b2cd13395c5d2d1f95934a6a8f884d2cb71e846eb99d6759f7e6a39c060b2d084604051611e0591815260200190565b60405180910390a450505050565b6001546001600160a01b0382166000908152600e602052604081209091611e3a9190612e41565b5092915050565b6000611545600783613881565b611e56612eba565b60a880546001600160a01b0383166001600160a01b03199091168117909155611e876076546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6001546001600160a01b0382166000908152600e60205260408120909161154591906138b6565b6001600160a01b031660009081526003918201602052604090200190565b6001600160a01b031660009081526004919091016020526040902090565b60065460009081906001600160a01b031663ebbdac918585611f438961394c565b6040518463ffffffff1660e01b8152600401611f6193929190615c1d565b6040805180830381865afa158015611f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa19190615c61565b91509150801580611fb0575081155b15611fd05784604051633615713d60e21b8152600401610a7b91906154f0565b5050505050565b6001600160a01b038216611fed57611fed615b48565b611ff78383613a1c565b15612017578160405163cda981d560e01b8152600401610a7b91906154f0565b6001600160a01b0382166000908152600380850160205260409091208251839291909101906120499082906004615347565b50602082810151600483015560408301516005830155606083015160068301556080909201516007909101805460ff191691151591909117905581015160000361209257505050565b82546000906001600160a01b0316816120ab8686613881565b90505b6001600160a01b03821615612121578192506120ca8683613881565b8110156120f9576001600160a01b039182166000908152600387016020526040902060010154909116906120ae565b6001600160a01b039182166000908152600387016020526040902060020154909116906120ae565b6040518060a00160405280846001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160011515815260200185815250866003016000876001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160020160146101000a81548160ff021916908315150217905550608082015181600301600082015181600001906004612256929190615347565b506020820151600482015560408201516005820155606082015160068201556080909101516007909101805460ff191691151591909117905550506001600160a01b0383166122bd5785546001600160a01b0319166001600160a01b03861617865561233a565b6122c78684613881565b811015612306576001600160a01b038381166000908152600388016020526040902060010180546001600160a01b03191691871691909117905561233a565b6001600160a01b038381166000908152600388016020526040902060020180546001600160a01b0319169187169190911790555b6123448686613a6d565b6001860180549060006123568361586d565b91905055508360200151866002016000828254612373919061581f565b9091555050505050505050565b6001600160a01b038116600081815260106020526040808220805460ff19169055517fcdd2e9b91a56913d370075169cefa1602ba36be5301664f752192bb1709df7579190a250565b80546001600160a01b03168015612425575b6001600160a01b0381811660009081526003840160205260409020600201541615612425576001600160a01b039081166000908152600383016020526040902060020154166123db565b919050565b60006001600160a01b038216612453576040516365e52d5160e11b815260040160405180910390fd5b6001600160a01b03828116600090815260038501602052604090206001015416156124aa576001600160a01b0380831660009081526003850160205260409020600101546124a391859116613dba565b9050611545565b506001600160a01b038082166000908152600384016020526040902054165b6001600160a01b0381161580159061250257506001600160a01b0380821660009081526003850160205260409020600101548382169116145b15611545576001600160a01b038082166000908152600385016020526040902054919250166124c9565b6001600160a01b038116600090815260018301602052604081205461255357506000611545565b8261255e8184613e10565b8154811061256e5761256e615857565b906000526020600020906003020160010154905092915050565b6000818181121561154557611545615b48565b6001600160a01b0383166000908152600185016020526040812054908190036126465784546125cb90600161581f565b6001600160a01b03858116600081815260018981016020908152604080842087905580516060810182529485528482018a81529085018981528c548085018e558d8652929094209451600390920290940180546001600160a01b03191691909516178455915191830191909155516002909101559050611fd0565b6000856126538187613e10565b8154811061266357612663615857565b90600052602060002090600302019050838160010160008282546126879190615886565b92505081905550828160020160008282546123739190615886565b6126d381600180546126b4919061581f565b6001600160a01b0385166000908152600e602052604090209190613e46565b816001600160a01b03167f655c1cd0236fb6dc4916f34c8ff10e3b18fcaea5b344dfc16c36fbb1bdfc5df282604051610b2491815260200190565b6001805461271c9190615a67565b8135146127615760405162461bcd60e51b8152602060048201526013602482015272115413d0d217d393d517d0d3d3535255151151606a1b6044820152606401610a7b565b60006127706020830183615c90565b9150506064811180159061278657506008548111155b6127a25760405162461bcd60e51b8152600401610a7b90615b8f565b60006127ac610c3b565b90506000805460646127be9190615cd9565b6127cd86356020880135615a67565b6003546127da9190615cd9565b6127e5906064615cd9565b6127ef9190615cf0565b905060005b838110156119c857600061280b6020870187615c90565b8381811061281b5761281b615857565b9050604002018036038101906128319190615d3a565b805190915060009061284590600790611ee6565b90506000612857604089013587615cd9565b6020840151845161286a90600790611f04565b54600485015461287a919061581f565b6128849088615cd9565b61288e9190615cd9565b6128989190615cf0565b90506000806128ab856000015184613f64565b915091506128bd85600001518361409d565b84516128c99082614108565b5050505050806128d89061586d565b90506127f4565b600c60005b8154811015612aae57600082828154811061290157612901615857565b600091825260209182902060408051606081018252600390930290910180546001600160a01b03168084526001820154948401949094526002015490820152915061294d600782613a1c565b15612a9b57600061295f600783611ee6565b905061297d836020015182600401546129789190615886565b614152565b600482015560208301516009546129979161297891615886565b60095560006129a7600784613881565b905060006129b6600785614168565b90506001600160a01b038116158015906129d95750816129d7600783613881565b105b806129f85750816129f66129ee60078761242a565b600790613881565b115b15612a7e57612a08600785614263565b604080516101208101909152612a7e908590858160a081018260048282826020028201915b815481526020019060010190808311612a2d57505050918352505060048201546020820152600582015460408201526006820154606082015260079182015460ff1615156080909101529190611fd7565b6001600160a01b0384166000908152600d60205260408120555050505b505080612aa79061586d565b90506128e4565b5060005b8154811015612c09576000828281548110612acf57612acf615857565b600091825260209182902060408051606081018252600390930290910180546001600160a01b031680845260018201549484019490945260020154908201529150612b1b600782613a1c565b158015612b3f57506001600160a01b0381166000908152600d602052604090205415155b15612bf6576000612b51600783611ee6565b9050612b608360200151614152565b60048281019190915560408051610120810191829052835460a08201908152612bdb9386938692849290918491906001830160c08601808311612a2d57505050918352505060048201546020820152600582015460408201526006820154606082015260079182015460ff1615156080909101529190611fd7565b6001600160a01b0382166000908152600d6020526040812055505b505080612c029061586d565b9050612ab2565b506000600c5550565b81546000908103612c2557506000611545565b82546000905b80821015612c72576000612c3f8383614644565b60008781526020902090915085908201541115612c5e57809150612c6c565b612c6981600161581f565b92505b50612c2b565b600082118015612c9e575083612c9b86612c8d600186615a67565b600091825260209091200190565b54145b15612cb757612cae600183615a67565b92505050611545565b509050611545565b505092915050565b60008260010154600003612cdd57506000611545565b600183015483546001600160a01b0384166000908152600686016020526040902054612d099190615cd9565b6115429190615cf0565b8254600184015460009190612d289084615cd9565b612d329190615cf0565b6001600160a01b0384166000908152600686016020526040812080549293508392909190612d61908490615a67565b9250508190555080846001016000828254612d7c9190615a67565b90915550506002840154612d9a90612d95908390615cd9565b612588565b6001600160a01b038416600090815260048601602052604081208054909190612dc4908490615886565b9091555050835482908590600090612ddd908490615a67565b909155505050505050565b600260da5403612e3a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a7b565b600260da55565b81546000905b8360010154811015612eac57600081815260028501602090815260409182902082518084019093528054835260010154908201819052841015612e8a5750612eac565b8051612e96908461581f565b9250508080612ea49061586d565b915050612e47565b9250929050565b600160da55565b6076546001600160a01b031633146115745760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a7b565b6001600160a01b0381166000908152600583016020526040812054612f39848461465f565b6115429190615a67565b60a880546001600160a01b03191690556114cf816146d9565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fa850ae9193f515cbae8d35e8925bd2be26627fc91bce650b8652ed254e9cab039190a250565b612fb3600783611ee6565b6007015460ff16612ffb5760405163973d02cb60e01b815260206004820152601160248201527024a72b20a624a22fab20a624a220aa27a960791b6044820152606401610a7b565b61300a82600061134684612588565b613021838261301a600786611f04565b919061472b565b816001600160a01b0316836001600160a01b03167fe5541a6b6103d4fa7e021ed54fad39c66f27a76bd13d374cf6240ae6bd0bb72b8360405161306691815260200190565b60405180910390a3505050565b604354610100900460ff1661309a5760405162461bcd60e51b8152600401610a7b90615d74565b61157461480b565b600081815b8181101561314d5760006130bc82600161581f565b90505b8281101561313a578585828181106130d9576130d9615857565b90506020028101906130eb9190615bb7565b6080013586868481811061310157613101615857565b90506020028101906131139190615bb7565b60800135036131285760009350505050611545565b806131328161586d565b9150506130bf565b50806131458161586d565b9150506130a7565b506001949350505050565b6000806120306001600160a01b0316620249f08888888888604051602001613184959493929190615de8565b60408051601f198184030181529082905261319e91615e45565b6000604051808303818686fa925050503d80600081146131da576040519150601f19603f3d011682016040523d82523d6000602084013e6131df565b606091505b50915091506000818060200190518101906131fa9190615e57565b90508280156132065750805b6132525760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c45440000006044820152606401610a7b565b5050505050505050565b60008061326a600884615cf0565b90506000613279600885615a90565b905084821061328d576000925050506132bf565b6000600160ff83161b8787858181106132a8576132a8615857565b9050013560f81c60f81b60f81c60ff161611925050505b9392505050565b600082815261013e6020908152604080832084845282528083206001600160a01b038716845290915290205460ff16156132ff57505050565b600082815261013e6020908152604080832084845282528083206001600160a01b03871684529091528120805460ff19166001179055613340600785611ee6565b6001600160a01b0385166000908152600b602052604090205490915060649061336b90600a90615cd9565b6133759190615cf0565b6001600160a01b0385166000908152600b60205260408120805490919061339d908490615a67565b9250508190555060006064600a83600401546133b99190615cd9565b6133c39190615cf0565b90506133d0600786614263565b808260040160008282546133e49190615a67565b909155505060408051610120810190915261345e908690848160a08101826004828282602002820191815481526020019060010190808311612a2d57505050918352505060048201546020820152600582015460408201526006820154606082015260079182015460ff1615156080909101529190611fd7565b8284866001600160a01b03167f2d7432ca38933aadba9547f33f0568008e240e52e66f1a16c6182e742bce3b1360405160405180910390a45050505050565b60018054600091826134ae8361586d565b9190505590508085146134d35760405162461bcd60e51b8152600401610a7b90615a0d565b83356020850135116134f75760405162461bcd60e51b8152600401610a7b90615a3a565b8335600f6000613508600185615a67565b8152602001908152602001600020600101546001613526919061581f565b146135435760405162461bcd60e51b8152600401610a7b90615aa4565b6000818152600f6020908152604080832087830135600180830182905589358355928901356002808401919091558054938401815585527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9092019190915591906135b090860186615c90565b915050606481118015906135c657506008548111155b6135e25760405162461bcd60e51b8152600401610a7b90615b8f565b60006135ec610c3b565b90506000805460646135fe9190615cd9565b61360d893560208b0135615a67565b60035461361a9190615cd9565b613625906064615cd9565b61362f9190615cf0565b905060005b838110156137de5786818151811061364e5761364e615857565b60200260200101516137ce57600061366960208a018a615c90565b8381811061367957613679615857565b90506040020180360381019061368f9190615d3a565b80519091506000906136a390600790611ee6565b905060006136b560408c013587615cd9565b602084015184516136c890600790611f04565b5460048501546136d8919061581f565b6136e29088615cd9565b6136ec9190615cd9565b6136f69190615cf0565b9050600080613709856000015184613f64565b9150915081846006016000828254613721919061581f565b909155505084516040518481526001600160a01b03909116907f65da9d8bbc1fc112cfb499f15f17b3bfe4c5070dfca6a3e30f7f5f7f17bd86849060200160405180910390a2845161378190829061377b90600790611f04565b90614832565b84600001516001600160a01b03167f520e62b73478b262ede881cd483440f8e7b8a4651b0ff9154aeb3510089ddbac826040516137c091815260200190565b60405180910390a250505050505b6137d78161586d565b9050613634565b506137e76128df565b876020013588600001358a7f0ce8712c4dee4bd5a691f0bc1c39594671591e77395f8ebf6a3fb5f63fbea66a8b6040013560405161382791815260200190565b60405180910390a4505050505050505050565b60006138468383612f14565b6001600160a01b038316600090815260058501602052604081208054929350839290919061387590849061581f565b90915550909392505050565b6001600160a01b038116600090815260048301602090815260408083205460038601909252822060070154611542919061581f565b60018201546000908082036138cf576000915050611545565b60006138dc600183615a67565b90505b84548110612cbf57600081815260028601602090815260409182902082518084019093528054835260010154908201819052851061391d5750612cbf565b8051613929908561581f565b9350816000036139395750612cbf565b508061394481615e74565b9150506138df565b613954615381565b6006546040516bffffffffffffffffffffffff19606085901b1660208201524660348201526001600160a01b039091169063a850a909907ffd10bf199d0185af9cce2005e6acc8d19924428058ac3374e16f18c97569b4ee906054016040516020818303038152906040526040518363ffffffff1660e01b81526004016139dc929190615e8b565b6040805180830381865afa1580156139f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115459190615ec5565b60006001600160a01b03821615801590611542575082546001600160a01b03838116911614806115425750506001600160a01b03908116600090815260039290920160205260409091205416151590565b60005b82546001600160a01b03838116911614801590613aba57506001600160a01b0382811660009081526003850160205260408082205490921681522060020154600160a01b900460ff165b15613d8c576001600160a01b03808316600090815260038501602052604080822054831680835281832054841683529120600101549091168103613c42576001600160a01b0381811660009081526003860160205260408082205483168252808220600290810154909316808352912090910154909250600160a01b900460ff1615613ba3576001600160a01b0380821660008181526003870160205260408082206002808201805460ff60a01b1990811690915588871685528385208201805482169055825487168552928420018054909216600160a01b1790915591905254169250613d86565b6001600160a01b038082166000908152600386016020526040902060020154811690841603613bd957809250613bd984846148af565b506001600160a01b0380831660009081526003850160205260408082205483168083528183206002808201805460ff60a01b19908116909155825487168652938520018054909316600160a01b1790925591829052549091613c3d91869116614a62565b613d86565b6001600160a01b03818116600090815260038601602052604080822054831682528082206001015490921680825291902060020154909250600160a01b900460ff1615613cec576001600160a01b0380821660008181526003870160205260408082206002808201805460ff60a01b1990811690915588871685528385208201805482169055825487168552928420018054909216600160a01b1790915591905254169250613d86565b6001600160a01b038082166000908152600386016020526040902060010154811690841603613d2257809250613d228484614a62565b506001600160a01b0380831660009081526003850160205260408082205483168083528183206002808201805460ff60a01b19908116909155825487168652938520018054909316600160a01b1790925591829052549091613d86918691166148af565b50613a70565b505080546001600160a01b03166000908152600390910160205260409020600201805460ff60a01b19169055565b60005b6001600160a01b0382811660009081526003850160205260409020600201541615613e0a576001600160a01b03918216600090815260038401602052604090206002015490911690613dbd565b50919050565b6001600160a01b038116600090815260018301602052604081205490819003613e3b57613e3b615b48565b611542600182615a67565b81600003613e5657613e56615b48565b82546001840154818103613ead576040805180820182528581526020808201868152600085815260028a019092529281209151825591516001918201558601805491613ea18361586d565b91905055505050505050565b60006002860181613ebf600185615a67565b815260200190815260200160002060010154905080841015613ee357613ee3615b48565b83811015613f32576040805180820182528681526020808201878152600086815260028b019092529281209151825591516001918201558701805491613f288361586d565b91905055506119c8565b84600287016000613f44600186615a67565b81526020019081526020016000206000016000828254612373919061581f565b60008080613f73600786611ee6565b604080516101208101909152908160a081018260048282826020028201915b815481526020019060010190808311613f925750505091835250506004820154602080830191909152600583015460408301526006830154606083015260079283015460ff161515608090920191909152820151919250600090613ff69088611f04565b54905060008290036140115760008094509450505050612eac565b806000036140285785600094509450505050612eac565b6000614034828461581f565b61403e8489615cd9565b6140489190615cf0565b905060006140568289615a67565b90506000606482876040015161406c9190615cd9565b6140769190615cf0565b9050614082818461581f565b61408c8284615a67565b975097505050505050509250929050565b60006140aa600784611ee6565b9050818160060160008282546140c0919061581f565b90915550506040518281526001600160a01b038416907f65da9d8bbc1fc112cfb499f15f17b3bfe4c5070dfca6a3e30f7f5f7f17bd86849060200160405180910390a2505050565b6141178161377b600785611f04565b816001600160a01b03167f520e62b73478b262ede881cd483440f8e7b8a4651b0ff9154aeb3510089ddbac82604051610b2491815260200190565b60008082121561416457614164615b48565b5090565b60006001600160a01b038216614191576040516365e52d5160e11b815260040160405180910390fd5b6001600160a01b03828116600090815260038501602052604090206002015416156141e1576001600160a01b0380831660009081526003850160205260409020600201546124a391859116614c15565b506001600160a01b038082166000908152600384016020526040902054165b6001600160a01b0381161580159061423957506001600160a01b0380821660009081526003850160205260409020600201548382169116145b15611545576001600160a01b03808216600090815260038501602052604090205491925016614200565b6001600160a01b03811661427957614279615b48565b6142838282613a1c565b6142a25780604051634b2990ed60e11b8152600401610a7b91906154f0565b6001600160a01b038181166000908152600384016020526040812060010154909182911615806142ef57506001600160a01b03838116600090815260038601602052604090206002015416155b156142fb575081614367565b506001600160a01b038083166000908152600385016020526040902060020154165b6001600160a01b0381811660009081526003860160205260409020600101541615614367576001600160a01b0390811660009081526003850160205260409020600101541661431d565b6001600160a01b03818116600090815260038601602052604090206001015416156143b3576001600160a01b0380821660009081526003860160205260409020600101541691506143d6565b6001600160a01b0380821660009081526003860160205260409020600201541691505b6001600160a01b038082166000908152600386016020526040808220548584168352912080546001600160a01b0319169190921690811790915580156144af576001600160a01b038082166000908152600387016020526040902060010154811690831603614477576001600160a01b038181166000908152600387016020526040902060010180546001600160a01b0319169185169190911790556144c9565b6001600160a01b038181166000908152600387016020526040902060020180546001600160a01b0319169185169190911790556144c9565b84546001600160a01b0319166001600160a01b0384161785555b6001600160a01b038281166000818152600388016020526040902060020154600160a01b900460ff1615918616146145a457614506868487614c65565b6001600160a01b03858116600090815260038801602052604080822060018082015488861680865284862092830180549288166001600160a01b03199384168117909155865284862080548316821790556002938401805494909301805494909716938216841787559285529284208054909316821790925590549152815460ff60a01b1916600160a01b9182900460ff1615159091021790559193915b80156145b4576145b48685614d5d565b6001600160a01b0383166000908152600387016020526040812080546001600160a01b0319908116825560018083018054909216909155600290910180546001600160a81b0319169055870180549161460c83615e74565b90915550506001600160a01b038316600090815260038701602052604081206007015460028801805491929091612373908490615a67565b60006146536002848418615cf0565b6115429084841661581f565b6001600160a01b03811660009081526006830160205260408120546002840154829161468f91612d959190615cd9565b6001600160a01b0384166000908152600486016020526040812054919250906146bc906129789084615886565b90506146d0670de0b6b3a764000082615cf0565b95945050505050565b607680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600083600101546000148061473f57508354155b61476357835460018501546147549084615cd9565b61475e9190615cf0565b614765565b815b6001600160a01b038416600090815260068601602052604081208054929350839290919061479490849061581f565b92505081905550808460010160008282546147af919061581f565b90915550508354829085906000906147c890849061581f565b909155505060028401546147e190612d95908390615cd9565b6001600160a01b038416600090815260048601602052604081208054909190612ddd908490615905565b604354610100900460ff16612eb35760405162461bcd60e51b8152600401610a7b90615d74565b8060000361483e575050565b8160010154600003614872576003820154604051636130835f60e01b8152610a7b916001600160a01b0316906004016154f0565b6001820154614889670de0b6b3a764000083615cd9565b6148939190615cf0565b8260020160008282546148a6919061581f565b90915550505050565b6001600160a01b038082166000818152600385016020526040808220600281018054915482871680865293852060010154959094526001600160a01b031990911693851693841790559216908015614932576001600160a01b038181166000908152600387016020526040902080546001600160a01b0319169186169190911790555b6001600160a01b038381166000908152600387016020526040902080546001600160a01b03191691841691821790556149835784546001600160a01b0319166001600160a01b038416178555614a18565b6001600160a01b0380831660009081526003870160205260409020600101548116908516036149e4576001600160a01b038281166000908152600387016020526040902060010180546001600160a01b031916918516919091179055614a18565b6001600160a01b038281166000908152600387016020526040902060020180546001600160a01b0319169185169190911790555b50506001600160a01b039081166000818152600390940160205260408085206001018054939094166001600160a01b03199384168117909455928452919092208054909216179055565b6001600160a01b038082166000818152600385016020526040808220600181018054915482871680865293852060020154959094526001600160a01b031990911693851693841790559216908015614ae5576001600160a01b038181166000908152600387016020526040902080546001600160a01b0319169186169190911790555b6001600160a01b038381166000908152600387016020526040902080546001600160a01b0319169184169182179055614b365784546001600160a01b0319166001600160a01b038416178555614bcb565b6001600160a01b038083166000908152600387016020526040902060020154811690851603614b97576001600160a01b038281166000908152600387016020526040902060020180546001600160a01b031916918516919091179055614bcb565b6001600160a01b038281166000908152600387016020526040902060010180546001600160a01b0319169185169190911790555b50506001600160a01b039081166000818152600390940160205260408085206002018054939094166001600160a01b03199384168117909455928452919092208054909216179055565b60005b6001600160a01b0382811660009081526003850160205260409020600101541615613e0a576001600160a01b03918216600090815260038401602052604090206001015490911690614c18565b6001600160a01b038082166000908152600385016020526040808220548584168352912080546001600160a01b0319169190921690811790915580614cc25783546001600160a01b0319166001600160a01b038416178455614d57565b6001600160a01b038082166000908152600386016020526040902060010154811690831603614d23576001600160a01b038181166000908152600386016020526040902060010180546001600160a01b031916918516919091179055614d57565b6001600160a01b038181166000908152600386016020526040902060020180546001600160a01b0319169185169190911790555b50505050565b60005b82546001600160a01b03838116911614801590614da257506001600160a01b0382166000908152600384016020526040902060020154600160a01b900460ff16155b156152fe576001600160a01b038083166000818152600386016020526040808220548416808352912060010154909216900361506c576001600160a01b038181166000908152600386016020526040808220600290810154909316808352912090910154909250600160a01b900460ff1615614e89576001600160a01b0380831660009081526003860160205260408082206002908101805460ff60a01b1990811690915593851683529120018054909116600160a01b179055614e6684826148af565b6001600160a01b0380821660009081526003860160205260409020600201541691505b6001600160a01b0382811660009081526003860160205260408082206001015490921681522060020154600160a01b900460ff16158015614efc57506001600160a01b038281166000908152600386016020526040808220600290810154909316825290200154600160a01b900460ff16155b15614f37576001600160a01b03821660009081526003850160205260409020600201805460ff60a01b1916600160a01b1790559150816152f8565b6001600160a01b038281166000908152600386016020526040808220600290810154909316825290200154600160a01b900460ff16614fec576001600160a01b0380831660008181526003870160205260408082206001810154909416825281206002908101805460ff60a01b19908116909155929091529091018054909116600160a01b179055614fc98483614a62565b6001600160a01b0380821660009081526003860160205260409020600201541691505b6001600160a01b0380821660009081526003860160205260408082206002908101805487861685528385208301805460ff600160a01b9384900416151590920260ff60a01b1992831617815582548216909255905490941683529120018054909116905561505a84826148af565b83546001600160a01b031692506152f8565b6001600160a01b0381811660009081526003860160205260408082206001015490921680825291902060020154909250600160a01b900460ff161561511c576001600160a01b0380831660009081526003860160205260408082206002908101805460ff60a01b1990811690915593851683529120018054909116600160a01b1790556150f98482614a62565b6001600160a01b0380821660009081526003860160205260409020600101541691505b6001600160a01b038281166000908152600386016020526040808220600290810154909316825290200154600160a01b900460ff1615801561518f57506001600160a01b0382811660009081526003860160205260408082206001015490921681522060020154600160a01b900460ff16155b156151ca576001600160a01b03821660009081526003850160205260409020600201805460ff60a01b1916600160a01b1790559150816152f8565b6001600160a01b0382811660009081526003860160205260408082206001015490921681522060020154600160a01b900460ff16615277576001600160a01b03808316600081815260038701602052604080822060029081018054909516835290822001805460ff60a01b19908116909155919052815416600160a01b17905561525484836148af565b6001600160a01b0380821660009081526003860160205260409020600101541691505b6001600160a01b038082166000908152600386016020526040808220600290810180548786168552838520808401805460ff600160a01b9485900416151590930260ff60a01b19938416179055825482169092556001909101549094168352912001805490911690556152ea8482614a62565b83546001600160a01b031692505b50614d60565b506001600160a01b03166000908152600390910160205260409020600201805460ff60a01b19169055565b60405180608001604052806004906020820280368337509192915050565b8260048101928215615375579160200282015b8281111561537557825182559160200191906001019061535a565b5061416492915061539f565b60405180604001604052806002906020820280368337509192915050565b5b8082111561416457600081556001016153a0565b6020808252825182820181905260009190848201906040850190845b818110156153f55783516001600160a01b0316835292840192918401916001016153d0565b50909695505050505050565b6001600160a01b03811681146114cf57600080fd5b803561242581615401565b60006020828403121561543357600080fd5b81356132bf81615401565b6101208101818860005b6004811015615467578151835260209283019290910190600101615448565b505050608082019690965260a081019490945260c084019290925260e0830152151561010090910152919050565b60008060c083850312156154a857600080fd5b60408301848111156154b957600080fd5b8392508460c0850111156154cc57600080fd5b809150509250929050565b6000602082840312156154e957600080fd5b5035919050565b6001600160a01b0391909116815260200190565b600060608284031215613e0a57600080fd5b600080600060a0848603121561552b57600080fd5b8335925061553c8560208601615504565b915060808401356001600160401b0381111561555757600080fd5b61556386828701615504565b9150509250925092565b6000806040838503121561558057600080fd5b823561558b81615401565b946020939093013593505050565b60008083601f8401126155ab57600080fd5b5081356001600160401b038111156155c257600080fd5b6020830191508360208260051b8501011115612eac57600080fd5b600080602083850312156155f057600080fd5b82356001600160401b0381111561560657600080fd5b61561285828601615599565b90969095509350505050565b6000806040838503121561563157600080fd5b823561563c81615401565b915060208301356154cc81615401565b60008060006060848603121561566157600080fd5b8335925060208401359150604084013561567a81615401565b809150509250925092565b80151581146114cf57600080fd5b600080604083850312156156a657600080fd5b82356156b181615401565b915060208301356154cc81615685565b600080600080600085870360e08112156156da57600080fd5b60808112156156e857600080fd5b5085945060808601356001600160401b038082111561570657600080fd5b818801915088601f83011261571a57600080fd5b81358181111561572957600080fd5b8960208260081b850101111561573e57600080fd5b60208301965080955050505061575660a08701615416565b915061576460c08701615416565b90509295509295909350565b6000806000806000806000610100888a03121561578c57600080fd5b8735965060208801359550604088013594506157ab8960608a01615504565b935060c08801356001600160401b03808211156157c757600080fd5b6157d38b838c01615504565b945060e08a01359150808211156157e957600080fd5b506157f68a828b01615599565b989b979a50959850939692959293505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561154557611545615809565b60808181019083833792915050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161587f5761587f615809565b5060010190565b8082018281126000831280158216821582161715612cbf57612cbf615809565b6007815266756e7374616b6560c81b602082015260400190565b6040815260006158d2604083016158a6565b82810360208401526132bf816014815273494e53554646494349454e545f42414c414e434560601b602082015260400190565b8181036000831280158383131683831282161715611e3a57611e3a615809565b600d81526c5354414b455f544f4f5f4c4f5760981b602082015260400190565b604081526000615957604083016158a6565b82810360208401526132bf81615925565b80820260008212600160ff1b8414161561598457615984615809565b818105831482151761154557611545615809565b6020808252600990820152682b20a624a220aa27a960b91b604082015260600190565b6040815260056040820152647374616b6560d81b606082015260806020820152600061154560808301615925565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b60208082526013908201527215539156141150d5115117d15413d0d217d251606a1b604082015260600190565b6020808252601390820152721393d7d09313d0d2d4d7d0d3d3535255151151606a1b604082015260600190565b8181038181111561154557611545615809565b634e487b7160e01b600052601260045260246000fd5b600082615a9f57615a9f615a7a565b500690565b602080825260139082015272494e56414c49445f53544152545f424c4f434b60681b604082015260600190565b600a815269756e64656c656761746560b01b602082015260400190565b6040815260006158d260408301615ad1565b601281527144454c45474154494f4e5f544f4f5f4c4f5760701b602082015260400190565b604081526000615b3760408301615ad1565b82810360208401526132bf81615b00565b634e487b7160e01b600052600160045260246000fd5b60408152600860408201526764656c656761746560c01b606082015260806020820152600061154560808301615b00565b6020808252600e908201526d0929cac82989288be988a9c8ea8960931b604082015260600190565b6000823560de19833603018112615bcd57600080fd5b9190910192915050565b6000808335601e19843603018112615bee57600080fd5b8301803591506001600160401b03821115615c0857600080fd5b602001915036819003821315612eac57600080fd5b61010081016040858337608084604084013760c082018360005b6002811015615c56578151835260209283019290910190600101615c37565b505050949350505050565b60008060408385031215615c7457600080fd5b8251615c7f81615685565b60208401519092506154cc81615685565b6000808335601e19843603018112615ca757600080fd5b8301803591506001600160401b03821115615cc157600080fd5b6020019150600681901b3603821315612eac57600080fd5b808202811582820484141761154557611545615809565b600082615cff57615cff615a7a565b500490565b604080519081016001600160401b0381118282101715615d3457634e487b7160e01b600052604160045260246000fd5b60405290565b600060408284031215615d4c57600080fd5b615d54615d04565b8235615d5f81615401565b81526020928301359281019290925250919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b858152606060208201526000615e02606083018688615dbf565b8281036040840152615e15818587615dbf565b98975050505050505050565b60005b83811015615e3c578181015183820152602001615e24565b50506000910152565b60008251615bcd818460208701615e21565b600060208284031215615e6957600080fd5b81516132bf81615685565b600081615e8357615e83615809565b506000190190565b8281526040602082015260008251806040840152615eb0816060850160208701615e21565b601f01601f1916919091016060019392505050565b600060408284031215615ed757600080fd5b82601f830112615ee657600080fd5b615eee615d04565b806040840185811115615f0057600080fd5b845b81811015615f1a578051845260209384019301615f02565b50909594505050505056fea2646970667358221220a626fbc30de48fae03e0787e09215ca109af7c4393b840809136a8d3e07d3add64736f6c63430008110033\",\n \"deployedBytecode\": \"0x6080604052600436106102ca5760003560e01c8063715018a61161017b578063a2562ddd116100d7578063e0563ab111610085578063e0563ab114610890578063e30c3978146108a6578063e3f56eaa146108c4578063ea0fee4f146108e4578063eacdc5ff146108f9578063f2fde38b1461090f578063f3f437031461092f57600080fd5b8063a2562ddd146107a4578063a2b915e2146107c4578063a77af229146107e4578063a90049d0146107f9578063ae97dde814610366578063c6b61e4c14610819578063ce513b6f1461087057600080fd5b8063947287cf11610134578063947287cf146106df57806395b0b027146106f557806397e5230d14610715578063982ef0a71461072c5780639a91e6d71461073f5780639b19251a14610754578063a15808791461078457600080fd5b8063715018a61461061057806378f619321461062557806379ba5097146106775780637f6497831461068c5780638b0e9f3f146106ac5780638da5cb5b146106c157600080fd5b80633a4b66f11161022a57806351351d53116101e357806351351d531461052b57806351cff8d91461054657806352a9674b14610566578063548db1741461059a5780635689762f146105ba578063572d356e146105da578063628da527146105f057600080fd5b80633a4b66f11461046b5780633b878c22146104735780633fd5000114610489578063410899c9146104a957806346df33d2146104c95780634d99dd161461050b57600080fd5b80632153f7fa116102875780632153f7fa1461039d578063284017f5146103bd57806328f73148146103e05780632e17de78146103f557806333378ada14610415578063355e6b4314610435578063375b3c0a1461045557600080fd5b80630209fdd0146102cf57806302985992146102fa5780631604e4161461031e5780631904bb2e146103345780631bce714d146103665780631f6590b81461037b575b600080fd5b3480156102db57600080fd5b506102e461094f565b6040516102f191906153b4565b60405180910390f35b34801561030657600080fd5b5061031060055481565b6040519081526020016102f1565b34801561032a57600080fd5b5061031060035481565b34801561034057600080fd5b5061035461034f366004615421565b610960565b6040516102f19695949392919061543e565b34801561037257600080fd5b50610310606481565b34801561038757600080fd5b5061039b610396366004615495565b610a33565b005b3480156103a957600080fd5b506102e46103b83660046154d7565b610b30565b3480156103c957600080fd5b506103d361202081565b6040516102f191906154f0565b3480156103ec57600080fd5b50610310610c3b565b34801561040157600080fd5b5061039b6104103660046154d7565b610d09565b34801561042157600080fd5b50610310610430366004615421565b610e2f565b34801561044157600080fd5b5061039b6104503660046154d7565b610e46565b34801561046157600080fd5b5061031060045481565b61039b610f11565b34801561047f57600080fd5b506103d361101081565b34801561049557600080fd5b506103106104a43660046154d7565b610ff0565b3480156104b557600080fd5b5061039b6104c4366004615516565b611011565b3480156104d557600080fd5b506104e96104e43660046154d7565b61121f565b60408051825181526020808401519082015291810151908201526060016102f1565b34801561051757600080fd5b5061039b61052636600461556d565b611297565b34801561053757600080fd5b506103d36002600160a01b0381565b34801561055257600080fd5b5061039b610561366004615421565b6113a2565b34801561057257600080fd5b506103107ffd10bf199d0185af9cce2005e6acc8d19924428058ac3374e16f18c97569b4ee81565b3480156105a657600080fd5b5061039b6105b53660046155dd565b6114d2565b3480156105c657600080fd5b506103106105d536600461561e565b61152b565b3480156105e657600080fd5b5061031060005481565b3480156105fc57600080fd5b5061031061060b36600461561e565b61154b565b34801561061c57600080fd5b5061039b611562565b34801561063157600080fd5b5061066761064036600461564c565b61013e60209081526000938452604080852082529284528284209052825290205460ff1681565b60405190151581526020016102f1565b34801561068357600080fd5b5061039b611576565b34801561069857600080fd5b5061039b6106a73660046155dd565b6115ed565b3480156106b857600080fd5b50600954610310565b3480156106cd57600080fd5b506076546001600160a01b03166103d3565b3480156106eb57600080fd5b5061031061520881565b34801561070157600080fd5b506006546103d3906001600160a01b031681565b34801561072157600080fd5b50610310620249f081565b61039b61073a366004615693565b611641565b34801561074b57600080fd5b5061039b61169d565b34801561076057600080fd5b5061066761076f366004615421565b60106020526000908152604090205460ff1681565b34801561079057600080fd5b5061039b61079f3660046156c1565b611702565b3480156107b057600080fd5b5061039b6107bf366004615770565b6119d0565b3480156107d057600080fd5b506103106107df366004615421565b611d5e565b3480156107f057600080fd5b50610310600a81565b34801561080557600080fd5b5061039b610814366004615693565b611d72565b34801561082557600080fd5b506108556108343660046154d7565b600f6020526000908152604090208054600182015460029092015490919083565b604080519384526020840192909252908201526060016102f1565b34801561087c57600080fd5b5061031061088b366004615421565b611e13565b34801561089c57600080fd5b506103d361203081565b3480156108b257600080fd5b5060a8546001600160a01b03166103d3565b3480156108d057600080fd5b506103106108df366004615421565b611e41565b3480156108f057600080fd5b50610310600181565b34801561090557600080fd5b5061031060015481565b34801561091b57600080fd5b5061039b61092a366004615421565b611e4e565b34801561093b57600080fd5b5061031061094a366004615421565b611ebf565b606061095b6064610b30565b905090565b610968615329565b6000808080808061097a600789611ee6565b604080516101208101909152908160a081018260048282826020028201915b8154815260200190600101908083116109995750505091835250506004820154602080830191909152600583015460408301526006830154606083015260079283015460ff1615156080909201919091528251908301519099509750909150610a029089611f04565b546020820151610a12919061581f565b94508060400151935080606001519250806080015191505091939550919395565b3360009081526010602052604090205460ff16610a845760405163973d02cb60e01b815260206004820152600960248201526815d2125511531254d560ba1b60448201526064015b60405180910390fd5b610a8f338383611f22565b604080516101208101909152610ae29033908060a0810185600482826080808284376000920182905250928452505060208201819052604082018190526060820152600160809091015260079190611fd7565b610aeb33612380565b336001600160a01b03167fcab5c47e498c5b85fd42d656842253cfe070f7648c3a198275347b47dec5d27b82604051610b249190615832565b60405180910390a25050565b60606000600760010154831115610b4957600854610b4b565b825b90506000816001600160401b03811115610b6757610b67615841565b604051908082528060200260200182016040528015610b90578160200160208202803683370190505b50905081600003610ba2579392505050565b6000610bae60076123c9565b90508082600081518110610bc457610bc4615857565b6001600160a01b039092166020928302919091019091015260015b83811015610c3157610bf260078361242a565b915081838281518110610c0757610c07615857565b6001600160a01b039092166020928302919091019091015280610c298161586d565b915050610bdf565b5090949350505050565b60008060076001015460641115610c5457600854610c57565b60645b905080600003610c6957600091505090565b6000610c7560076123c9565b9050610c82600782611f04565b54610c8e600783611ee6565b60040154610c9c919061581f565b610ca6908461581f565b925060015b82811015610d0357610cbe60078361242a565b9150610ccb600783611f04565b54610cd7600784611ee6565b60040154610ce5919061581f565b610cef908561581f565b935080610cfb8161586d565b915050610cab565b50505090565b6000610d16600c3361252c565b336000908152600a6020526040902060070154610d339190615886565b90506000610d4083612588565b905081811315610d63576040516396906e6360e01b8152600401610a7b906158c0565b6000610d6f8284615905565b905060045481128015610d8157508015155b15610d9f576040516396906e6360e01b8152600401610a7b90615945565b610da761169d565b610dc233610db784600019615968565b600c9190600061259b565b80600003610dea576000610dd7600733611ee6565b600701805460ff19169115159190911790555b610df433856126a2565b60405184815233907f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759060200160405180910390a250505050565b6000610e3c600783611ee6565b6006015492915050565b610e51600733611ee6565b6007015460ff16610e755760405163973d02cb60e01b8152600401610a7b90615998565b6064811115610ebb5760405162461bcd60e51b815260206004820152601260248201527124a72b20a624a22fa1a7a6a6a4a9a9a4a7a760711b6044820152606401610a7b565b6000610ec8600733611ee6565b6005810154604080519182526020820185905291925033917f6e500db30ce535d38852e318f333e9be41a3fec6c65d234ebb06203c896db9a5910160405180910390a260050155565b610f1c600733611ee6565b6007015460ff16610f405760405163973d02cb60e01b8152600401610a7b90615998565b6000610f4d600c3361252c565b336000908152600a6020526040902060070154610f6a9190615886565b905060045481610f7934612588565b610f839190615886565b1215610fa2576040516396906e6360e01b8152600401610a7b906159bb565b610faa61169d565b610fb8600c3334600061259b565b60405134815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9060200160405180910390a250565b6002818154811061100057600080fd5b600091825260209091200154905081565b336002600160a01b03146110385760405163973d02cb60e01b8152600401610a7b906159e9565b60018054600091826110498361586d565b91905055905080841461106e5760405162461bcd60e51b8152600401610a7b90615a0d565b82356020840135116110925760405162461bcd60e51b8152600401610a7b90615a3a565b6000546110a484356020860135615a67565b6110af90600161581f565b6110b99190615a90565b156111145760405162461bcd60e51b815260206004820152602560248201527f45504f43485f4d5553545f42455f444956495349424c455f42595f45504f43486044820152645f53495a4560d81b6064820152608401610a7b565b8235600f6000611125600185615a67565b8152602001908152602001600020600101546001611143919061581f565b146111605760405162461bcd60e51b8152600401610a7b90615aa4565b6000818152600f602090815260408083209186013560018084018290558735845591870135600280850191909155805492830181559093527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace01919091556111c8848461270e565b6111d06128df565b83602001358460000135867f0ce8712c4dee4bd5a691f0bc1c39594671591e77395f8ebf6a3fb5f63fbea66a876040013560405161121091815260200190565b60405180910390a45050505050565b6040805160608101825260008082526020820181905291810182905290611247600284612c12565b9050600f600061125883600161581f565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050915050919050565b60006112a4600784611f04565b905060006112b28233612cc7565b9050808311156112d5576040516396906e6360e01b8152600401610a7b90615aee565b6112e0823385612d13565b60006112ec8483615a67565b9050600554811080156112fe57508015155b1561131c576040516396906e6360e01b8152600401610a7b90615b25565b611327856000611d72565b600061133285612588565b905061135086600061134684600019615968565b600c92919061259b565b61135a33866126a2565b6040518581526001600160a01b0387169033907f4d10bd049775c77bd7f255195afba5088028ecb3c7c277d393ccff7934f2f92c9060200160405180910390a3505050505050565b6113aa612de8565b6001600160a01b0381166113c0576113c0615b48565b336000908152600e6020526040812060015490919081906113e2908490612e41565b80855560405182815291935091506001600160a01b0385169033907f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b63989060200160405180910390a36000846001600160a01b03168360405160006040518083038185875af1925050503d8060008114611477576040519150601f19603f3d011682016040523d82523d6000602084013e61147c565b606091505b50509050806114c15760405162461bcd60e51b815260206004820152601160248201527015d2551211149055d05317d19052531151607a1b6044820152606401610a7b565b505050506114cf600160da55565b50565b6114da612eba565b60005b81811015611526576115148383838181106114fa576114fa615857565b905060200201602081019061150f9190615421565b612380565b8061151e8161586d565b9150506114dd565b505050565b60006115428261153c600786611f04565b90612f14565b90505b92915050565b60006115428261155c600786611f04565b90612cc7565b61156a612eba565b6115746000612f43565b565b60a85433906001600160a01b031681146115e45760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610a7b565b6114cf81612f43565b6115f5612eba565b60005b818110156115265761162f83838381811061161557611615615857565b905060200201602081019061162a9190615421565b612f5c565b806116398161586d565b9150506115f8565b600061164e600784611f04565b6005549091503461165f8333612cc7565b611669919061581f565b1015611688576040516396906e6360e01b8152600401610a7b90615b5e565b6116928383611d72565b611526338434612fa8565b60006116aa600733611ee6565b600681015490915060008190036116bf575050565b600060068301556116d033826126a2565b60405181815233907f378c825c0ac073cbae19612eb73cde31c0972f0c8ba2dedb659840f32550df2b90602001610b24565b604354610100900460ff16158080156117225750604354600160ff909116105b8061173c5750303b15801561173c575060435460ff166001145b61179f5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610a7b565b6043805460ff1916600117905580156117c2576043805461ff0019166101001790555b336002600160a01b03146117e95760405163973d02cb60e01b8152600401610a7b906159e9565b6001805560608601356000556117fe82612f43565b611806613073565b853560035560208601356004556040860135600555600680546001600160a01b0319166001600160a01b03851617905560005b848110156119815760006040518060a0016040528088888581811061186057611860615857565b905061010002016020016004806020026040519081016040528092919082600460200280828437600092019190915250505081526020018888858181106118a9576118a9615857565b9050610100020160e00135815260200160008152602001600081526020016001151581525090506119058787848181106118e5576118e5615857565b6118fc926020610100909202019081019150615421565b60079083611fd7565b61196e87878481811061191a5761191a615857565b611931926020610100909202019081019150615421565b88888581811061194357611943615857565b9050610100020160a00189898681811061195f5761195f615857565b90506101000201602001611f22565b50806119798161586d565b915050611839565b5080156119c8576043805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b8060028110156119f25760405162461bcd60e51b8152600401610a7b90615b8f565b6119fc83836130a2565b611a3f5760405162461bcd60e51b8152602060048201526014602482015273424c4f434b484153485f4e4f545f554e4951554560601b6044820152606401610a7b565b60005b81811015611bd957611bd14689868685818110611a6157611a61615857565b9050602002810190611a739190615bb7565b608001358a888887818110611a8a57611a8a615857565b9050602002810190611a9c9190615bb7565b35898988818110611aaf57611aaf615857565b9050602002810190611ac19190615bb7565b602001358a8a89818110611ad757611ad7615857565b9050602002810190611ae99190615bb7565b604001358b8b8a818110611aff57611aff615857565b9050602002810190611b119190615bb7565b604080516020810199909952880196909652606087810195909552608087019390935260a086019190915260c085015260e084015201356101008201526101200160405160208183030381529060405280519060200120858584818110611b7a57611b7a615857565b9050602002810190611b8c9190615bb7565b611b9a9060c0810190615bd7565b878786818110611bac57611bac615857565b9050602002810190611bbe9190615bb7565b611bcc9060a0810190615bd7565b613158565b600101611a42565b506000606460076001015410611bf0576064611bf4565b6008545b90506000611c0182610b30565b90506000826001600160401b03811115611c1d57611c1d615841565b604051908082528060200260200182016040528015611c46578160200160208202803683370190505b50905060005b83811015611d44576000805b86811015611d3a57611c9b898983818110611c7557611c75615857565b9050602002810190611c879190615bb7565b611c959060a0810190615bd7565b8561325c565b15611cae5781611caa8161586d565b9250505b6001821115611d2857611cff858481518110611ccc57611ccc615857565b60200260200101518a8a84818110611ce657611ce6615857565b9050602002810190611cf89190615bb7565b358e6132c6565b6001848481518110611d1357611d13615857565b91151560209283029190910190910152611d3a565b80611d328161586d565b915050611c58565b5050600101611c4c565b50611d518b89898461349d565b5050505050505050505050565b6000611d6b600783611f04565b5492915050565b6000611d7f600784611f04565b90506000611d8d823361383a565b905080600003611d9d5750505050565b8215611db357611dae338583612fa8565b611dbd565b611dbd33826126a2565b821515846001600160a01b0316336001600160a01b03167f6b2cd13395c5d2d1f95934a6a8f884d2cb71e846eb99d6759f7e6a39c060b2d084604051611e0591815260200190565b60405180910390a450505050565b6001546001600160a01b0382166000908152600e602052604081209091611e3a9190612e41565b5092915050565b6000611545600783613881565b611e56612eba565b60a880546001600160a01b0383166001600160a01b03199091168117909155611e876076546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6001546001600160a01b0382166000908152600e60205260408120909161154591906138b6565b6001600160a01b031660009081526003918201602052604090200190565b6001600160a01b031660009081526004919091016020526040902090565b60065460009081906001600160a01b031663ebbdac918585611f438961394c565b6040518463ffffffff1660e01b8152600401611f6193929190615c1d565b6040805180830381865afa158015611f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa19190615c61565b91509150801580611fb0575081155b15611fd05784604051633615713d60e21b8152600401610a7b91906154f0565b5050505050565b6001600160a01b038216611fed57611fed615b48565b611ff78383613a1c565b15612017578160405163cda981d560e01b8152600401610a7b91906154f0565b6001600160a01b0382166000908152600380850160205260409091208251839291909101906120499082906004615347565b50602082810151600483015560408301516005830155606083015160068301556080909201516007909101805460ff191691151591909117905581015160000361209257505050565b82546000906001600160a01b0316816120ab8686613881565b90505b6001600160a01b03821615612121578192506120ca8683613881565b8110156120f9576001600160a01b039182166000908152600387016020526040902060010154909116906120ae565b6001600160a01b039182166000908152600387016020526040902060020154909116906120ae565b6040518060a00160405280846001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160011515815260200185815250866003016000876001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060208201518160010160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160020160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060608201518160020160146101000a81548160ff021916908315150217905550608082015181600301600082015181600001906004612256929190615347565b506020820151600482015560408201516005820155606082015160068201556080909101516007909101805460ff191691151591909117905550506001600160a01b0383166122bd5785546001600160a01b0319166001600160a01b03861617865561233a565b6122c78684613881565b811015612306576001600160a01b038381166000908152600388016020526040902060010180546001600160a01b03191691871691909117905561233a565b6001600160a01b038381166000908152600388016020526040902060020180546001600160a01b0319169187169190911790555b6123448686613a6d565b6001860180549060006123568361586d565b91905055508360200151866002016000828254612373919061581f565b9091555050505050505050565b6001600160a01b038116600081815260106020526040808220805460ff19169055517fcdd2e9b91a56913d370075169cefa1602ba36be5301664f752192bb1709df7579190a250565b80546001600160a01b03168015612425575b6001600160a01b0381811660009081526003840160205260409020600201541615612425576001600160a01b039081166000908152600383016020526040902060020154166123db565b919050565b60006001600160a01b038216612453576040516365e52d5160e11b815260040160405180910390fd5b6001600160a01b03828116600090815260038501602052604090206001015416156124aa576001600160a01b0380831660009081526003850160205260409020600101546124a391859116613dba565b9050611545565b506001600160a01b038082166000908152600384016020526040902054165b6001600160a01b0381161580159061250257506001600160a01b0380821660009081526003850160205260409020600101548382169116145b15611545576001600160a01b038082166000908152600385016020526040902054919250166124c9565b6001600160a01b038116600090815260018301602052604081205461255357506000611545565b8261255e8184613e10565b8154811061256e5761256e615857565b906000526020600020906003020160010154905092915050565b6000818181121561154557611545615b48565b6001600160a01b0383166000908152600185016020526040812054908190036126465784546125cb90600161581f565b6001600160a01b03858116600081815260018981016020908152604080842087905580516060810182529485528482018a81529085018981528c548085018e558d8652929094209451600390920290940180546001600160a01b03191691909516178455915191830191909155516002909101559050611fd0565b6000856126538187613e10565b8154811061266357612663615857565b90600052602060002090600302019050838160010160008282546126879190615886565b92505081905550828160020160008282546123739190615886565b6126d381600180546126b4919061581f565b6001600160a01b0385166000908152600e602052604090209190613e46565b816001600160a01b03167f655c1cd0236fb6dc4916f34c8ff10e3b18fcaea5b344dfc16c36fbb1bdfc5df282604051610b2491815260200190565b6001805461271c9190615a67565b8135146127615760405162461bcd60e51b8152602060048201526013602482015272115413d0d217d393d517d0d3d3535255151151606a1b6044820152606401610a7b565b60006127706020830183615c90565b9150506064811180159061278657506008548111155b6127a25760405162461bcd60e51b8152600401610a7b90615b8f565b60006127ac610c3b565b90506000805460646127be9190615cd9565b6127cd86356020880135615a67565b6003546127da9190615cd9565b6127e5906064615cd9565b6127ef9190615cf0565b905060005b838110156119c857600061280b6020870187615c90565b8381811061281b5761281b615857565b9050604002018036038101906128319190615d3a565b805190915060009061284590600790611ee6565b90506000612857604089013587615cd9565b6020840151845161286a90600790611f04565b54600485015461287a919061581f565b6128849088615cd9565b61288e9190615cd9565b6128989190615cf0565b90506000806128ab856000015184613f64565b915091506128bd85600001518361409d565b84516128c99082614108565b5050505050806128d89061586d565b90506127f4565b600c60005b8154811015612aae57600082828154811061290157612901615857565b600091825260209182902060408051606081018252600390930290910180546001600160a01b03168084526001820154948401949094526002015490820152915061294d600782613a1c565b15612a9b57600061295f600783611ee6565b905061297d836020015182600401546129789190615886565b614152565b600482015560208301516009546129979161297891615886565b60095560006129a7600784613881565b905060006129b6600785614168565b90506001600160a01b038116158015906129d95750816129d7600783613881565b105b806129f85750816129f66129ee60078761242a565b600790613881565b115b15612a7e57612a08600785614263565b604080516101208101909152612a7e908590858160a081018260048282826020028201915b815481526020019060010190808311612a2d57505050918352505060048201546020820152600582015460408201526006820154606082015260079182015460ff1615156080909101529190611fd7565b6001600160a01b0384166000908152600d60205260408120555050505b505080612aa79061586d565b90506128e4565b5060005b8154811015612c09576000828281548110612acf57612acf615857565b600091825260209182902060408051606081018252600390930290910180546001600160a01b031680845260018201549484019490945260020154908201529150612b1b600782613a1c565b158015612b3f57506001600160a01b0381166000908152600d602052604090205415155b15612bf6576000612b51600783611ee6565b9050612b608360200151614152565b60048281019190915560408051610120810191829052835460a08201908152612bdb9386938692849290918491906001830160c08601808311612a2d57505050918352505060048201546020820152600582015460408201526006820154606082015260079182015460ff1615156080909101529190611fd7565b6001600160a01b0382166000908152600d6020526040812055505b505080612c029061586d565b9050612ab2565b506000600c5550565b81546000908103612c2557506000611545565b82546000905b80821015612c72576000612c3f8383614644565b60008781526020902090915085908201541115612c5e57809150612c6c565b612c6981600161581f565b92505b50612c2b565b600082118015612c9e575083612c9b86612c8d600186615a67565b600091825260209091200190565b54145b15612cb757612cae600183615a67565b92505050611545565b509050611545565b505092915050565b60008260010154600003612cdd57506000611545565b600183015483546001600160a01b0384166000908152600686016020526040902054612d099190615cd9565b6115429190615cf0565b8254600184015460009190612d289084615cd9565b612d329190615cf0565b6001600160a01b0384166000908152600686016020526040812080549293508392909190612d61908490615a67565b9250508190555080846001016000828254612d7c9190615a67565b90915550506002840154612d9a90612d95908390615cd9565b612588565b6001600160a01b038416600090815260048601602052604081208054909190612dc4908490615886565b9091555050835482908590600090612ddd908490615a67565b909155505050505050565b600260da5403612e3a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a7b565b600260da55565b81546000905b8360010154811015612eac57600081815260028501602090815260409182902082518084019093528054835260010154908201819052841015612e8a5750612eac565b8051612e96908461581f565b9250508080612ea49061586d565b915050612e47565b9250929050565b600160da55565b6076546001600160a01b031633146115745760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a7b565b6001600160a01b0381166000908152600583016020526040812054612f39848461465f565b6115429190615a67565b60a880546001600160a01b03191690556114cf816146d9565b6001600160a01b038116600081815260106020526040808220805460ff19166001179055517fa850ae9193f515cbae8d35e8925bd2be26627fc91bce650b8652ed254e9cab039190a250565b612fb3600783611ee6565b6007015460ff16612ffb5760405163973d02cb60e01b815260206004820152601160248201527024a72b20a624a22fab20a624a220aa27a960791b6044820152606401610a7b565b61300a82600061134684612588565b613021838261301a600786611f04565b919061472b565b816001600160a01b0316836001600160a01b03167fe5541a6b6103d4fa7e021ed54fad39c66f27a76bd13d374cf6240ae6bd0bb72b8360405161306691815260200190565b60405180910390a3505050565b604354610100900460ff1661309a5760405162461bcd60e51b8152600401610a7b90615d74565b61157461480b565b600081815b8181101561314d5760006130bc82600161581f565b90505b8281101561313a578585828181106130d9576130d9615857565b90506020028101906130eb9190615bb7565b6080013586868481811061310157613101615857565b90506020028101906131139190615bb7565b60800135036131285760009350505050611545565b806131328161586d565b9150506130bf565b50806131458161586d565b9150506130a7565b506001949350505050565b6000806120306001600160a01b0316620249f08888888888604051602001613184959493929190615de8565b60408051601f198184030181529082905261319e91615e45565b6000604051808303818686fa925050503d80600081146131da576040519150601f19603f3d011682016040523d82523d6000602084013e6131df565b606091505b50915091506000818060200190518101906131fa9190615e57565b90508280156132065750805b6132525760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c45440000006044820152606401610a7b565b5050505050505050565b60008061326a600884615cf0565b90506000613279600885615a90565b905084821061328d576000925050506132bf565b6000600160ff83161b8787858181106132a8576132a8615857565b9050013560f81c60f81b60f81c60ff161611925050505b9392505050565b600082815261013e6020908152604080832084845282528083206001600160a01b038716845290915290205460ff16156132ff57505050565b600082815261013e6020908152604080832084845282528083206001600160a01b03871684529091528120805460ff19166001179055613340600785611ee6565b6001600160a01b0385166000908152600b602052604090205490915060649061336b90600a90615cd9565b6133759190615cf0565b6001600160a01b0385166000908152600b60205260408120805490919061339d908490615a67565b9250508190555060006064600a83600401546133b99190615cd9565b6133c39190615cf0565b90506133d0600786614263565b808260040160008282546133e49190615a67565b909155505060408051610120810190915261345e908690848160a08101826004828282602002820191815481526020019060010190808311612a2d57505050918352505060048201546020820152600582015460408201526006820154606082015260079182015460ff1615156080909101529190611fd7565b8284866001600160a01b03167f2d7432ca38933aadba9547f33f0568008e240e52e66f1a16c6182e742bce3b1360405160405180910390a45050505050565b60018054600091826134ae8361586d565b9190505590508085146134d35760405162461bcd60e51b8152600401610a7b90615a0d565b83356020850135116134f75760405162461bcd60e51b8152600401610a7b90615a3a565b8335600f6000613508600185615a67565b8152602001908152602001600020600101546001613526919061581f565b146135435760405162461bcd60e51b8152600401610a7b90615aa4565b6000818152600f6020908152604080832087830135600180830182905589358355928901356002808401919091558054938401815585527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace9092019190915591906135b090860186615c90565b915050606481118015906135c657506008548111155b6135e25760405162461bcd60e51b8152600401610a7b90615b8f565b60006135ec610c3b565b90506000805460646135fe9190615cd9565b61360d893560208b0135615a67565b60035461361a9190615cd9565b613625906064615cd9565b61362f9190615cf0565b905060005b838110156137de5786818151811061364e5761364e615857565b60200260200101516137ce57600061366960208a018a615c90565b8381811061367957613679615857565b90506040020180360381019061368f9190615d3a565b80519091506000906136a390600790611ee6565b905060006136b560408c013587615cd9565b602084015184516136c890600790611f04565b5460048501546136d8919061581f565b6136e29088615cd9565b6136ec9190615cd9565b6136f69190615cf0565b9050600080613709856000015184613f64565b9150915081846006016000828254613721919061581f565b909155505084516040518481526001600160a01b03909116907f65da9d8bbc1fc112cfb499f15f17b3bfe4c5070dfca6a3e30f7f5f7f17bd86849060200160405180910390a2845161378190829061377b90600790611f04565b90614832565b84600001516001600160a01b03167f520e62b73478b262ede881cd483440f8e7b8a4651b0ff9154aeb3510089ddbac826040516137c091815260200190565b60405180910390a250505050505b6137d78161586d565b9050613634565b506137e76128df565b876020013588600001358a7f0ce8712c4dee4bd5a691f0bc1c39594671591e77395f8ebf6a3fb5f63fbea66a8b6040013560405161382791815260200190565b60405180910390a4505050505050505050565b60006138468383612f14565b6001600160a01b038316600090815260058501602052604081208054929350839290919061387590849061581f565b90915550909392505050565b6001600160a01b038116600090815260048301602090815260408083205460038601909252822060070154611542919061581f565b60018201546000908082036138cf576000915050611545565b60006138dc600183615a67565b90505b84548110612cbf57600081815260028601602090815260409182902082518084019093528054835260010154908201819052851061391d5750612cbf565b8051613929908561581f565b9350816000036139395750612cbf565b508061394481615e74565b9150506138df565b613954615381565b6006546040516bffffffffffffffffffffffff19606085901b1660208201524660348201526001600160a01b039091169063a850a909907ffd10bf199d0185af9cce2005e6acc8d19924428058ac3374e16f18c97569b4ee906054016040516020818303038152906040526040518363ffffffff1660e01b81526004016139dc929190615e8b565b6040805180830381865afa1580156139f8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115459190615ec5565b60006001600160a01b03821615801590611542575082546001600160a01b03838116911614806115425750506001600160a01b03908116600090815260039290920160205260409091205416151590565b60005b82546001600160a01b03838116911614801590613aba57506001600160a01b0382811660009081526003850160205260408082205490921681522060020154600160a01b900460ff165b15613d8c576001600160a01b03808316600090815260038501602052604080822054831680835281832054841683529120600101549091168103613c42576001600160a01b0381811660009081526003860160205260408082205483168252808220600290810154909316808352912090910154909250600160a01b900460ff1615613ba3576001600160a01b0380821660008181526003870160205260408082206002808201805460ff60a01b1990811690915588871685528385208201805482169055825487168552928420018054909216600160a01b1790915591905254169250613d86565b6001600160a01b038082166000908152600386016020526040902060020154811690841603613bd957809250613bd984846148af565b506001600160a01b0380831660009081526003850160205260408082205483168083528183206002808201805460ff60a01b19908116909155825487168652938520018054909316600160a01b1790925591829052549091613c3d91869116614a62565b613d86565b6001600160a01b03818116600090815260038601602052604080822054831682528082206001015490921680825291902060020154909250600160a01b900460ff1615613cec576001600160a01b0380821660008181526003870160205260408082206002808201805460ff60a01b1990811690915588871685528385208201805482169055825487168552928420018054909216600160a01b1790915591905254169250613d86565b6001600160a01b038082166000908152600386016020526040902060010154811690841603613d2257809250613d228484614a62565b506001600160a01b0380831660009081526003850160205260408082205483168083528183206002808201805460ff60a01b19908116909155825487168652938520018054909316600160a01b1790925591829052549091613d86918691166148af565b50613a70565b505080546001600160a01b03166000908152600390910160205260409020600201805460ff60a01b19169055565b60005b6001600160a01b0382811660009081526003850160205260409020600201541615613e0a576001600160a01b03918216600090815260038401602052604090206002015490911690613dbd565b50919050565b6001600160a01b038116600090815260018301602052604081205490819003613e3b57613e3b615b48565b611542600182615a67565b81600003613e5657613e56615b48565b82546001840154818103613ead576040805180820182528581526020808201868152600085815260028a019092529281209151825591516001918201558601805491613ea18361586d565b91905055505050505050565b60006002860181613ebf600185615a67565b815260200190815260200160002060010154905080841015613ee357613ee3615b48565b83811015613f32576040805180820182528681526020808201878152600086815260028b019092529281209151825591516001918201558701805491613f288361586d565b91905055506119c8565b84600287016000613f44600186615a67565b81526020019081526020016000206000016000828254612373919061581f565b60008080613f73600786611ee6565b604080516101208101909152908160a081018260048282826020028201915b815481526020019060010190808311613f925750505091835250506004820154602080830191909152600583015460408301526006830154606083015260079283015460ff161515608090920191909152820151919250600090613ff69088611f04565b54905060008290036140115760008094509450505050612eac565b806000036140285785600094509450505050612eac565b6000614034828461581f565b61403e8489615cd9565b6140489190615cf0565b905060006140568289615a67565b90506000606482876040015161406c9190615cd9565b6140769190615cf0565b9050614082818461581f565b61408c8284615a67565b975097505050505050509250929050565b60006140aa600784611ee6565b9050818160060160008282546140c0919061581f565b90915550506040518281526001600160a01b038416907f65da9d8bbc1fc112cfb499f15f17b3bfe4c5070dfca6a3e30f7f5f7f17bd86849060200160405180910390a2505050565b6141178161377b600785611f04565b816001600160a01b03167f520e62b73478b262ede881cd483440f8e7b8a4651b0ff9154aeb3510089ddbac82604051610b2491815260200190565b60008082121561416457614164615b48565b5090565b60006001600160a01b038216614191576040516365e52d5160e11b815260040160405180910390fd5b6001600160a01b03828116600090815260038501602052604090206002015416156141e1576001600160a01b0380831660009081526003850160205260409020600201546124a391859116614c15565b506001600160a01b038082166000908152600384016020526040902054165b6001600160a01b0381161580159061423957506001600160a01b0380821660009081526003850160205260409020600201548382169116145b15611545576001600160a01b03808216600090815260038501602052604090205491925016614200565b6001600160a01b03811661427957614279615b48565b6142838282613a1c565b6142a25780604051634b2990ed60e11b8152600401610a7b91906154f0565b6001600160a01b038181166000908152600384016020526040812060010154909182911615806142ef57506001600160a01b03838116600090815260038601602052604090206002015416155b156142fb575081614367565b506001600160a01b038083166000908152600385016020526040902060020154165b6001600160a01b0381811660009081526003860160205260409020600101541615614367576001600160a01b0390811660009081526003850160205260409020600101541661431d565b6001600160a01b03818116600090815260038601602052604090206001015416156143b3576001600160a01b0380821660009081526003860160205260409020600101541691506143d6565b6001600160a01b0380821660009081526003860160205260409020600201541691505b6001600160a01b038082166000908152600386016020526040808220548584168352912080546001600160a01b0319169190921690811790915580156144af576001600160a01b038082166000908152600387016020526040902060010154811690831603614477576001600160a01b038181166000908152600387016020526040902060010180546001600160a01b0319169185169190911790556144c9565b6001600160a01b038181166000908152600387016020526040902060020180546001600160a01b0319169185169190911790556144c9565b84546001600160a01b0319166001600160a01b0384161785555b6001600160a01b038281166000818152600388016020526040902060020154600160a01b900460ff1615918616146145a457614506868487614c65565b6001600160a01b03858116600090815260038801602052604080822060018082015488861680865284862092830180549288166001600160a01b03199384168117909155865284862080548316821790556002938401805494909301805494909716938216841787559285529284208054909316821790925590549152815460ff60a01b1916600160a01b9182900460ff1615159091021790559193915b80156145b4576145b48685614d5d565b6001600160a01b0383166000908152600387016020526040812080546001600160a01b0319908116825560018083018054909216909155600290910180546001600160a81b0319169055870180549161460c83615e74565b90915550506001600160a01b038316600090815260038701602052604081206007015460028801805491929091612373908490615a67565b60006146536002848418615cf0565b6115429084841661581f565b6001600160a01b03811660009081526006830160205260408120546002840154829161468f91612d959190615cd9565b6001600160a01b0384166000908152600486016020526040812054919250906146bc906129789084615886565b90506146d0670de0b6b3a764000082615cf0565b95945050505050565b607680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600083600101546000148061473f57508354155b61476357835460018501546147549084615cd9565b61475e9190615cf0565b614765565b815b6001600160a01b038416600090815260068601602052604081208054929350839290919061479490849061581f565b92505081905550808460010160008282546147af919061581f565b90915550508354829085906000906147c890849061581f565b909155505060028401546147e190612d95908390615cd9565b6001600160a01b038416600090815260048601602052604081208054909190612ddd908490615905565b604354610100900460ff16612eb35760405162461bcd60e51b8152600401610a7b90615d74565b8060000361483e575050565b8160010154600003614872576003820154604051636130835f60e01b8152610a7b916001600160a01b0316906004016154f0565b6001820154614889670de0b6b3a764000083615cd9565b6148939190615cf0565b8260020160008282546148a6919061581f565b90915550505050565b6001600160a01b038082166000818152600385016020526040808220600281018054915482871680865293852060010154959094526001600160a01b031990911693851693841790559216908015614932576001600160a01b038181166000908152600387016020526040902080546001600160a01b0319169186169190911790555b6001600160a01b038381166000908152600387016020526040902080546001600160a01b03191691841691821790556149835784546001600160a01b0319166001600160a01b038416178555614a18565b6001600160a01b0380831660009081526003870160205260409020600101548116908516036149e4576001600160a01b038281166000908152600387016020526040902060010180546001600160a01b031916918516919091179055614a18565b6001600160a01b038281166000908152600387016020526040902060020180546001600160a01b0319169185169190911790555b50506001600160a01b039081166000818152600390940160205260408085206001018054939094166001600160a01b03199384168117909455928452919092208054909216179055565b6001600160a01b038082166000818152600385016020526040808220600181018054915482871680865293852060020154959094526001600160a01b031990911693851693841790559216908015614ae5576001600160a01b038181166000908152600387016020526040902080546001600160a01b0319169186169190911790555b6001600160a01b038381166000908152600387016020526040902080546001600160a01b0319169184169182179055614b365784546001600160a01b0319166001600160a01b038416178555614bcb565b6001600160a01b038083166000908152600387016020526040902060020154811690851603614b97576001600160a01b038281166000908152600387016020526040902060020180546001600160a01b031916918516919091179055614bcb565b6001600160a01b038281166000908152600387016020526040902060010180546001600160a01b0319169185169190911790555b50506001600160a01b039081166000818152600390940160205260408085206002018054939094166001600160a01b03199384168117909455928452919092208054909216179055565b60005b6001600160a01b0382811660009081526003850160205260409020600101541615613e0a576001600160a01b03918216600090815260038401602052604090206001015490911690614c18565b6001600160a01b038082166000908152600385016020526040808220548584168352912080546001600160a01b0319169190921690811790915580614cc25783546001600160a01b0319166001600160a01b038416178455614d57565b6001600160a01b038082166000908152600386016020526040902060010154811690831603614d23576001600160a01b038181166000908152600386016020526040902060010180546001600160a01b031916918516919091179055614d57565b6001600160a01b038181166000908152600386016020526040902060020180546001600160a01b0319169185169190911790555b50505050565b60005b82546001600160a01b03838116911614801590614da257506001600160a01b0382166000908152600384016020526040902060020154600160a01b900460ff16155b156152fe576001600160a01b038083166000818152600386016020526040808220548416808352912060010154909216900361506c576001600160a01b038181166000908152600386016020526040808220600290810154909316808352912090910154909250600160a01b900460ff1615614e89576001600160a01b0380831660009081526003860160205260408082206002908101805460ff60a01b1990811690915593851683529120018054909116600160a01b179055614e6684826148af565b6001600160a01b0380821660009081526003860160205260409020600201541691505b6001600160a01b0382811660009081526003860160205260408082206001015490921681522060020154600160a01b900460ff16158015614efc57506001600160a01b038281166000908152600386016020526040808220600290810154909316825290200154600160a01b900460ff16155b15614f37576001600160a01b03821660009081526003850160205260409020600201805460ff60a01b1916600160a01b1790559150816152f8565b6001600160a01b038281166000908152600386016020526040808220600290810154909316825290200154600160a01b900460ff16614fec576001600160a01b0380831660008181526003870160205260408082206001810154909416825281206002908101805460ff60a01b19908116909155929091529091018054909116600160a01b179055614fc98483614a62565b6001600160a01b0380821660009081526003860160205260409020600201541691505b6001600160a01b0380821660009081526003860160205260408082206002908101805487861685528385208301805460ff600160a01b9384900416151590920260ff60a01b1992831617815582548216909255905490941683529120018054909116905561505a84826148af565b83546001600160a01b031692506152f8565b6001600160a01b0381811660009081526003860160205260408082206001015490921680825291902060020154909250600160a01b900460ff161561511c576001600160a01b0380831660009081526003860160205260408082206002908101805460ff60a01b1990811690915593851683529120018054909116600160a01b1790556150f98482614a62565b6001600160a01b0380821660009081526003860160205260409020600101541691505b6001600160a01b038281166000908152600386016020526040808220600290810154909316825290200154600160a01b900460ff1615801561518f57506001600160a01b0382811660009081526003860160205260408082206001015490921681522060020154600160a01b900460ff16155b156151ca576001600160a01b03821660009081526003850160205260409020600201805460ff60a01b1916600160a01b1790559150816152f8565b6001600160a01b0382811660009081526003860160205260408082206001015490921681522060020154600160a01b900460ff16615277576001600160a01b03808316600081815260038701602052604080822060029081018054909516835290822001805460ff60a01b19908116909155919052815416600160a01b17905561525484836148af565b6001600160a01b0380821660009081526003860160205260409020600101541691505b6001600160a01b038082166000908152600386016020526040808220600290810180548786168552838520808401805460ff600160a01b9485900416151590930260ff60a01b19938416179055825482169092556001909101549094168352912001805490911690556152ea8482614a62565b83546001600160a01b031692505b50614d60565b506001600160a01b03166000908152600390910160205260409020600201805460ff60a01b19169055565b60405180608001604052806004906020820280368337509192915050565b8260048101928215615375579160200282015b8281111561537557825182559160200191906001019061535a565b5061416492915061539f565b60405180604001604052806002906020820280368337509192915050565b5b8082111561416457600081556001016153a0565b6020808252825182820181905260009190848201906040850190845b818110156153f55783516001600160a01b0316835292840192918401916001016153d0565b50909695505050505050565b6001600160a01b03811681146114cf57600080fd5b803561242581615401565b60006020828403121561543357600080fd5b81356132bf81615401565b6101208101818860005b6004811015615467578151835260209283019290910190600101615448565b505050608082019690965260a081019490945260c084019290925260e0830152151561010090910152919050565b60008060c083850312156154a857600080fd5b60408301848111156154b957600080fd5b8392508460c0850111156154cc57600080fd5b809150509250929050565b6000602082840312156154e957600080fd5b5035919050565b6001600160a01b0391909116815260200190565b600060608284031215613e0a57600080fd5b600080600060a0848603121561552b57600080fd5b8335925061553c8560208601615504565b915060808401356001600160401b0381111561555757600080fd5b61556386828701615504565b9150509250925092565b6000806040838503121561558057600080fd5b823561558b81615401565b946020939093013593505050565b60008083601f8401126155ab57600080fd5b5081356001600160401b038111156155c257600080fd5b6020830191508360208260051b8501011115612eac57600080fd5b600080602083850312156155f057600080fd5b82356001600160401b0381111561560657600080fd5b61561285828601615599565b90969095509350505050565b6000806040838503121561563157600080fd5b823561563c81615401565b915060208301356154cc81615401565b60008060006060848603121561566157600080fd5b8335925060208401359150604084013561567a81615401565b809150509250925092565b80151581146114cf57600080fd5b600080604083850312156156a657600080fd5b82356156b181615401565b915060208301356154cc81615685565b600080600080600085870360e08112156156da57600080fd5b60808112156156e857600080fd5b5085945060808601356001600160401b038082111561570657600080fd5b818801915088601f83011261571a57600080fd5b81358181111561572957600080fd5b8960208260081b850101111561573e57600080fd5b60208301965080955050505061575660a08701615416565b915061576460c08701615416565b90509295509295909350565b6000806000806000806000610100888a03121561578c57600080fd5b8735965060208801359550604088013594506157ab8960608a01615504565b935060c08801356001600160401b03808211156157c757600080fd5b6157d38b838c01615504565b945060e08a01359150808211156157e957600080fd5b506157f68a828b01615599565b989b979a50959850939692959293505050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561154557611545615809565b60808181019083833792915050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60006001820161587f5761587f615809565b5060010190565b8082018281126000831280158216821582161715612cbf57612cbf615809565b6007815266756e7374616b6560c81b602082015260400190565b6040815260006158d2604083016158a6565b82810360208401526132bf816014815273494e53554646494349454e545f42414c414e434560601b602082015260400190565b8181036000831280158383131683831282161715611e3a57611e3a615809565b600d81526c5354414b455f544f4f5f4c4f5760981b602082015260400190565b604081526000615957604083016158a6565b82810360208401526132bf81615925565b80820260008212600160ff1b8414161561598457615984615809565b818105831482151761154557611545615809565b6020808252600990820152682b20a624a220aa27a960b91b604082015260600190565b6040815260056040820152647374616b6560d81b606082015260806020820152600061154560808301615925565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b60208082526013908201527215539156141150d5115117d15413d0d217d251606a1b604082015260600190565b6020808252601390820152721393d7d09313d0d2d4d7d0d3d3535255151151606a1b604082015260600190565b8181038181111561154557611545615809565b634e487b7160e01b600052601260045260246000fd5b600082615a9f57615a9f615a7a565b500690565b602080825260139082015272494e56414c49445f53544152545f424c4f434b60681b604082015260600190565b600a815269756e64656c656761746560b01b602082015260400190565b6040815260006158d260408301615ad1565b601281527144454c45474154494f4e5f544f4f5f4c4f5760701b602082015260400190565b604081526000615b3760408301615ad1565b82810360208401526132bf81615b00565b634e487b7160e01b600052600160045260246000fd5b60408152600860408201526764656c656761746560c01b606082015260806020820152600061154560808301615b00565b6020808252600e908201526d0929cac82989288be988a9c8ea8960931b604082015260600190565b6000823560de19833603018112615bcd57600080fd5b9190910192915050565b6000808335601e19843603018112615bee57600080fd5b8301803591506001600160401b03821115615c0857600080fd5b602001915036819003821315612eac57600080fd5b61010081016040858337608084604084013760c082018360005b6002811015615c56578151835260209283019290910190600101615c37565b505050949350505050565b60008060408385031215615c7457600080fd5b8251615c7f81615685565b60208401519092506154cc81615685565b6000808335601e19843603018112615ca757600080fd5b8301803591506001600160401b03821115615cc157600080fd5b6020019150600681901b3603821315612eac57600080fd5b808202811582820484141761154557611545615809565b600082615cff57615cff615a7a565b500490565b604080519081016001600160401b0381118282101715615d3457634e487b7160e01b600052604160045260246000fd5b60405290565b600060408284031215615d4c57600080fd5b615d54615d04565b8235615d5f81615401565b81526020928301359281019290925250919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b858152606060208201526000615e02606083018688615dbf565b8281036040840152615e15818587615dbf565b98975050505050505050565b60005b83811015615e3c578181015183820152602001615e24565b50506000910152565b60008251615bcd818460208701615e21565b600060208284031215615e6957600080fd5b81516132bf81615685565b600081615e8357615e83615809565b506000190190565b8281526040602082015260008251806040840152615eb0816060850160208701615e21565b601f01601f1916919091016060019392505050565b600060408284031215615ed757600080fd5b82601f830112615ee657600080fd5b615eee615d04565b806040840185811115615f0057600080fd5b845b81811015615f1a578051845260209384019301615f02565b50909594505050505056fea2646970667358221220a626fbc30de48fae03e0787e09215ca109af7c4393b840809136a8d3e07d3add64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var L2StateSenderArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"L2StateSender\",\n \"sourceName\": \"contracts/child/L2StateSender.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"L2StateSynced\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAX_LENGTH\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"counter\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"syncState\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610297806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806316f198311461004657806361bc221a1461005b578063a6f9885c14610076575b600080fd5b61005961005436600461017a565b61007f565b005b61006460005481565b60405190815260200160405180910390f35b61006461080081565b6001600160a01b0383166100cd5760405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b60448201526064015b60405180910390fd5b6108008111156101145760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b60448201526064016100c4565b826001600160a01b0316336001600160a01b031660008081546101369061020b565b9190508190557fedaf3c471ebd67d60c29efe34b639ede7d6a1d92eaeb3f503e784971e67118a5858560405161016d929190610232565b60405180910390a4505050565b60008060006040848603121561018f57600080fd5b83356001600160a01b03811681146101a657600080fd5b9250602084013567ffffffffffffffff808211156101c357600080fd5b818601915086601f8301126101d757600080fd5b8135818111156101e657600080fd5b8760208285010111156101f857600080fd5b6020830194508093505050509250925092565b60006001820161022b57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea2646970667358221220d2d546f135265c71683c4923890de2d8ae66f3be17185690036424019a5309ae64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806316f198311461004657806361bc221a1461005b578063a6f9885c14610076575b600080fd5b61005961005436600461017a565b61007f565b005b61006460005481565b60405190815260200160405180910390f35b61006461080081565b6001600160a01b0383166100cd5760405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b60448201526064015b60405180910390fd5b6108008111156101145760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b60448201526064016100c4565b826001600160a01b0316336001600160a01b031660008081546101369061020b565b9190508190557fedaf3c471ebd67d60c29efe34b639ede7d6a1d92eaeb3f503e784971e67118a5858560405161016d929190610232565b60405180910390a4505050565b60008060006040848603121561018f57600080fd5b83356001600160a01b03811681146101a657600080fd5b9250602084013567ffffffffffffffff808211156101c357600080fd5b818601915086601f8301126101d757600080fd5b8135818111156101e657600080fd5b8760208285010111156101f857600080fd5b6020830194508093505050509250925092565b60006001820161022b57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea2646970667358221220d2d546f135265c71683c4923890de2d8ae66f3be17185690036424019a5309ae64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var StateReceiverArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"StateReceiver\",\n \"sourceName\": \"contracts/child/StateReceiver.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"startId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"endId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes32\",\n \"name\": \"root\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"NewCommitment\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"counter\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"message\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"StateSyncResult\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32[][]\",\n \"name\": \"proofs\",\n \"type\": \"bytes32[][]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"internalType\": \"struct StateReceiver.StateSync[]\",\n \"name\": \"objs\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"batchExecute\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"root\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct StateReceiver.StateSyncCommitment\",\n \"name\": \"commitment\",\n \"type\": \"tuple\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"signature\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"bitmap\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"commit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"commitmentCounter\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"commitmentIds\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"commitments\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"root\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"internalType\": \"struct StateReceiver.StateSync\",\n \"name\": \"obj\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"execute\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getCommitmentByStateSyncId\",\n \"outputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"root\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct StateReceiver.StateSyncCommitment\",\n \"name\": \"\",\n \"type\": \"tuple\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getRootByStateSyncId\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"lastCommittedId\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"processedStateSyncs\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611428806100206000396000f3fe608060405234801561001057600080fd5b50600436106100e05760003560e01c80639017c127116100875780639017c127146101de578063947287cf146101f157806397e5230d146101fa578063ad240c2a14610204578063c59a18f71461020d578063c6df461714610220578063e0563ab114610233578063eb70ef441461023c57600080fd5b8063196f1b2d146100e557806323e281cf1461010b578063284017f5146101145780633b878c221461013557806349ce89971461013e57806350d5b95b1461018857806351351d531461019d578063544c5e0f146101ab575b600080fd5b6100f86100f3366004610e88565b610271565b6040519081526020015b60405180910390f35b6100f860325481565b61011d61202081565b6040516001600160a01b039091168152602001610102565b61011d61101081565b61016d61014c366004610e88565b60356020526000908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610102565b61019b610196366004610eec565b6102f0565b005b61011d6002600160a01b0381565b6101ce6101b9366004610e88565b60346020526000908152604090205460ff1681565b6040519015158152602001610102565b61019b6101ec366004610f5b565b6103b7565b6100f861520881565b6100f8620249f081565b6100f860335481565b6100f861021b366004610e88565b610557565b61019b61022e366004611007565b610578565b61011d61203081565b61024f61024a366004610e88565b61075c565b6040805182518152602080840151908201529181015190820152606001610102565b60008060358161028260368661081f565b81526020810191909152604001600020600201549050806102ea5760405162461bcd60e51b815260206004820152601d60248201527f537461746552656365697665723a204e4f5f524f4f545f464f525f494400000060448201526064015b60405180910390fd5b92915050565b60006102fc823561075c565b805190915061036c906103109084356110a5565b8251602084015161032191906110a5565b61032c9060016110b8565b83604001518787876040516020016103449190611110565b604051602081830303815290604052805190602001206108cc9095949392919063ffffffff16565b6103a85760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa82927a7a360991b60448201526064016102e1565b6103b182610a68565b50505050565b8281811461041a5760405162461bcd60e51b815260206004820152602a60248201527f537461746552656365697665723a20554e4d4154434845445f4c454e4754485f604482015269504152414d455445525360b01b60648201526084016102e1565b60005b8181101561054f57600061045485858481811061043c5761043c6111ac565b905060200281019061044e91906111c2565b3561075c565b905060006105088260000151878786818110610472576104726111ac565b905060200281019061048491906111c2565b61048f9190356110a5565b835160208501516104a091906110a5565b6104ab9060016110b8565b84604001518b8b888181106104c2576104c26111ac565b90506020028101906104d491906111e2565b8b8b8a8181106104e6576104e66111ac565b90506020028101906104f891906111c2565b6040516020016103449190611110565b90508061051957505060010161041d565b61054586868581811061052e5761052e6111ac565b905060200281019061054091906111c2565b610a68565b505060010161041d565b505050505050565b6036818154811061056757600080fd5b600091825260209091200154905081565b336002600160a01b03146105bc5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064016102e1565b6033546105ca9060016110b8565b85351461060c5760405162461bcd60e51b815260206004820152601060248201526f1253959053125117d4d510549517d25160821b60448201526064016102e1565b8435602086013510156106525760405162461bcd60e51b815260206004820152600e60248201526d1253959053125117d1539117d25160921b60448201526064016102e1565b60408051863560208083019190915287013581830152908601356060820152610697906080016040516020818303038152906040528051906020012085858585610c83565b603280548691603591600091826106ad8361122b565b90915550815260208082019290925260409081016000208335815591830135600183015582013560028201555050603680546001810182556000919091526020868101357f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b89092018290556033829055604080519088013581528735917f11efd893530b26afc66d488ff54cb15df117cb6e0e4a08c6dcb166d766c3bf3b910160405180910390a35050505050565b604080516060810182526000808252602082018190529181018290529061078460368461081f565b60365490915081036107e45760405162461bcd60e51b815260206004820152602360248201527f537461746552656365697665723a204e4f5f434f4d4d49544d454e545f464f5260448201526217d25160ea1b60648201526084016102e1565b600090815260356020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915292915050565b81546000908103610832575060006102ea565b82546000905b8082101561087f57600061084c8383610d87565b6000878152602090209091508590820154111561086b57809150610879565b6108768160016110b8565b92505b50610838565b6000821180156108ab5750836108a88661089a6001866110a5565b600091825260209091200190565b54145b156108c4576108bb6001836110a5565b925050506102ea565b509392505050565b6000816108da866001610da9565b811461091f5760405162461bcd60e51b81526020600482015260146024820152730929cac82989288bea0a49e9e8cbe988a9c8ea8960631b60448201526064016102e1565b8587106109635760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b60448201526064016102e1565b8761099f5760405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa622a0a360a11b60448201526064016102e1565b8760005b82811015610a595760008686838181106109bf576109bf6111ac565b90506020020135905060028a6109d5919061125a565b600003610a0d576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a3a565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b610a4560028b61126e565b99505080610a529061122b565b90506109a3565b50909414979650505050505050565b803560009081526034602052604090205460ff1615610ad85760405162461bcd60e51b815260206004820152602660248201527f537461746552656365697665723a2053544154455f53594e435f49535f50524f60448201526510d154d4d15160d21b60648201526084016102e1565b610ae86060820160408301611282565b6001600160a01b03163b600003610b3c576040805160208082526000908201819052918335917f31c652130602f3ce96ceaf8a4c2b8b49f049166c6fcf2eb31943a75ec7c936ae910160405180910390a350565b8035600090815260346020526040808220805460ff191660011790558190610b6a9060608501908501611282565b6001600160a01b03168335610b856040860160208701611282565b610b92606087018761129d565b604051602401610ba594939291906112e3565b60408051601f198184030181529181526020820180516001600160e01b031663eeb4994560e01b17905251610bda919061133c565b6000604051808303816000865af19150503d8060008114610c17576040519150601f19603f3d011682016040523d82523d6000602084013e610c1c565b606091505b509150915081610c3f5782356000908152603460205260409020805460ff191690555b81151583600001357f31c652130602f3ce96ceaf8a4c2b8b49f049166c6fcf2eb31943a75ec7c936ae83604051610c76919061134e565b60405180910390a3505050565b6000806120306001600160a01b0316620249f08888888888604051602001610caf959493929190611381565b60408051601f1981840301815290829052610cc99161133c565b6000604051808303818686fa925050503d8060008114610d05576040519150601f19603f3d011682016040523d82523d6000602084013e610d0a565b606091505b5091509150600081806020019051810190610d2591906113ba565b9050828015610d315750805b610d7d5760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c454400000060448201526064016102e1565b5050505050505050565b6000610d96600284841861126e565b610da2908484166110b8565b9392505050565b600080610db584610df4565b90506001836002811115610dcb57610dcb6113dc565b148015610ddb575083816001901b105b610de6576000610de9565b60015b60ff16019392505050565b600080608083901c15610e0957608092831c92015b604083901c15610e1b57604092831c92015b602083901c15610e2d57602092831c92015b601083901c15610e3f57601092831c92015b600883901c15610e5157600892831c92015b600483901c15610e6357600492831c92015b600283901c15610e7557600292831c92015b600183901c156102ea5760010192915050565b600060208284031215610e9a57600080fd5b5035919050565b60008083601f840112610eb357600080fd5b5081356001600160401b03811115610eca57600080fd5b6020830191508360208260051b8501011115610ee557600080fd5b9250929050565b600080600060408486031215610f0157600080fd5b83356001600160401b0380821115610f1857600080fd5b610f2487838801610ea1565b90955093506020860135915080821115610f3d57600080fd5b50840160808187031215610f5057600080fd5b809150509250925092565b60008060008060408587031215610f7157600080fd5b84356001600160401b0380821115610f8857600080fd5b610f9488838901610ea1565b90965094506020870135915080821115610fad57600080fd5b50610fba87828801610ea1565b95989497509550505050565b60008083601f840112610fd857600080fd5b5081356001600160401b03811115610fef57600080fd5b602083019150836020828501011115610ee557600080fd5b600080600080600085870360a081121561102057600080fd5b606081121561102e57600080fd5b5085945060608601356001600160401b038082111561104c57600080fd5b61105889838a01610fc6565b9096509450608088013591508082111561107157600080fd5b5061107e88828901610fc6565b969995985093965092949392505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156102ea576102ea61108f565b808201808211156102ea576102ea61108f565b80356001600160a01b03811681146110e257600080fd5b919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152813560208201526000611129602084016110cb565b60018060a01b03808216604085015280611145604087016110cb565b16606085015250506060830135601e1984360301811261116457600080fd5b83016020810190356001600160401b0381111561118057600080fd5b80360382131561118f57600080fd5b6080808501526111a360a0850182846110e7565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60008235607e198336030181126111d857600080fd5b9190910192915050565b6000808335601e198436030181126111f957600080fd5b8301803591506001600160401b0382111561121357600080fd5b6020019150600581901b3603821315610ee557600080fd5b60006001820161123d5761123d61108f565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261126957611269611244565b500690565b60008261127d5761127d611244565b500490565b60006020828403121561129457600080fd5b610da2826110cb565b6000808335601e198436030181126112b457600080fd5b8301803591506001600160401b038211156112ce57600080fd5b602001915036819003821315610ee557600080fd5b8481526001600160a01b038416602082015260606040820181905260009061130e90830184866110e7565b9695505050505050565b60005b8381101561133357818101518382015260200161131b565b50506000910152565b600082516111d8818460208701611318565b602081526000825180602084015261136d816040850160208701611318565b601f01601f19169190910160400192915050565b85815260606020820152600061139b6060830186886110e7565b82810360408401526113ae8185876110e7565b98975050505050505050565b6000602082840312156113cc57600080fd5b81518015158114610da257600080fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220f12de4c572934572c3dae6184bcfe87730e8a0938ba1504547710fd27554218264736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100e05760003560e01c80639017c127116100875780639017c127146101de578063947287cf146101f157806397e5230d146101fa578063ad240c2a14610204578063c59a18f71461020d578063c6df461714610220578063e0563ab114610233578063eb70ef441461023c57600080fd5b8063196f1b2d146100e557806323e281cf1461010b578063284017f5146101145780633b878c221461013557806349ce89971461013e57806350d5b95b1461018857806351351d531461019d578063544c5e0f146101ab575b600080fd5b6100f86100f3366004610e88565b610271565b6040519081526020015b60405180910390f35b6100f860325481565b61011d61202081565b6040516001600160a01b039091168152602001610102565b61011d61101081565b61016d61014c366004610e88565b60356020526000908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610102565b61019b610196366004610eec565b6102f0565b005b61011d6002600160a01b0381565b6101ce6101b9366004610e88565b60346020526000908152604090205460ff1681565b6040519015158152602001610102565b61019b6101ec366004610f5b565b6103b7565b6100f861520881565b6100f8620249f081565b6100f860335481565b6100f861021b366004610e88565b610557565b61019b61022e366004611007565b610578565b61011d61203081565b61024f61024a366004610e88565b61075c565b6040805182518152602080840151908201529181015190820152606001610102565b60008060358161028260368661081f565b81526020810191909152604001600020600201549050806102ea5760405162461bcd60e51b815260206004820152601d60248201527f537461746552656365697665723a204e4f5f524f4f545f464f525f494400000060448201526064015b60405180910390fd5b92915050565b60006102fc823561075c565b805190915061036c906103109084356110a5565b8251602084015161032191906110a5565b61032c9060016110b8565b83604001518787876040516020016103449190611110565b604051602081830303815290604052805190602001206108cc9095949392919063ffffffff16565b6103a85760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa82927a7a360991b60448201526064016102e1565b6103b182610a68565b50505050565b8281811461041a5760405162461bcd60e51b815260206004820152602a60248201527f537461746552656365697665723a20554e4d4154434845445f4c454e4754485f604482015269504152414d455445525360b01b60648201526084016102e1565b60005b8181101561054f57600061045485858481811061043c5761043c6111ac565b905060200281019061044e91906111c2565b3561075c565b905060006105088260000151878786818110610472576104726111ac565b905060200281019061048491906111c2565b61048f9190356110a5565b835160208501516104a091906110a5565b6104ab9060016110b8565b84604001518b8b888181106104c2576104c26111ac565b90506020028101906104d491906111e2565b8b8b8a8181106104e6576104e66111ac565b90506020028101906104f891906111c2565b6040516020016103449190611110565b90508061051957505060010161041d565b61054586868581811061052e5761052e6111ac565b905060200281019061054091906111c2565b610a68565b505060010161041d565b505050505050565b6036818154811061056757600080fd5b600091825260209091200154905081565b336002600160a01b03146105bc5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064016102e1565b6033546105ca9060016110b8565b85351461060c5760405162461bcd60e51b815260206004820152601060248201526f1253959053125117d4d510549517d25160821b60448201526064016102e1565b8435602086013510156106525760405162461bcd60e51b815260206004820152600e60248201526d1253959053125117d1539117d25160921b60448201526064016102e1565b60408051863560208083019190915287013581830152908601356060820152610697906080016040516020818303038152906040528051906020012085858585610c83565b603280548691603591600091826106ad8361122b565b90915550815260208082019290925260409081016000208335815591830135600183015582013560028201555050603680546001810182556000919091526020868101357f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b89092018290556033829055604080519088013581528735917f11efd893530b26afc66d488ff54cb15df117cb6e0e4a08c6dcb166d766c3bf3b910160405180910390a35050505050565b604080516060810182526000808252602082018190529181018290529061078460368461081f565b60365490915081036107e45760405162461bcd60e51b815260206004820152602360248201527f537461746552656365697665723a204e4f5f434f4d4d49544d454e545f464f5260448201526217d25160ea1b60648201526084016102e1565b600090815260356020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915292915050565b81546000908103610832575060006102ea565b82546000905b8082101561087f57600061084c8383610d87565b6000878152602090209091508590820154111561086b57809150610879565b6108768160016110b8565b92505b50610838565b6000821180156108ab5750836108a88661089a6001866110a5565b600091825260209091200190565b54145b156108c4576108bb6001836110a5565b925050506102ea565b509392505050565b6000816108da866001610da9565b811461091f5760405162461bcd60e51b81526020600482015260146024820152730929cac82989288bea0a49e9e8cbe988a9c8ea8960631b60448201526064016102e1565b8587106109635760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b60448201526064016102e1565b8761099f5760405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa622a0a360a11b60448201526064016102e1565b8760005b82811015610a595760008686838181106109bf576109bf6111ac565b90506020020135905060028a6109d5919061125a565b600003610a0d576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a3a565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b610a4560028b61126e565b99505080610a529061122b565b90506109a3565b50909414979650505050505050565b803560009081526034602052604090205460ff1615610ad85760405162461bcd60e51b815260206004820152602660248201527f537461746552656365697665723a2053544154455f53594e435f49535f50524f60448201526510d154d4d15160d21b60648201526084016102e1565b610ae86060820160408301611282565b6001600160a01b03163b600003610b3c576040805160208082526000908201819052918335917f31c652130602f3ce96ceaf8a4c2b8b49f049166c6fcf2eb31943a75ec7c936ae910160405180910390a350565b8035600090815260346020526040808220805460ff191660011790558190610b6a9060608501908501611282565b6001600160a01b03168335610b856040860160208701611282565b610b92606087018761129d565b604051602401610ba594939291906112e3565b60408051601f198184030181529181526020820180516001600160e01b031663eeb4994560e01b17905251610bda919061133c565b6000604051808303816000865af19150503d8060008114610c17576040519150601f19603f3d011682016040523d82523d6000602084013e610c1c565b606091505b509150915081610c3f5782356000908152603460205260409020805460ff191690555b81151583600001357f31c652130602f3ce96ceaf8a4c2b8b49f049166c6fcf2eb31943a75ec7c936ae83604051610c76919061134e565b60405180910390a3505050565b6000806120306001600160a01b0316620249f08888888888604051602001610caf959493929190611381565b60408051601f1981840301815290829052610cc99161133c565b6000604051808303818686fa925050503d8060008114610d05576040519150601f19603f3d011682016040523d82523d6000602084013e610d0a565b606091505b5091509150600081806020019051810190610d2591906113ba565b9050828015610d315750805b610d7d5760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c454400000060448201526064016102e1565b5050505050505050565b6000610d96600284841861126e565b610da2908484166110b8565b9392505050565b600080610db584610df4565b90506001836002811115610dcb57610dcb6113dc565b148015610ddb575083816001901b105b610de6576000610de9565b60015b60ff16019392505050565b600080608083901c15610e0957608092831c92015b604083901c15610e1b57604092831c92015b602083901c15610e2d57602092831c92015b601083901c15610e3f57601092831c92015b600883901c15610e5157600892831c92015b600483901c15610e6357600492831c92015b600283901c15610e7557600292831c92015b600183901c156102ea5760010192915050565b600060208284031215610e9a57600080fd5b5035919050565b60008083601f840112610eb357600080fd5b5081356001600160401b03811115610eca57600080fd5b6020830191508360208260051b8501011115610ee557600080fd5b9250929050565b600080600060408486031215610f0157600080fd5b83356001600160401b0380821115610f1857600080fd5b610f2487838801610ea1565b90955093506020860135915080821115610f3d57600080fd5b50840160808187031215610f5057600080fd5b809150509250925092565b60008060008060408587031215610f7157600080fd5b84356001600160401b0380821115610f8857600080fd5b610f9488838901610ea1565b90965094506020870135915080821115610fad57600080fd5b50610fba87828801610ea1565b95989497509550505050565b60008083601f840112610fd857600080fd5b5081356001600160401b03811115610fef57600080fd5b602083019150836020828501011115610ee557600080fd5b600080600080600085870360a081121561102057600080fd5b606081121561102e57600080fd5b5085945060608601356001600160401b038082111561104c57600080fd5b61105889838a01610fc6565b9096509450608088013591508082111561107157600080fd5b5061107e88828901610fc6565b969995985093965092949392505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156102ea576102ea61108f565b808201808211156102ea576102ea61108f565b80356001600160a01b03811681146110e257600080fd5b919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152813560208201526000611129602084016110cb565b60018060a01b03808216604085015280611145604087016110cb565b16606085015250506060830135601e1984360301811261116457600080fd5b83016020810190356001600160401b0381111561118057600080fd5b80360382131561118f57600080fd5b6080808501526111a360a0850182846110e7565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60008235607e198336030181126111d857600080fd5b9190910192915050565b6000808335601e198436030181126111f957600080fd5b8301803591506001600160401b0382111561121357600080fd5b6020019150600581901b3603821315610ee557600080fd5b60006001820161123d5761123d61108f565b5060010190565b634e487b7160e01b600052601260045260246000fd5b60008261126957611269611244565b500690565b60008261127d5761127d611244565b500490565b60006020828403121561129457600080fd5b610da2826110cb565b6000808335601e198436030181126112b457600080fd5b8301803591506001600160401b038211156112ce57600080fd5b602001915036819003821315610ee557600080fd5b8481526001600160a01b038416602082015260606040820181905260009061130e90830184866110e7565b9695505050505050565b60005b8381101561133357818101518382015260200161131b565b50506000910152565b600082516111d8818460208701611318565b602081526000825180602084015261136d816040850160208701611318565b601f01601f19169190910160400192915050565b85815260606020820152600061139b6060830186886110e7565b82810360408401526113ae8185876110e7565b98975050505050505050565b6000602082840312156113cc57600080fd5b81518015158114610da257600080fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220f12de4c572934572c3dae6184bcfe87730e8a0938ba1504547710fd27554218264736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var NativeERC20Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"NativeERC20\",\n \"sourceName\": \"contracts/child/NativeERC20.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"predicate_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"rootToken_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"name_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"symbol_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"decimals_\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506111c3806100206000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806370a08231116100b85780639dc29fac1161007c5780639dc29fac14610278578063a457c2d71461028b578063a9059cbb1461029e578063dd62ed3e146102b1578063e0563ab1146102c4578063e6198705146102cd57600080fd5b806370a082311461022d5780638420ce9914610248578063947287cf1461025d57806395d89b411461026657806397e5230d1461026e57600080fd5b8063284017f51161010a578063284017f5146101d2578063313ce567146101db57806339509351146101f05780633b878c221461020357806340c10f191461020c57806351351d531461021f57600080fd5b806306fdde0314610147578063095ea7b31461016557806318160ddd146101885780631f2d00651461019a57806323b872dd146101bf575b600080fd5b61014f6102de565b60405161015c9190610cfd565b60405180910390f35b610178610173366004610d4c565b610370565b604051901515815260200161015c565b6034545b60405190815260200161015c565b6036546001600160a01b03165b6040516001600160a01b03909116815260200161015c565b6101786101cd366004610d76565b61038a565b6101a761202081565b60395460405160ff909116815260200161015c565b6101786101fe366004610d4c565b6103ae565b6101a761101081565b61017861021a366004610d4c565b6103d0565b6101a76002600160a01b0381565b61018c61023b366004610db2565b6001600160a01b03163190565b61025b610256366004610e1d565b610419565b005b61018c61520881565b61014f6105c8565b61018c620249f081565b610178610286366004610d4c565b6105d7565b610178610299366004610d4c565b61060e565b6101786102ac366004610d4c565b610689565b61018c6102bf366004610ec8565b610697565b6101a761203081565b6035546001600160a01b03166101a7565b6060603780546102ed90610efb565b80601f016020809104026020016040519081016040528092919081815260200182805461031990610efb565b80156103665780601f1061033b57610100808354040283529160200191610366565b820191906000526020600020905b81548152906001019060200180831161034957829003601f168201915b5050505050905090565b60003361037e8185856106c2565b60019150505b92915050565b6000336103988582856107e6565b6103a3858585610860565b506001949350505050565b60003361037e8185856103c18383610697565b6103cb9190610f4b565b6106c2565b6035546000906001600160a01b031633146104065760405162461bcd60e51b81526004016103fd90610f5e565b60405180910390fd5b6104108383610a25565b50600192915050565b600054610100900460ff16158080156104395750600054600160ff909116105b806104535750303b158015610453575060005460ff166001145b6104b65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103fd565b6000805460ff1916600117905580156104d9576000805461ff0019166101001790555b336002600160a01b031461051d5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064016103fd565b603580546001600160a01b03808b166001600160a01b03199283161790925560368054928a1692909116919091179055603761055a868883611007565b506038610568848683611007565b506039805460ff191660ff841617905580156105be576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6060603880546102ed90610efb565b6035546000906001600160a01b031633146106045760405162461bcd60e51b81526004016103fd90610f5e565b6104108383610b7f565b6000338161061c8286610697565b90508381101561067c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016103fd565b6103a382868684036106c2565b60003361037e818585610860565b6001600160a01b03918216600090815260336020908152604080832093909416825291909152205490565b6001600160a01b0383166107245760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103fd565b6001600160a01b0382166107855760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103fd565b6001600160a01b0383811660008181526033602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006107f28484610697565b9050600019811461085a578181101561084d5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103fd565b61085a84848484036106c2565b50505050565b6001600160a01b0383166108c45760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103fd565b6001600160a01b0382166109265760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103fd565b6000806120206001600160a01b031685858560405160200161094a939291906110c8565b60408051601f1981840301815290829052610964916110ec565b6000604051808303816000865af19150503d80600081146109a1576040519150601f19603f3d011682016040523d82523d6000602084013e6109a6565b606091505b50915091508180156109c75750808060200190518101906109c79190611108565b6109e35760405162461bcd60e51b81526004016103fd9061112a565b836001600160a01b0316856001600160a01b031660008051602061116e83398151915285604051610a1691815260200190565b60405180910390a35050505050565b6001600160a01b038216610a7b5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016103fd565b8060346000828254610a8d9190610f4b565b9091555050604051600090819061202090610ab0908390879087906020016110c8565b60408051601f1981840301815290829052610aca916110ec565b6000604051808303816000865af19150503d8060008114610b07576040519150601f19603f3d011682016040523d82523d6000602084013e610b0c565b606091505b5091509150818015610b2d575080806020019051810190610b2d9190611108565b610b495760405162461bcd60e51b81526004016103fd9061112a565b6040518381526001600160a01b0385169060009060008051602061116e833981519152906020015b60405180910390a350505050565b6001600160a01b038216610bdf5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016103fd565b8060346000828254610bf1919061115a565b9091555050604051600090819061202090610c14908690849087906020016110c8565b60408051601f1981840301815290829052610c2e916110ec565b6000604051808303816000865af19150503d8060008114610c6b576040519150601f19603f3d011682016040523d82523d6000602084013e610c70565b606091505b5091509150818015610c91575080806020019051810190610c919190611108565b610cad5760405162461bcd60e51b81526004016103fd9061112a565b6040518381526000906001600160a01b0386169060008051602061116e83398151915290602001610b71565b60005b83811015610cf4578181015183820152602001610cdc565b50506000910152565b6020815260008251806020840152610d1c816040850160208701610cd9565b601f01601f19169190910160400192915050565b80356001600160a01b0381168114610d4757600080fd5b919050565b60008060408385031215610d5f57600080fd5b610d6883610d30565b946020939093013593505050565b600080600060608486031215610d8b57600080fd5b610d9484610d30565b9250610da260208501610d30565b9150604084013590509250925092565b600060208284031215610dc457600080fd5b610dcd82610d30565b9392505050565b60008083601f840112610de657600080fd5b50813567ffffffffffffffff811115610dfe57600080fd5b602083019150836020828501011115610e1657600080fd5b9250929050565b600080600080600080600060a0888a031215610e3857600080fd5b610e4188610d30565b9650610e4f60208901610d30565b9550604088013567ffffffffffffffff80821115610e6c57600080fd5b610e788b838c01610dd4565b909750955060608a0135915080821115610e9157600080fd5b50610e9e8a828b01610dd4565b909450925050608088013560ff81168114610eb857600080fd5b8091505092959891949750929550565b60008060408385031215610edb57600080fd5b610ee483610d30565b9150610ef260208401610d30565b90509250929050565b600181811c90821680610f0f57607f821691505b602082108103610f2f57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561038457610384610f35565b60208082526024908201527f4e617469766545524332303a204f6e6c79207072656469636174652063616e2060408201526318d85b1b60e21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561100257600081815260208120601f850160051c81016020861015610fdf5750805b601f850160051c820191505b81811015610ffe57828155600101610feb565b5050505b505050565b67ffffffffffffffff83111561101f5761101f610fa2565b6110338361102d8354610efb565b83610fb8565b6000601f841160018114611067576000851561104f5750838201355b600019600387901b1c1916600186901b1783556110c1565b600083815260209020601f19861690835b828110156110985786850135825560209485019460019092019101611078565b50868210156110b55760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600082516110fe818460208701610cd9565b9190910192915050565b60006020828403121561111a57600080fd5b81518015158114610dcd57600080fd5b60208082526016908201527514149150d3d35412531157d0d0531317d1905253115160521b604082015260600190565b8181038181111561038457610384610f3556feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212201cc2b3ea246b46198f0ff59b53d69a9ac96c47a287d6ed78414118383506ad4264736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101425760003560e01c806370a08231116100b85780639dc29fac1161007c5780639dc29fac14610278578063a457c2d71461028b578063a9059cbb1461029e578063dd62ed3e146102b1578063e0563ab1146102c4578063e6198705146102cd57600080fd5b806370a082311461022d5780638420ce9914610248578063947287cf1461025d57806395d89b411461026657806397e5230d1461026e57600080fd5b8063284017f51161010a578063284017f5146101d2578063313ce567146101db57806339509351146101f05780633b878c221461020357806340c10f191461020c57806351351d531461021f57600080fd5b806306fdde0314610147578063095ea7b31461016557806318160ddd146101885780631f2d00651461019a57806323b872dd146101bf575b600080fd5b61014f6102de565b60405161015c9190610cfd565b60405180910390f35b610178610173366004610d4c565b610370565b604051901515815260200161015c565b6034545b60405190815260200161015c565b6036546001600160a01b03165b6040516001600160a01b03909116815260200161015c565b6101786101cd366004610d76565b61038a565b6101a761202081565b60395460405160ff909116815260200161015c565b6101786101fe366004610d4c565b6103ae565b6101a761101081565b61017861021a366004610d4c565b6103d0565b6101a76002600160a01b0381565b61018c61023b366004610db2565b6001600160a01b03163190565b61025b610256366004610e1d565b610419565b005b61018c61520881565b61014f6105c8565b61018c620249f081565b610178610286366004610d4c565b6105d7565b610178610299366004610d4c565b61060e565b6101786102ac366004610d4c565b610689565b61018c6102bf366004610ec8565b610697565b6101a761203081565b6035546001600160a01b03166101a7565b6060603780546102ed90610efb565b80601f016020809104026020016040519081016040528092919081815260200182805461031990610efb565b80156103665780601f1061033b57610100808354040283529160200191610366565b820191906000526020600020905b81548152906001019060200180831161034957829003601f168201915b5050505050905090565b60003361037e8185856106c2565b60019150505b92915050565b6000336103988582856107e6565b6103a3858585610860565b506001949350505050565b60003361037e8185856103c18383610697565b6103cb9190610f4b565b6106c2565b6035546000906001600160a01b031633146104065760405162461bcd60e51b81526004016103fd90610f5e565b60405180910390fd5b6104108383610a25565b50600192915050565b600054610100900460ff16158080156104395750600054600160ff909116105b806104535750303b158015610453575060005460ff166001145b6104b65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103fd565b6000805460ff1916600117905580156104d9576000805461ff0019166101001790555b336002600160a01b031461051d5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064016103fd565b603580546001600160a01b03808b166001600160a01b03199283161790925560368054928a1692909116919091179055603761055a868883611007565b506038610568848683611007565b506039805460ff191660ff841617905580156105be576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b6060603880546102ed90610efb565b6035546000906001600160a01b031633146106045760405162461bcd60e51b81526004016103fd90610f5e565b6104108383610b7f565b6000338161061c8286610697565b90508381101561067c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016103fd565b6103a382868684036106c2565b60003361037e818585610860565b6001600160a01b03918216600090815260336020908152604080832093909416825291909152205490565b6001600160a01b0383166107245760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016103fd565b6001600160a01b0382166107855760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016103fd565b6001600160a01b0383811660008181526033602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006107f28484610697565b9050600019811461085a578181101561084d5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016103fd565b61085a84848484036106c2565b50505050565b6001600160a01b0383166108c45760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016103fd565b6001600160a01b0382166109265760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016103fd565b6000806120206001600160a01b031685858560405160200161094a939291906110c8565b60408051601f1981840301815290829052610964916110ec565b6000604051808303816000865af19150503d80600081146109a1576040519150601f19603f3d011682016040523d82523d6000602084013e6109a6565b606091505b50915091508180156109c75750808060200190518101906109c79190611108565b6109e35760405162461bcd60e51b81526004016103fd9061112a565b836001600160a01b0316856001600160a01b031660008051602061116e83398151915285604051610a1691815260200190565b60405180910390a35050505050565b6001600160a01b038216610a7b5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016103fd565b8060346000828254610a8d9190610f4b565b9091555050604051600090819061202090610ab0908390879087906020016110c8565b60408051601f1981840301815290829052610aca916110ec565b6000604051808303816000865af19150503d8060008114610b07576040519150601f19603f3d011682016040523d82523d6000602084013e610b0c565b606091505b5091509150818015610b2d575080806020019051810190610b2d9190611108565b610b495760405162461bcd60e51b81526004016103fd9061112a565b6040518381526001600160a01b0385169060009060008051602061116e833981519152906020015b60405180910390a350505050565b6001600160a01b038216610bdf5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016103fd565b8060346000828254610bf1919061115a565b9091555050604051600090819061202090610c14908690849087906020016110c8565b60408051601f1981840301815290829052610c2e916110ec565b6000604051808303816000865af19150503d8060008114610c6b576040519150601f19603f3d011682016040523d82523d6000602084013e610c70565b606091505b5091509150818015610c91575080806020019051810190610c919190611108565b610cad5760405162461bcd60e51b81526004016103fd9061112a565b6040518381526000906001600160a01b0386169060008051602061116e83398151915290602001610b71565b60005b83811015610cf4578181015183820152602001610cdc565b50506000910152565b6020815260008251806020840152610d1c816040850160208701610cd9565b601f01601f19169190910160400192915050565b80356001600160a01b0381168114610d4757600080fd5b919050565b60008060408385031215610d5f57600080fd5b610d6883610d30565b946020939093013593505050565b600080600060608486031215610d8b57600080fd5b610d9484610d30565b9250610da260208501610d30565b9150604084013590509250925092565b600060208284031215610dc457600080fd5b610dcd82610d30565b9392505050565b60008083601f840112610de657600080fd5b50813567ffffffffffffffff811115610dfe57600080fd5b602083019150836020828501011115610e1657600080fd5b9250929050565b600080600080600080600060a0888a031215610e3857600080fd5b610e4188610d30565b9650610e4f60208901610d30565b9550604088013567ffffffffffffffff80821115610e6c57600080fd5b610e788b838c01610dd4565b909750955060608a0135915080821115610e9157600080fd5b50610e9e8a828b01610dd4565b909450925050608088013560ff81168114610eb857600080fd5b8091505092959891949750929550565b60008060408385031215610edb57600080fd5b610ee483610d30565b9150610ef260208401610d30565b90509250929050565b600181811c90821680610f0f57607f821691505b602082108103610f2f57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561038457610384610f35565b60208082526024908201527f4e617469766545524332303a204f6e6c79207072656469636174652063616e2060408201526318d85b1b60e21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561100257600081815260208120601f850160051c81016020861015610fdf5750805b601f850160051c820191505b81811015610ffe57828155600101610feb565b5050505b505050565b67ffffffffffffffff83111561101f5761101f610fa2565b6110338361102d8354610efb565b83610fb8565b6000601f841160018114611067576000851561104f5750838201355b600019600387901b1c1916600186901b1783556110c1565b600083815260209020601f19861690835b828110156110985786850135825560209485019460019092019101611078565b50868210156110b55760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600082516110fe818460208701610cd9565b9190910192915050565b60006020828403121561111a57600080fd5b81518015158114610dcd57600080fd5b60208082526016908201527514149150d3d35412531157d0d0531317d1905253115160521b604082015260600190565b8181038181111561038457610384610f3556feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212201cc2b3ea246b46198f0ff59b53d69a9ac96c47a287d6ed78414118383506ad4264736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var NativeERC20MintableArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"NativeERC20Mintable\",\n \"sourceName\": \"contracts/child/NativeERC20Mintable.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"predicate_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"owner_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"rootToken_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"name_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"symbol_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"decimals_\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b5061001a3361001f565b610098565b603480546001600160a01b031916905561004381610046602090811b6108ce17901c565b50565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6114ad806100a76000396000f3fe608060405234801561001057600080fd5b50600436106101795760003560e01c8063715018a6116100d9578063a457c2d711610087578063a457c2d7146102e3578063a9059cbb146102f6578063dd62ed3e14610309578063e0563ab11461031c578063e30c397814610325578063e619870514610336578063f2fde38b1461034757600080fd5b8063715018a61461029457806379ba50971461029c5780638da5cb5b146102a4578063947287cf146102b557806395d89b41146102be57806397e5230d146102c65780639dc29fac146102d057600080fd5b8063284017f511610136578063284017f51461021e578063313ce56714610227578063395093511461023c5780633b878c221461024f57806340c10f191461025857806351351d531461026b57806370a082311461027957600080fd5b806306fdde031461017e578063095ea7b31461019c57806318160ddd146101bf5780631f2d0065146101d1578063238b4bc5146101f657806323b872dd1461020b575b600080fd5b61018661035a565b6040516101939190610fce565b60405180910390f35b6101af6101aa36600461101d565b6103ec565b6040519015158152602001610193565b6036545b604051908152602001610193565b6038546001600160a01b03165b6040516001600160a01b039091168152602001610193565b610209610204366004611090565b610406565b005b6101af61021936600461114b565b610625565b6101de61202081565b603b5460405160ff9091168152602001610193565b6101af61024a36600461101d565b610649565b6101de61101081565b6101af61026636600461101d565b61066b565b6101de6002600160a01b0381565b6101c3610287366004611187565b6001600160a01b03163190565b6102096106c0565b6102096106d4565b6033546001600160a01b03166101de565b6101c361520881565b61018661074e565b6101c3620249f081565b6101af6102de36600461101d565b61075d565b6101af6102f136600461101d565b6107a9565b6101af61030436600461101d565b610824565b6101c36103173660046111a9565b610832565b6101de61203081565b6034546001600160a01b03166101de565b6037546001600160a01b03166101de565b610209610355366004611187565b61085d565b606060398054610369906111dc565b80601f0160208091040260200160405190810160405280929190818152602001828054610395906111dc565b80156103e25780601f106103b7576101008083540402835291602001916103e2565b820191906000526020600020905b8154815290600101906020018083116103c557829003601f168201915b5050505050905090565b6000336103fa818585610920565b60019150505b92915050565b600054610100900460ff16158080156104265750600054600160ff909116105b806104405750303b158015610440575060005460ff166001145b6104a85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156104cb576000805461ff0019166101001790555b336002600160a01b031461050f5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b604482015260640161049f565b6001600160a01b0388166105705760405162461bcd60e51b815260206004820152602260248201527f4e617469766545524332303a20496e76616c6964206f776e6572206164647265604482015261737360f01b606482015260840161049f565b603780546001600160a01b03808c166001600160a01b03199283161790925560388054928a169290911691909117905560396105ad86888361127b565b50603a6105bb84868361127b565b50603b805460ff191660ff84161790556105d488610a44565b801561061a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b600033610633858285610a5d565b61063e858585610ad7565b506001949350505050565b6000336103fa81858561065c8383610832565b6106669190611352565b610920565b6037546000906001600160a01b031633148061069157506033546001600160a01b031633145b6106ad5760405162461bcd60e51b815260040161049f90611365565b6106b78383610c9c565b50600192915050565b6106c8610df6565b6106d26000610a44565b565b60345433906001600160a01b031681146107425760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161049f565b61074b81610a44565b50565b6060603a8054610369906111dc565b6037546000906001600160a01b031633148061078357506033546001600160a01b031633145b61079f5760405162461bcd60e51b815260040161049f90611365565b6106b78383610e50565b600033816107b78286610832565b9050838110156108175760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161049f565b61063e8286868403610920565b6000336103fa818585610ad7565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b610865610df6565b603480546001600160a01b0383166001600160a01b031990911681179091556108966033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0383166109825760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161049f565b6001600160a01b0382166109e35760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161049f565b6001600160a01b0383811660008181526035602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b603480546001600160a01b031916905561074b816108ce565b6000610a698484610832565b90506000198114610ad15781811015610ac45760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161049f565b610ad18484848403610920565b50505050565b6001600160a01b038316610b3b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161049f565b6001600160a01b038216610b9d5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161049f565b6000806120206001600160a01b0316858585604051602001610bc1939291906113b2565b60408051601f1981840301815290829052610bdb916113d6565b6000604051808303816000865af19150503d8060008114610c18576040519150601f19603f3d011682016040523d82523d6000602084013e610c1d565b606091505b5091509150818015610c3e575080806020019051810190610c3e91906113f2565b610c5a5760405162461bcd60e51b815260040161049f90611414565b836001600160a01b0316856001600160a01b031660008051602061145883398151915285604051610c8d91815260200190565b60405180910390a35050505050565b6001600160a01b038216610cf25760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161049f565b8060366000828254610d049190611352565b9091555050604051600090819061202090610d27908390879087906020016113b2565b60408051601f1981840301815290829052610d41916113d6565b6000604051808303816000865af19150503d8060008114610d7e576040519150601f19603f3d011682016040523d82523d6000602084013e610d83565b606091505b5091509150818015610da4575080806020019051810190610da491906113f2565b610dc05760405162461bcd60e51b815260040161049f90611414565b6040518381526001600160a01b03851690600090600080516020611458833981519152906020015b60405180910390a350505050565b6033546001600160a01b031633146106d25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161049f565b6001600160a01b038216610eb05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161049f565b8060366000828254610ec29190611444565b9091555050604051600090819061202090610ee5908690849087906020016113b2565b60408051601f1981840301815290829052610eff916113d6565b6000604051808303816000865af19150503d8060008114610f3c576040519150601f19603f3d011682016040523d82523d6000602084013e610f41565b606091505b5091509150818015610f62575080806020019051810190610f6291906113f2565b610f7e5760405162461bcd60e51b815260040161049f90611414565b6040518381526000906001600160a01b0386169060008051602061145883398151915290602001610de8565b60005b83811015610fc5578181015183820152602001610fad565b50506000910152565b6020815260008251806020840152610fed816040850160208701610faa565b601f01601f19169190910160400192915050565b80356001600160a01b038116811461101857600080fd5b919050565b6000806040838503121561103057600080fd5b61103983611001565b946020939093013593505050565b60008083601f84011261105957600080fd5b50813567ffffffffffffffff81111561107157600080fd5b60208301915083602082850101111561108957600080fd5b9250929050565b60008060008060008060008060c0898b0312156110ac57600080fd5b6110b589611001565b97506110c360208a01611001565b96506110d160408a01611001565b9550606089013567ffffffffffffffff808211156110ee57600080fd5b6110fa8c838d01611047565b909750955060808b013591508082111561111357600080fd5b506111208b828c01611047565b90945092505060a089013560ff8116811461113a57600080fd5b809150509295985092959890939650565b60008060006060848603121561116057600080fd5b61116984611001565b925061117760208501611001565b9150604084013590509250925092565b60006020828403121561119957600080fd5b6111a282611001565b9392505050565b600080604083850312156111bc57600080fd5b6111c583611001565b91506111d360208401611001565b90509250929050565b600181811c908216806111f057607f821691505b60208210810361121057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b601f82111561127657600081815260208120601f850160051c810160208610156112535750805b601f850160051c820191505b818110156112725782815560010161125f565b5050505b505050565b67ffffffffffffffff83111561129357611293611216565b6112a7836112a183546111dc565b8361122c565b6000601f8411600181146112db57600085156112c35750838201355b600019600387901b1c1916600186901b178355611335565b600083815260209020601f19861690835b8281101561130c57868501358255602094850194600190920191016112ec565b50868210156113295760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b634e487b7160e01b600052601160045260246000fd5b808201808211156104005761040061133c565b6020808252602d908201527f4e617469766545524332303a204f6e6c7920707265646963617465206f72206f60408201526c1ddb995c8818d85b8818d85b1b609a1b606082015260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600082516113e8818460208701610faa565b9190910192915050565b60006020828403121561140457600080fd5b815180151581146111a257600080fd5b60208082526016908201527514149150d3d35412531157d0d0531317d1905253115160521b604082015260600190565b818103818111156104005761040061133c56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212209be318415f88ce7ef3eb3e9be7eed0fb2e93811e73c7b0d5b1fd4e46144f210d64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101795760003560e01c8063715018a6116100d9578063a457c2d711610087578063a457c2d7146102e3578063a9059cbb146102f6578063dd62ed3e14610309578063e0563ab11461031c578063e30c397814610325578063e619870514610336578063f2fde38b1461034757600080fd5b8063715018a61461029457806379ba50971461029c5780638da5cb5b146102a4578063947287cf146102b557806395d89b41146102be57806397e5230d146102c65780639dc29fac146102d057600080fd5b8063284017f511610136578063284017f51461021e578063313ce56714610227578063395093511461023c5780633b878c221461024f57806340c10f191461025857806351351d531461026b57806370a082311461027957600080fd5b806306fdde031461017e578063095ea7b31461019c57806318160ddd146101bf5780631f2d0065146101d1578063238b4bc5146101f657806323b872dd1461020b575b600080fd5b61018661035a565b6040516101939190610fce565b60405180910390f35b6101af6101aa36600461101d565b6103ec565b6040519015158152602001610193565b6036545b604051908152602001610193565b6038546001600160a01b03165b6040516001600160a01b039091168152602001610193565b610209610204366004611090565b610406565b005b6101af61021936600461114b565b610625565b6101de61202081565b603b5460405160ff9091168152602001610193565b6101af61024a36600461101d565b610649565b6101de61101081565b6101af61026636600461101d565b61066b565b6101de6002600160a01b0381565b6101c3610287366004611187565b6001600160a01b03163190565b6102096106c0565b6102096106d4565b6033546001600160a01b03166101de565b6101c361520881565b61018661074e565b6101c3620249f081565b6101af6102de36600461101d565b61075d565b6101af6102f136600461101d565b6107a9565b6101af61030436600461101d565b610824565b6101c36103173660046111a9565b610832565b6101de61203081565b6034546001600160a01b03166101de565b6037546001600160a01b03166101de565b610209610355366004611187565b61085d565b606060398054610369906111dc565b80601f0160208091040260200160405190810160405280929190818152602001828054610395906111dc565b80156103e25780601f106103b7576101008083540402835291602001916103e2565b820191906000526020600020905b8154815290600101906020018083116103c557829003601f168201915b5050505050905090565b6000336103fa818585610920565b60019150505b92915050565b600054610100900460ff16158080156104265750600054600160ff909116105b806104405750303b158015610440575060005460ff166001145b6104a85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff1916600117905580156104cb576000805461ff0019166101001790555b336002600160a01b031461050f5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b604482015260640161049f565b6001600160a01b0388166105705760405162461bcd60e51b815260206004820152602260248201527f4e617469766545524332303a20496e76616c6964206f776e6572206164647265604482015261737360f01b606482015260840161049f565b603780546001600160a01b03808c166001600160a01b03199283161790925560388054928a169290911691909117905560396105ad86888361127b565b50603a6105bb84868361127b565b50603b805460ff191660ff84161790556105d488610a44565b801561061a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b600033610633858285610a5d565b61063e858585610ad7565b506001949350505050565b6000336103fa81858561065c8383610832565b6106669190611352565b610920565b6037546000906001600160a01b031633148061069157506033546001600160a01b031633145b6106ad5760405162461bcd60e51b815260040161049f90611365565b6106b78383610c9c565b50600192915050565b6106c8610df6565b6106d26000610a44565b565b60345433906001600160a01b031681146107425760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b606482015260840161049f565b61074b81610a44565b50565b6060603a8054610369906111dc565b6037546000906001600160a01b031633148061078357506033546001600160a01b031633145b61079f5760405162461bcd60e51b815260040161049f90611365565b6106b78383610e50565b600033816107b78286610832565b9050838110156108175760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b606482015260840161049f565b61063e8286868403610920565b6000336103fa818585610ad7565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b610865610df6565b603480546001600160a01b0383166001600160a01b031990911681179091556108966033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b0383166109825760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b606482015260840161049f565b6001600160a01b0382166109e35760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b606482015260840161049f565b6001600160a01b0383811660008181526035602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b603480546001600160a01b031916905561074b816108ce565b6000610a698484610832565b90506000198114610ad15781811015610ac45760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e6365000000604482015260640161049f565b610ad18484848403610920565b50505050565b6001600160a01b038316610b3b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b606482015260840161049f565b6001600160a01b038216610b9d5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b606482015260840161049f565b6000806120206001600160a01b0316858585604051602001610bc1939291906113b2565b60408051601f1981840301815290829052610bdb916113d6565b6000604051808303816000865af19150503d8060008114610c18576040519150601f19603f3d011682016040523d82523d6000602084013e610c1d565b606091505b5091509150818015610c3e575080806020019051810190610c3e91906113f2565b610c5a5760405162461bcd60e51b815260040161049f90611414565b836001600160a01b0316856001600160a01b031660008051602061145883398151915285604051610c8d91815260200190565b60405180910390a35050505050565b6001600160a01b038216610cf25760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640161049f565b8060366000828254610d049190611352565b9091555050604051600090819061202090610d27908390879087906020016113b2565b60408051601f1981840301815290829052610d41916113d6565b6000604051808303816000865af19150503d8060008114610d7e576040519150601f19603f3d011682016040523d82523d6000602084013e610d83565b606091505b5091509150818015610da4575080806020019051810190610da491906113f2565b610dc05760405162461bcd60e51b815260040161049f90611414565b6040518381526001600160a01b03851690600090600080516020611458833981519152906020015b60405180910390a350505050565b6033546001600160a01b031633146106d25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161049f565b6001600160a01b038216610eb05760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b606482015260840161049f565b8060366000828254610ec29190611444565b9091555050604051600090819061202090610ee5908690849087906020016113b2565b60408051601f1981840301815290829052610eff916113d6565b6000604051808303816000865af19150503d8060008114610f3c576040519150601f19603f3d011682016040523d82523d6000602084013e610f41565b606091505b5091509150818015610f62575080806020019051810190610f6291906113f2565b610f7e5760405162461bcd60e51b815260040161049f90611414565b6040518381526000906001600160a01b0386169060008051602061145883398151915290602001610de8565b60005b83811015610fc5578181015183820152602001610fad565b50506000910152565b6020815260008251806020840152610fed816040850160208701610faa565b601f01601f19169190910160400192915050565b80356001600160a01b038116811461101857600080fd5b919050565b6000806040838503121561103057600080fd5b61103983611001565b946020939093013593505050565b60008083601f84011261105957600080fd5b50813567ffffffffffffffff81111561107157600080fd5b60208301915083602082850101111561108957600080fd5b9250929050565b60008060008060008060008060c0898b0312156110ac57600080fd5b6110b589611001565b97506110c360208a01611001565b96506110d160408a01611001565b9550606089013567ffffffffffffffff808211156110ee57600080fd5b6110fa8c838d01611047565b909750955060808b013591508082111561111357600080fd5b506111208b828c01611047565b90945092505060a089013560ff8116811461113a57600080fd5b809150509295985092959890939650565b60008060006060848603121561116057600080fd5b61116984611001565b925061117760208501611001565b9150604084013590509250925092565b60006020828403121561119957600080fd5b6111a282611001565b9392505050565b600080604083850312156111bc57600080fd5b6111c583611001565b91506111d360208401611001565b90509250929050565b600181811c908216806111f057607f821691505b60208210810361121057634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b601f82111561127657600081815260208120601f850160051c810160208610156112535750805b601f850160051c820191505b818110156112725782815560010161125f565b5050505b505050565b67ffffffffffffffff83111561129357611293611216565b6112a7836112a183546111dc565b8361122c565b6000601f8411600181146112db57600085156112c35750838201355b600019600387901b1c1916600186901b178355611335565b600083815260209020601f19861690835b8281101561130c57868501358255602094850194600190920191016112ec565b50868210156113295760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b634e487b7160e01b600052601160045260246000fd5b808201808211156104005761040061133c565b6020808252602d908201527f4e617469766545524332303a204f6e6c7920707265646963617465206f72206f60408201526c1ddb995c8818d85b8818d85b1b609a1b606082015260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600082516113e8818460208701610faa565b9190910192915050565b60006020828403121561140457600080fd5b815180151581146111a257600080fd5b60208082526016908201527514149150d3d35412531157d0d0531317d1905253115160521b604082015260600190565b818103818111156104005761040061133c56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212209be318415f88ce7ef3eb3e9be7eed0fb2e93811e73c7b0d5b1fd4e46144f210d64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var ChildERC20Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC20\",\n \"sourceName\": \"contracts/child/ChildERC20.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"userAddress\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"relayerAddress\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"functionSignature\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"MetaTransactionExecuted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"userAddress\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"functionSignature\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"sigR\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"sigS\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"sigV\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"executeMetaTransaction\",\n \"outputs\": [\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"user\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"getNonce\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"nonce\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"rootToken_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"name_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"symbol_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"decimals_\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506118e3806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806340c10f19116100a2578063a457c2d711610071578063a457c2d71461026b578063a9059cbb1461027e578063dd62ed3e14610291578063e6198705146102a4578063f6d2ee86146102b557600080fd5b806340c10f191461021457806370a082311461022757806395d89b41146102505780639dc29fac1461025857600080fd5b80631f2d0065116100e95780631f2d00651461018157806323b872dd146101a65780632d0335ab146101b9578063313ce567146101e2578063395093511461020157600080fd5b806306fdde031461011b578063095ea7b3146101395780630c53c51c1461015c57806318160ddd1461016f575b600080fd5b6101236102ca565b6040516101309190611371565b60405180910390f35b61014c6101473660046113a7565b61035c565b6040519015158152602001610130565b61012361016a36600461142b565b610380565b603c545b604051908152602001610130565b606d546001600160a01b03165b6040516001600160a01b039091168152602001610130565b61014c6101b43660046114a1565b610663565b6101736101c73660046114dd565b6001600160a01b031660009081526006602052604090205490565b606d54600160a01b900460ff1660405160ff9091168152602001610130565b61014c61020f3660046113a7565b610691565b61014c6102223660046113a7565b6106bd565b6101736102353660046114dd565b6001600160a01b03166000908152603a602052604090205490565b6101236106fd565b61014c6102663660046113a7565b61070c565b61014c6102793660046113a7565b610743565b61014c61028c3660046113a7565b6107c9565b61017361029f3660046114f8565b6107e1565b606c546001600160a01b031661018e565b6102c86102c336600461152b565b61080c565b005b6060603d80546102d9906115af565b80601f0160208091040260200160405190810160405280929190818152602001828054610305906115af565b80156103525780601f1061032757610100808354040283529160200191610352565b820191906000526020600020905b81548152906001019060200180831161033557829003601f168201915b5050505050905090565b600080610367610a8c565b9050610374818585610a9b565b60019150505b92915050565b606060006103c387878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610bc092505050565b90506001600160e01b031960003581169082160361044e5760405162461bcd60e51b815260206004820152603d60248201527f66756e6374696f6e5369676e61747572652063616e206e6f74206265206f662060448201527f657865637574654d6574615472616e73616374696f6e206d6574686f6400000060648201526084015b60405180910390fd5b604080516060810182526001600160a01b038a16600081815260066020908152848220548452808401929092528351601f8b0183900483028101830185528a815290938301918b908b9081908401838280828437600092019190915250505091525090506104bf8982888888610bdb565b6105155760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610445565b600660008a6001600160a01b03166001600160a01b031681526020019081526020016000206000815460010191905081905550600080306001600160a01b03168a8a8d60405160200161056a939291906115e9565b60408051601f19818403018152908290526105849161160f565b6000604051808303816000865af19150503d80600081146105c1576040519150601f19603f3d011682016040523d82523d6000602084013e6105c6565b606091505b5091509150816106185760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610445565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b8b338c8c60405161064d949392919061162b565b60405180910390a19a9950505050505050505050565b60008061066e610a8c565b905061067b858285610cb7565b610686858585610d31565b506001949350505050565b60008061069c610a8c565b90506103748185856106ae85896107e1565b6106b89190611677565b610a9b565b606c546000906001600160a01b031633146106ea5760405162461bcd60e51b815260040161044590611698565b6106f48383610eca565b50600192915050565b6060603e80546102d9906115af565b606c546000906001600160a01b031633146107395760405162461bcd60e51b815260040161044590611698565b6106f48383610f7a565b60008061074e610a8c565b9050600061075c82866107e1565b9050838110156107bc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610445565b6106868286868403610a9b565b6000806107d4610a8c565b9050610374818585610d31565b6001600160a01b039182166000908152603b6020908152604080832093909416825291909152205490565b600754610100900460ff161580801561082c5750600754600160ff909116105b806108465750303b158015610846575060075460ff166001145b6108a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610445565b6007805460ff1916600117905580156108cc576007805461ff0019166101001790555b6001600160a01b038716158015906108e357508415155b80156108ee57508215155b61093a5760405162461bcd60e51b815260206004820152601e60248201527f4368696c6445524332303a204241445f494e495449414c495a4154494f4e00006044820152606401610445565b606d805460ff8416600160a01b026001600160a81b03199091166001600160a01b038a1617179055606c80546001600160a01b03191633179055604080516020601f88018190048102820181019092528681526109e591889088908190840183828082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525061109992505050565b610a3d86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b602082015291506110ca9050565b8015610a83576007805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6000610a96611136565b905090565b6001600160a01b038316610afd5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610445565b6001600160a01b038216610b5e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610445565b6001600160a01b038381166000818152603b602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60008151600003610bd357506000919050565b506020015190565b6000806001610bf1610bec88611192565b61120f565b6040805160008152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015610c3f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610c965760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610445565b866001600160a01b0316816001600160a01b03161491505095945050505050565b6000610cc384846107e1565b90506000198114610d2b5781811015610d1e5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610445565b610d2b8484848403610a9b565b50505050565b6001600160a01b038316610d955760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610445565b6001600160a01b038216610df75760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610445565b6001600160a01b0383166000908152603a602052604090205481811015610e6f5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610445565b6001600160a01b038085166000818152603a6020526040808220868603905592861680825290839020805486019055915160008051602061188e83398151915290610ebd9086815260200190565b60405180910390a3610d2b565b6001600160a01b038216610f205760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610445565b80603c6000828254610f329190611677565b90915550506001600160a01b0382166000818152603a602090815260408083208054860190555184815260008051602061188e833981519152910160405180910390a35b5050565b6001600160a01b038216610fda5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610445565b6001600160a01b0382166000908152603a60205260409020548181101561104e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610445565b6001600160a01b0383166000818152603a602090815260408083208686039055603c805487900390555185815291929160008051602061188e8339815191529101610bb3565b505050565b600754610100900460ff166110c05760405162461bcd60e51b8152600401610445906116db565b610f76828261125d565b815160208084019190912082519183019190912060038290556004819055466001557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61111881848461129d565b600055600280546001600160a01b0319163017905560055550505050565b600030330361118c57600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b0316915061118f9050565b50335b90565b600060405180608001604052806043815260200161184b60439139805160209182012083518483015160408087015180519086012090516111f2950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061037a61121c6112e6565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600754610100900460ff166112845760405162461bcd60e51b8152600401610445906116db565b603d611290838261178a565b50603e611094828261178a565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6002546000906001600160a01b031630148015611304575060015446145b15611310575060005490565b610a9660055460035460045461129d565b60005b8381101561133c578181015183820152602001611324565b50506000910152565b6000815180845261135d816020860160208601611321565b601f01601f19169290920160200192915050565b6020815260006113846020830184611345565b9392505050565b80356001600160a01b03811681146113a257600080fd5b919050565b600080604083850312156113ba57600080fd5b6113c38361138b565b946020939093013593505050565b60008083601f8401126113e357600080fd5b50813567ffffffffffffffff8111156113fb57600080fd5b60208301915083602082850101111561141357600080fd5b9250929050565b803560ff811681146113a257600080fd5b60008060008060008060a0878903121561144457600080fd5b61144d8761138b565b9550602087013567ffffffffffffffff81111561146957600080fd5b61147589828a016113d1565b90965094505060408701359250606087013591506114956080880161141a565b90509295509295509295565b6000806000606084860312156114b657600080fd5b6114bf8461138b565b92506114cd6020850161138b565b9150604084013590509250925092565b6000602082840312156114ef57600080fd5b6113848261138b565b6000806040838503121561150b57600080fd5b6115148361138b565b91506115226020840161138b565b90509250929050565b6000806000806000806080878903121561154457600080fd5b61154d8761138b565b9550602087013567ffffffffffffffff8082111561156a57600080fd5b6115768a838b016113d1565b9097509550604089013591508082111561158f57600080fd5b5061159c89828a016113d1565b909450925061149590506060880161141a565b600181811c908216806115c357607f821691505b6020821081036115e357634e487b7160e01b600052602260045260246000fd5b50919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251611621818460208701611321565b9190910192915050565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b8082018082111561037a57634e487b7160e01b600052601160045260246000fd5b60208082526023908201527f4368696c6445524332303a204f6e6c79207072656469636174652063616e2063604082015262185b1b60ea1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561109457600081815260208120601f850160051c810160208610156117635750805b601f850160051c820191505b818110156117825782815560010161176f565b505050505050565b815167ffffffffffffffff8111156117a4576117a4611726565b6117b8816117b284546115af565b8461173c565b602080601f8311600181146117ed57600084156117d55750858301515b600019600386901b1c1916600185901b178555611782565b600085815260208120601f198616915b8281101561181c578886015182559484019460019091019084016117fd565b508582101561183a5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122006e7874e62afcc37d931c31b2d4bea5f12ba721af845c8552d4733d66d6dcbb064736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101165760003560e01c806340c10f19116100a2578063a457c2d711610071578063a457c2d71461026b578063a9059cbb1461027e578063dd62ed3e14610291578063e6198705146102a4578063f6d2ee86146102b557600080fd5b806340c10f191461021457806370a082311461022757806395d89b41146102505780639dc29fac1461025857600080fd5b80631f2d0065116100e95780631f2d00651461018157806323b872dd146101a65780632d0335ab146101b9578063313ce567146101e2578063395093511461020157600080fd5b806306fdde031461011b578063095ea7b3146101395780630c53c51c1461015c57806318160ddd1461016f575b600080fd5b6101236102ca565b6040516101309190611371565b60405180910390f35b61014c6101473660046113a7565b61035c565b6040519015158152602001610130565b61012361016a36600461142b565b610380565b603c545b604051908152602001610130565b606d546001600160a01b03165b6040516001600160a01b039091168152602001610130565b61014c6101b43660046114a1565b610663565b6101736101c73660046114dd565b6001600160a01b031660009081526006602052604090205490565b606d54600160a01b900460ff1660405160ff9091168152602001610130565b61014c61020f3660046113a7565b610691565b61014c6102223660046113a7565b6106bd565b6101736102353660046114dd565b6001600160a01b03166000908152603a602052604090205490565b6101236106fd565b61014c6102663660046113a7565b61070c565b61014c6102793660046113a7565b610743565b61014c61028c3660046113a7565b6107c9565b61017361029f3660046114f8565b6107e1565b606c546001600160a01b031661018e565b6102c86102c336600461152b565b61080c565b005b6060603d80546102d9906115af565b80601f0160208091040260200160405190810160405280929190818152602001828054610305906115af565b80156103525780601f1061032757610100808354040283529160200191610352565b820191906000526020600020905b81548152906001019060200180831161033557829003601f168201915b5050505050905090565b600080610367610a8c565b9050610374818585610a9b565b60019150505b92915050565b606060006103c387878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610bc092505050565b90506001600160e01b031960003581169082160361044e5760405162461bcd60e51b815260206004820152603d60248201527f66756e6374696f6e5369676e61747572652063616e206e6f74206265206f662060448201527f657865637574654d6574615472616e73616374696f6e206d6574686f6400000060648201526084015b60405180910390fd5b604080516060810182526001600160a01b038a16600081815260066020908152848220548452808401929092528351601f8b0183900483028101830185528a815290938301918b908b9081908401838280828437600092019190915250505091525090506104bf8982888888610bdb565b6105155760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610445565b600660008a6001600160a01b03166001600160a01b031681526020019081526020016000206000815460010191905081905550600080306001600160a01b03168a8a8d60405160200161056a939291906115e9565b60408051601f19818403018152908290526105849161160f565b6000604051808303816000865af19150503d80600081146105c1576040519150601f19603f3d011682016040523d82523d6000602084013e6105c6565b606091505b5091509150816106185760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610445565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b8b338c8c60405161064d949392919061162b565b60405180910390a19a9950505050505050505050565b60008061066e610a8c565b905061067b858285610cb7565b610686858585610d31565b506001949350505050565b60008061069c610a8c565b90506103748185856106ae85896107e1565b6106b89190611677565b610a9b565b606c546000906001600160a01b031633146106ea5760405162461bcd60e51b815260040161044590611698565b6106f48383610eca565b50600192915050565b6060603e80546102d9906115af565b606c546000906001600160a01b031633146107395760405162461bcd60e51b815260040161044590611698565b6106f48383610f7a565b60008061074e610a8c565b9050600061075c82866107e1565b9050838110156107bc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610445565b6106868286868403610a9b565b6000806107d4610a8c565b9050610374818585610d31565b6001600160a01b039182166000908152603b6020908152604080832093909416825291909152205490565b600754610100900460ff161580801561082c5750600754600160ff909116105b806108465750303b158015610846575060075460ff166001145b6108a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610445565b6007805460ff1916600117905580156108cc576007805461ff0019166101001790555b6001600160a01b038716158015906108e357508415155b80156108ee57508215155b61093a5760405162461bcd60e51b815260206004820152601e60248201527f4368696c6445524332303a204241445f494e495449414c495a4154494f4e00006044820152606401610445565b606d805460ff8416600160a01b026001600160a81b03199091166001600160a01b038a1617179055606c80546001600160a01b03191633179055604080516020601f88018190048102820181019092528681526109e591889088908190840183828082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525061109992505050565b610a3d86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b602082015291506110ca9050565b8015610a83576007805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6000610a96611136565b905090565b6001600160a01b038316610afd5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610445565b6001600160a01b038216610b5e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610445565b6001600160a01b038381166000818152603b602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60008151600003610bd357506000919050565b506020015190565b6000806001610bf1610bec88611192565b61120f565b6040805160008152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015610c3f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610c965760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610445565b866001600160a01b0316816001600160a01b03161491505095945050505050565b6000610cc384846107e1565b90506000198114610d2b5781811015610d1e5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610445565b610d2b8484848403610a9b565b50505050565b6001600160a01b038316610d955760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610445565b6001600160a01b038216610df75760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610445565b6001600160a01b0383166000908152603a602052604090205481811015610e6f5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610445565b6001600160a01b038085166000818152603a6020526040808220868603905592861680825290839020805486019055915160008051602061188e83398151915290610ebd9086815260200190565b60405180910390a3610d2b565b6001600160a01b038216610f205760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610445565b80603c6000828254610f329190611677565b90915550506001600160a01b0382166000818152603a602090815260408083208054860190555184815260008051602061188e833981519152910160405180910390a35b5050565b6001600160a01b038216610fda5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610445565b6001600160a01b0382166000908152603a60205260409020548181101561104e5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610445565b6001600160a01b0383166000818152603a602090815260408083208686039055603c805487900390555185815291929160008051602061188e8339815191529101610bb3565b505050565b600754610100900460ff166110c05760405162461bcd60e51b8152600401610445906116db565b610f76828261125d565b815160208084019190912082519183019190912060038290556004819055466001557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61111881848461129d565b600055600280546001600160a01b0319163017905560055550505050565b600030330361118c57600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b0316915061118f9050565b50335b90565b600060405180608001604052806043815260200161184b60439139805160209182012083518483015160408087015180519086012090516111f2950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061037a61121c6112e6565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b600754610100900460ff166112845760405162461bcd60e51b8152600401610445906116db565b603d611290838261178a565b50603e611094828261178a565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6002546000906001600160a01b031630148015611304575060015446145b15611310575060005490565b610a9660055460035460045461129d565b60005b8381101561133c578181015183820152602001611324565b50506000910152565b6000815180845261135d816020860160208601611321565b601f01601f19169290920160200192915050565b6020815260006113846020830184611345565b9392505050565b80356001600160a01b03811681146113a257600080fd5b919050565b600080604083850312156113ba57600080fd5b6113c38361138b565b946020939093013593505050565b60008083601f8401126113e357600080fd5b50813567ffffffffffffffff8111156113fb57600080fd5b60208301915083602082850101111561141357600080fd5b9250929050565b803560ff811681146113a257600080fd5b60008060008060008060a0878903121561144457600080fd5b61144d8761138b565b9550602087013567ffffffffffffffff81111561146957600080fd5b61147589828a016113d1565b90965094505060408701359250606087013591506114956080880161141a565b90509295509295509295565b6000806000606084860312156114b657600080fd5b6114bf8461138b565b92506114cd6020850161138b565b9150604084013590509250925092565b6000602082840312156114ef57600080fd5b6113848261138b565b6000806040838503121561150b57600080fd5b6115148361138b565b91506115226020840161138b565b90509250929050565b6000806000806000806080878903121561154457600080fd5b61154d8761138b565b9550602087013567ffffffffffffffff8082111561156a57600080fd5b6115768a838b016113d1565b9097509550604089013591508082111561158f57600080fd5b5061159c89828a016113d1565b909450925061149590506060880161141a565b600181811c908216806115c357607f821691505b6020821081036115e357634e487b7160e01b600052602260045260246000fd5b50919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251611621818460208701611321565b9190910192915050565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b8082018082111561037a57634e487b7160e01b600052601160045260246000fd5b60208082526023908201527f4368696c6445524332303a204f6e6c79207072656469636174652063616e2063604082015262185b1b60ea1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561109457600081815260208120601f850160051c810160208610156117635750805b601f850160051c820191505b818110156117825782815560010161176f565b505050505050565b815167ffffffffffffffff8111156117a4576117a4611726565b6117b8816117b284546115af565b8461173c565b602080601f8311600181146117ed57600084156117d55750858301515b600019600386901b1c1916600185901b178555611782565b600085815260208120601f198616915b8281101561181c578886015182559484019460019091019084016117fd565b508582101561183a5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122006e7874e62afcc37d931c31b2d4bea5f12ba721af845c8552d4733d66d6dcbb064736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var ChildERC20PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC20Predicate\",\n \"sourceName\": \"contracts/child/ChildERC20Predicate.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC20Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC20Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newNativeTokenRootAddress\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611490806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806397e5230d116100a2578063d41f177111610071578063d41f17711461023d578063e0563ab114610264578063eeb499451461026d578063f3fef3a314610280578063f64512551461029357600080fd5b806397e5230d146101e6578063b1768065146101f0578063b68ad1e414610217578063c3b35a7e1461022a57600080fd5b80633b878c22116100e95780633b878c221461017c57806351351d531461018557806371cf93b7146101935780637efab4f5146101a6578063947287cf146101cf57600080fd5b806305dc2e8f1461011b5780631459457a1461014b5780631bc114ba14610160578063284017f514610173575b600080fd5b60345461012e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61015e610159366004610f98565b6102ba565b005b60335461012e906001600160a01b031681565b61012e61202081565b61012e61101081565b61012e6002600160a01b0381565b60355461012e906001600160a01b031681565b61012e6101b4366004611009565b6037602052600090815260409020546001600160a01b031681565b6101d861520881565b604051908152602001610142565b6101d8620249f081565b6101d87f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60365461012e906001600160a01b031681565b61015e61023836600461102d565b61055a565b6101d87f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61012e61203081565b61015e61027b36600461106e565b61056a565b61015e61028e3660046110f7565b61073e565b6101d87f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b336002600160a01b03146103035760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064015b60405180910390fd5b600054610100900460ff16158080156103235750600054600160ff909116105b8061033d5750303b15801561033d575060005460ff166001145b6103a05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016102fa565b6000805460ff1916600117905580156103c3576000805461ff0019166101001790555b6001600160a01b038616158015906103e357506001600160a01b03851615155b80156103f757506001600160a01b03841615155b801561040b57506001600160a01b03831615155b6104675760405162461bcd60e51b815260206004820152602760248201527f4368696c6445524332305072656469636174653a204241445f494e495449414c60448201526624ad20aa24a7a760c91b60648201526084016102fa565b603380546001600160a01b03199081166001600160a01b03898116919091179092556034805482168884161790556035805482168784161790556036805490911685831617905582161561050c576001600160a01b03821660008181526037602052604080822080546001600160a01b03191661101090811790915590519092917f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d91a35b8015610552576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b61056583838361074d565b505050565b6034546001600160a01b031633146105d55760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f53544154455f6044820152672922a1a2a4ab22a960c11b60648201526084016102fa565b6035546001600160a01b038481169116146106435760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f524f4f545f50604482015267524544494341544560c01b60648201526084016102fa565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f821610672602060008486611123565b61067b9161114d565b0361069a576106956106908260208186611123565b610ac3565b610738565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6106c9602060008486611123565b6106d29161114d565b036106e1576106958282610d6e565b60405162461bcd60e51b815260206004820152602660248201527f4368696c6445524332305072656469636174653a20494e56414c49445f5349476044820152654e415455524560d01b60648201526084016102fa565b50505050565b61074982338361074d565b5050565b826001600160a01b03163b6000036107b15760405162461bcd60e51b815260206004820152602160248201527f4368696c6445524332305072656469636174653a204e4f545f434f4e545241436044820152601560fa1b60648201526084016102fa565b6000836001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610815919061116b565b6001600160a01b038181166000908152603760205260409020549192508581169116146108545760405162461bcd60e51b81526004016102fa90611188565b6001600160a01b03811661086a5761086a6111cb565b306001600160a01b0316846001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d6919061116b565b6001600160a01b0316146108ec576108ec6111cb565b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac9061091a90339086906004016111e1565b6020604051808303816000875af1158015610939573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095d91906111fa565b6109a95760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204255524e5f4641494c454460448201526064016102fa565b603354603554604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610a349391169160c401611262565b600060405180830381600087803b158015610a4e57600080fd5b505af1158015610a62573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316826001600160a01b03167fa0923f060a16fc784558d43de424ffde7b01643de5e5d335851b9df94c76bb273386604051610ab59291906111e1565b60405180910390a450505050565b6000808080610ad48587018761128e565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610b175760405162461bcd60e51b81526004016102fa90611188565b806001600160a01b03163b600003610b3157610b316111cb565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061116b565b9050856001600160a01b0316816001600160a01b031614610bb857610bb86111cb565b6001600160a01b038116610bce57610bce6111cb565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3a919061116b565b6001600160a01b031614610c5057610c506111cb565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610c7e90879087906004016111e1565b6020604051808303816000875af1158015610c9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc191906111fa565b610d0d5760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204d494e545f4641494c454460448201526064016102fa565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fdf34f3a3ed8bedc14a4b284ebaee5374d55b64bac6a84c270dabe8fd6b4cdafd8887604051610d5c9291906111e1565b60405180910390a45050505050505050565b6000808080610d7f85870187611382565b92975090955093509150506001600160a01b038416610da057610da06111cb565b6001600160a01b038481166000908152603760205260409020541615610dc857610dc86111cb565b6036546040516bffffffffffffffffffffffff19606087901b166020820152600091610e18916001600160a01b039091169060340160405160208183030381529060405280519060200120610ee3565b6001600160a01b038681166000908152603760205260409081902080546001600160a01b031916928416928317905551637b69774360e11b81529192509063f6d2ee8690610e7090889088908890889060040161140f565b600060405180830381600087803b158015610e8a57600080fd5b505af1158015610e9e573d6000803e3d6000fd5b50506040516001600160a01b038085169350881691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a350505050505050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116610f7a5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016102fa565b92915050565b6001600160a01b0381168114610f9557600080fd5b50565b600080600080600060a08688031215610fb057600080fd5b8535610fbb81610f80565b94506020860135610fcb81610f80565b93506040860135610fdb81610f80565b92506060860135610feb81610f80565b91506080860135610ffb81610f80565b809150509295509295909350565b60006020828403121561101b57600080fd5b813561102681610f80565b9392505050565b60008060006060848603121561104257600080fd5b833561104d81610f80565b9250602084013561105d81610f80565b929592945050506040919091013590565b6000806000806060858703121561108457600080fd5b84359350602085013561109681610f80565b9250604085013567ffffffffffffffff808211156110b357600080fd5b818701915087601f8301126110c757600080fd5b8135818111156110d657600080fd5b8860208285010111156110e857600080fd5b95989497505060200194505050565b6000806040838503121561110a57600080fd5b823561111581610f80565b946020939093013593505050565b6000808585111561113357600080fd5b8386111561114057600080fd5b5050820193919092039150565b80356020831015610f7a57600019602084900360031b1b1692915050565b60006020828403121561117d57600080fd5b815161102681610f80565b60208082526023908201527f4368696c6445524332305072656469636174653a20554e4d41505045445f544f60408201526225a2a760e91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b60006020828403121561120c57600080fd5b8151801515811461102657600080fd5b6000815180845260005b8181101561124257602081850181015186830182015201611226565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190526000906112869083018461121c565b949350505050565b600080600080608085870312156112a457600080fd5b84356112af81610f80565b935060208501356112bf81610f80565b925060408501356112cf81610f80565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261130657600080fd5b813567ffffffffffffffff80821115611321576113216112df565b604051601f8301601f19908116603f01168101908282118183101715611349576113496112df565b8160405283815286602085880101111561136257600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a0868803121561139a57600080fd5b8535945060208601356113ac81610f80565b9350604086013567ffffffffffffffff808211156113c957600080fd5b6113d589838a016112f5565b945060608801359150808211156113eb57600080fd5b506113f8888289016112f5565b925050608086013560ff81168114610ffb57600080fd5b6001600160a01b03851681526080602082018190526000906114339083018661121c565b8281036040840152611445818661121c565b91505060ff831660608301529594505050505056fea2646970667358221220826f58ea208b8a100d3343999582bb4813e24a5dd686101ad5da8213058bdfaf64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101165760003560e01c806397e5230d116100a2578063d41f177111610071578063d41f17711461023d578063e0563ab114610264578063eeb499451461026d578063f3fef3a314610280578063f64512551461029357600080fd5b806397e5230d146101e6578063b1768065146101f0578063b68ad1e414610217578063c3b35a7e1461022a57600080fd5b80633b878c22116100e95780633b878c221461017c57806351351d531461018557806371cf93b7146101935780637efab4f5146101a6578063947287cf146101cf57600080fd5b806305dc2e8f1461011b5780631459457a1461014b5780631bc114ba14610160578063284017f514610173575b600080fd5b60345461012e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61015e610159366004610f98565b6102ba565b005b60335461012e906001600160a01b031681565b61012e61202081565b61012e61101081565b61012e6002600160a01b0381565b60355461012e906001600160a01b031681565b61012e6101b4366004611009565b6037602052600090815260409020546001600160a01b031681565b6101d861520881565b604051908152602001610142565b6101d8620249f081565b6101d87f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60365461012e906001600160a01b031681565b61015e61023836600461102d565b61055a565b6101d87f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61012e61203081565b61015e61027b36600461106e565b61056a565b61015e61028e3660046110f7565b61073e565b6101d87f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b336002600160a01b03146103035760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064015b60405180910390fd5b600054610100900460ff16158080156103235750600054600160ff909116105b8061033d5750303b15801561033d575060005460ff166001145b6103a05760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016102fa565b6000805460ff1916600117905580156103c3576000805461ff0019166101001790555b6001600160a01b038616158015906103e357506001600160a01b03851615155b80156103f757506001600160a01b03841615155b801561040b57506001600160a01b03831615155b6104675760405162461bcd60e51b815260206004820152602760248201527f4368696c6445524332305072656469636174653a204241445f494e495449414c60448201526624ad20aa24a7a760c91b60648201526084016102fa565b603380546001600160a01b03199081166001600160a01b03898116919091179092556034805482168884161790556035805482168784161790556036805490911685831617905582161561050c576001600160a01b03821660008181526037602052604080822080546001600160a01b03191661101090811790915590519092917f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d91a35b8015610552576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b61056583838361074d565b505050565b6034546001600160a01b031633146105d55760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f53544154455f6044820152672922a1a2a4ab22a960c11b60648201526084016102fa565b6035546001600160a01b038481169116146106435760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f524f4f545f50604482015267524544494341544560c01b60648201526084016102fa565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f821610672602060008486611123565b61067b9161114d565b0361069a576106956106908260208186611123565b610ac3565b610738565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6106c9602060008486611123565b6106d29161114d565b036106e1576106958282610d6e565b60405162461bcd60e51b815260206004820152602660248201527f4368696c6445524332305072656469636174653a20494e56414c49445f5349476044820152654e415455524560d01b60648201526084016102fa565b50505050565b61074982338361074d565b5050565b826001600160a01b03163b6000036107b15760405162461bcd60e51b815260206004820152602160248201527f4368696c6445524332305072656469636174653a204e4f545f434f4e545241436044820152601560fa1b60648201526084016102fa565b6000836001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610815919061116b565b6001600160a01b038181166000908152603760205260409020549192508581169116146108545760405162461bcd60e51b81526004016102fa90611188565b6001600160a01b03811661086a5761086a6111cb565b306001600160a01b0316846001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d6919061116b565b6001600160a01b0316146108ec576108ec6111cb565b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac9061091a90339086906004016111e1565b6020604051808303816000875af1158015610939573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095d91906111fa565b6109a95760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204255524e5f4641494c454460448201526064016102fa565b603354603554604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610a349391169160c401611262565b600060405180830381600087803b158015610a4e57600080fd5b505af1158015610a62573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316826001600160a01b03167fa0923f060a16fc784558d43de424ffde7b01643de5e5d335851b9df94c76bb273386604051610ab59291906111e1565b60405180910390a450505050565b6000808080610ad48587018761128e565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610b175760405162461bcd60e51b81526004016102fa90611188565b806001600160a01b03163b600003610b3157610b316111cb565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b95919061116b565b9050856001600160a01b0316816001600160a01b031614610bb857610bb86111cb565b6001600160a01b038116610bce57610bce6111cb565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3a919061116b565b6001600160a01b031614610c5057610c506111cb565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610c7e90879087906004016111e1565b6020604051808303816000875af1158015610c9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc191906111fa565b610d0d5760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204d494e545f4641494c454460448201526064016102fa565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fdf34f3a3ed8bedc14a4b284ebaee5374d55b64bac6a84c270dabe8fd6b4cdafd8887604051610d5c9291906111e1565b60405180910390a45050505050505050565b6000808080610d7f85870187611382565b92975090955093509150506001600160a01b038416610da057610da06111cb565b6001600160a01b038481166000908152603760205260409020541615610dc857610dc86111cb565b6036546040516bffffffffffffffffffffffff19606087901b166020820152600091610e18916001600160a01b039091169060340160405160208183030381529060405280519060200120610ee3565b6001600160a01b038681166000908152603760205260409081902080546001600160a01b031916928416928317905551637b69774360e11b81529192509063f6d2ee8690610e7090889088908890889060040161140f565b600060405180830381600087803b158015610e8a57600080fd5b505af1158015610e9e573d6000803e3d6000fd5b50506040516001600160a01b038085169350881691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a350505050505050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116610f7a5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016102fa565b92915050565b6001600160a01b0381168114610f9557600080fd5b50565b600080600080600060a08688031215610fb057600080fd5b8535610fbb81610f80565b94506020860135610fcb81610f80565b93506040860135610fdb81610f80565b92506060860135610feb81610f80565b91506080860135610ffb81610f80565b809150509295509295909350565b60006020828403121561101b57600080fd5b813561102681610f80565b9392505050565b60008060006060848603121561104257600080fd5b833561104d81610f80565b9250602084013561105d81610f80565b929592945050506040919091013590565b6000806000806060858703121561108457600080fd5b84359350602085013561109681610f80565b9250604085013567ffffffffffffffff808211156110b357600080fd5b818701915087601f8301126110c757600080fd5b8135818111156110d657600080fd5b8860208285010111156110e857600080fd5b95989497505060200194505050565b6000806040838503121561110a57600080fd5b823561111581610f80565b946020939093013593505050565b6000808585111561113357600080fd5b8386111561114057600080fd5b5050820193919092039150565b80356020831015610f7a57600019602084900360031b1b1692915050565b60006020828403121561117d57600080fd5b815161102681610f80565b60208082526023908201527f4368696c6445524332305072656469636174653a20554e4d41505045445f544f60408201526225a2a760e91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b60006020828403121561120c57600080fd5b8151801515811461102657600080fd5b6000815180845260005b8181101561124257602081850181015186830182015201611226565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190526000906112869083018461121c565b949350505050565b600080600080608085870312156112a457600080fd5b84356112af81610f80565b935060208501356112bf81610f80565b925060408501356112cf81610f80565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261130657600080fd5b813567ffffffffffffffff80821115611321576113216112df565b604051601f8301601f19908116603f01168101908282118183101715611349576113496112df565b8160405283815286602085880101111561136257600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a0868803121561139a57600080fd5b8535945060208601356113ac81610f80565b9350604086013567ffffffffffffffff808211156113c957600080fd5b6113d589838a016112f5565b945060608801359150808211156113eb57600080fd5b506113f8888289016112f5565b925050608086013560ff81168114610ffb57600080fd5b6001600160a01b03851681526080602082018190526000906114339083018661121c565b8281036040840152611445818661121c565b91505060ff831660608301529594505050505056fea2646970667358221220826f58ea208b8a100d3343999582bb4813e24a5dd686101ad5da8213058bdfaf64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var SystemArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"System\",\n \"sourceName\": \"contracts/child/System.sol\",\n \"abi\": [\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b5060f58061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610605a5760003560e01c8063284017f514605f5780633b878c2214608457806351351d5314608c578063947287cf14609957806397e5230d1460ae578063e0563ab11460b7575b600080fd5b606761202081565b6040516001600160a01b0390911681526020015b60405180910390f35b606761101081565b60676002600160a01b0381565b60a161520881565b604051908152602001607b565b60a1620249f081565b60676120308156fea264697066735822122064014c9d48fdaeeccbde77e32e0a3289adc5bd43847b6b471e83d76a9ba6fbab64736f6c63430008110033\",\n \"deployedBytecode\": \"0x6080604052348015600f57600080fd5b5060043610605a5760003560e01c8063284017f514605f5780633b878c2214608457806351351d5314608c578063947287cf14609957806397e5230d1460ae578063e0563ab11460b7575b600080fd5b606761202081565b6040516001600160a01b0390911681526020015b60405180910390f35b606761101081565b60676002600160a01b0381565b60a161520881565b604051908152602001607b565b60a1620249f081565b60676120308156fea264697066735822122064014c9d48fdaeeccbde77e32e0a3289adc5bd43847b6b471e83d76a9ba6fbab64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var BLSArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"BLS\",\n \"sourceName\": \"contracts/common/BLS.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"domain\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"message\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"expandMsgTo96\",\n \"outputs\": [\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"domain\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"messages\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"hashToField\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"domain\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"message\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"hashToPoint\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"point\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"name\": \"isOnCurveG1\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"_isOnCurve\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"point\",\n \"type\": \"uint256[4]\"\n }\n ],\n \"name\": \"isOnCurveG2\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"_isOnCurve\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"name\": \"isValidSignature\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"_x\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mapToPoint\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"p\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256[4][]\",\n \"name\": \"pubkeys\",\n \"type\": \"uint256[4][]\"\n },\n {\n \"internalType\": \"uint256[2][]\",\n \"name\": \"messages\",\n \"type\": \"uint256[2][]\"\n }\n ],\n \"name\": \"verifyMultiple\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"checkResult\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"callSuccess\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256[4][]\",\n \"name\": \"pubkeys\",\n \"type\": \"uint256[4][]\"\n },\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"message\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"name\": \"verifyMultipleSameMsg\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"checkResult\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"callSuccess\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"pubkey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"message\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"name\": \"verifySingle\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612df8806100206000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806391ec2d2b1161006657806391ec2d2b1461013b578063a850a9091461015b578063d58e77331461016e578063e242cce914610181578063ebbdac911461019457600080fd5b8063115000fe146100a3578063247dd9fb146100cb5780633e5476ce146100de5780638669026f146101085780639141376314610128575b600080fd5b6100b66100b1366004612708565b6101a7565b60405190151581526020015b60405180910390f35b6100b66100d9366004612785565b61030e565b6100f16100ec366004612841565b6103b8565b6040805192151583529015156020830152016100c2565b61011b6101163660046128ce565b61079f565b6040516100c29190612957565b6100f1610136366004612988565b6108bb565b61014e6101493660046128ce565b610d5c565b6040516100c29190612a86565b61011b6101693660046128ce565b610ff8565b61011b61017c366004612aa0565b6111d4565b6100b661018f366004612785565b6115aa565b6100f16101a2366004612ab9565b611609565b600081516020830151600080516020612d63833981519152828309600080516020612d638339815191528283098182830101600080516020612d638339815191528283840108600080516020612d638339815191528682600080516020612d6383398151915203860109935050600080516020612d638339815191528483600080516020612d63833981519152038301099150600080516020612d638339815191527f2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e584089450600080516020612d638339815191527e9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2830893506040870151925060608701519150600080516020612d638339815191528083600080516020612d63833981519152038508600080516020612d63833981519152848608099050600080516020612d63833981519152828460011b0994149290931491909116949350505050565b8051600090600080516020612d6383398151915211158061034157506020820151600080516020612d6383398151915211155b1561034e57506000919050565b60405163e242cce960e01b8152309063e242cce990610371908590600401612957565b602060405180830381865afa15801561038e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b29190612b1c565b92915050565b60008083806103e25760405162461bcd60e51b81526004016103d990612b3e565b60405180910390fd5b60006103ef826001612b95565b6103fa906006612ba8565b90506000816001600160401b038111156104165761041661269a565b60405190808252806020026020018201604052801561043f578160200160208202803683370190505b50905088600060200201358160008151811061045d5761045d612b06565b602090810291909101015288600160200201358160018151811061048357610483612b06565b602002602001018181525050600080516020612d43833981519152816002815181106104b1576104b1612b06565b602002602001018181525050600080516020612d23833981519152816003815181106104df576104df612b06565b602002602001018181525050600080516020612d838339815191528160048151811061050d5761050d612b06565b602002602001018181525050600080516020612da38339815191528160058151811061053b5761053b612b06565b60200260200101818152505060005b8381101561075a57863582610560836006612ba8565b61056b906006612b95565b8151811061057b5761057b612b06565b602090810291909101015286600160200201358261059a836006612ba8565b6105a5906007612b95565b815181106105b5576105b5612b06565b6020026020010181815250508888828181106105d3576105d3612b06565b9050608002016001600481106105eb576105eb612b06565b6020020135826105fc836006612ba8565b610607906008612b95565b8151811061061757610617612b06565b60200260200101818152505088888281811061063557610635612b06565b90506080020160006004811061064d5761064d612b06565b60200201358261065e836006612ba8565b610669906009612b95565b8151811061067957610679612b06565b60200260200101818152505088888281811061069757610697612b06565b9050608002016003600481106106af576106af612b06565b6020020135826106c0836006612ba8565b6106cb90600a612b95565b815181106106db576106db612b06565b6020026020010181815250508888828181106106f9576106f9612b06565b90506080020160026004811061071157610711612b06565b602002013582610722836006612ba8565b61072d90600b612b95565b8151811061073d5761073d612b06565b60209081029190910101528061075281612bbf565b91505061054a565b50610763612640565b602081602085026020850160085afa945084610789576000809550955050505050610796565b5115159450600193505050505b94509492505050565b6107a761265e565b6040516391ec2d2b60e01b815260009030906391ec2d2b906107cf9087908790600401612bd8565b600060405180830381865afa1580156107ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108149190810190612bf9565b9050600080600080601885016001600160c01b0381511693506030860190506001600160c01b038151169450600080516020612d6383398151915285600080516020612d63833981519152600160c01b870908604887015160608801516001600160c01b0390811697501694509250600080516020612d6383398151915290508481600160c01b860908604080518082019091529283526020830152509695505050505050565b60008084806108dc5760405162461bcd60e51b81526004016103d990612b3e565b8084146109495760405162461bcd60e51b815260206004820152603560248201527f424c533a206e756d626572206f66207075626c6963206b65797320616e64206d604482015274195cdcd859d95cc81b5d5cdd08189948195c5d585b605a1b60648201526084016103d9565b6000610956826001612b95565b610961906006612ba8565b90506000816001600160401b0381111561097d5761097d61269a565b6040519080825280602002602001820160405280156109a6578160200160208202803683370190505b5090508960006020020135816000815181106109c4576109c4612b06565b60209081029190910101528960016020020135816001815181106109ea576109ea612b06565b602002602001018181525050600080516020612d4383398151915281600281518110610a1857610a18612b06565b602002602001018181525050600080516020612d2383398151915281600381518110610a4657610a46612b06565b602002602001018181525050600080516020612d8383398151915281600481518110610a7457610a74612b06565b602002602001018181525050600080516020612da383398151915281600581518110610aa257610aa2612b06565b60200260200101818152505060005b83811015610d1657878782818110610acb57610acb612b06565b905060400201600060028110610ae357610ae3612b06565b602002013582610af4836006612ba8565b610aff906006612b95565b81518110610b0f57610b0f612b06565b602002602001018181525050878782818110610b2d57610b2d612b06565b905060400201600160028110610b4557610b45612b06565b602002013582610b56836006612ba8565b610b61906007612b95565b81518110610b7157610b71612b06565b602002602001018181525050898982818110610b8f57610b8f612b06565b905060800201600160048110610ba757610ba7612b06565b602002013582610bb8836006612ba8565b610bc3906008612b95565b81518110610bd357610bd3612b06565b602002602001018181525050898982818110610bf157610bf1612b06565b905060800201600060048110610c0957610c09612b06565b602002013582610c1a836006612ba8565b610c25906009612b95565b81518110610c3557610c35612b06565b602002602001018181525050898982818110610c5357610c53612b06565b905060800201600360048110610c6b57610c6b612b06565b602002013582610c7c836006612ba8565b610c8790600a612b95565b81518110610c9757610c97612b06565b602002602001018181525050898982818110610cb557610cb5612b06565b905060800201600260048110610ccd57610ccd612b06565b602002013582610cde836006612ba8565b610ce990600b612b95565b81518110610cf957610cf9612b06565b602090810291909101015280610d0e81612bbf565b915050610ab1565b50610d1f612640565b602081602085026020850160085afa945084610d45576000809550955050505050610d52565b5115159450600193505050505b9550959350505050565b80516060906000610d6e826020612b95565b610d79906040612b95565b610d84906004612b95565b6001600160401b03811115610d9b57610d9b61269a565b6040519080825280601f01601f191660200182016040528015610dc5576020820181803683370190505b5060408051606080825260808201909252919250600091906020820181803683370190505090506060820160005b84811015610e0d5760208188018101518383015201610df3565b5083016000815360010160608153600101600081536001810187905260210160208153506000600283604051610e439190612c6f565b602060405180830381855afa158015610e60573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610e839190612c8b565b9050600060429450848452816020850152600160408501536041840188905260206061850153600284604051610eb99190612c6f565b602060405180830381855afa158015610ed6573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610ef99190612c8b565b905080602084015280821880602086015250600260408501536041840188905260206061850153600284604051610f309190612c6f565b602060405180830381855afa158015610f4d573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610f709190612c8b565b905080604084015280821880602086015250600360408501536041840188905260206061850153600284604051610fa79190612c6f565b602060405180830381855afa158015610fc4573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610fe79190612c8b565b606084015250909695505050505050565b61100061265e565b604051638669026f60e01b81526000903090638669026f906110289087908790600401612bd8565b6040805180830381865afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110689190612ca4565b805160405163d58e773360e01b81526004810191909152909150600090309063d58e7733906024016040805180830381865afa1580156110ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d09190612ca4565b602083015160405163d58e773360e01b81526004810191909152909150600090309063d58e7733906024016040805180830381865afa158015611117573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113b9190612ca4565b905061114561267c565b825181526020808401518282015282516040808401919091529083015160608301526000908460808460066107d05a03fa9050808061118057fe5b50806111c85760405162461bcd60e51b8152602060048201526017602482015276109314ce88189b881859190818d85b1b0819985a5b1959604a1b60448201526064016103d9565b50919695505050505050565b6111dc61265e565b600080516020612d6383398151915282106112455760405162461bcd60e51b815260206004820152602360248201527f6d6170546f506f696e7446543a20696e76616c6964206669656c6420656c656d604482015262195b9d60ea1b60648201526084016103d9565b81600061125182611790565b9150506000600080516020612d638339815191528061127257611272612cf9565b8384099050600080516020612d638339815191526004820890506000600080516020612d6383398151915277b3c4d79d41a91759a9e4c7e359b6b89eaec68e62effffffd850990506000600080516020612d6383398151915283830990506112d9816117b9565b9050600080516020612d638339815191528283099150600080516020612d638339815191528183099150600080516020612d638339815191528286099150600080516020612d6383398151915261133e83600080516020612d63833981519152612d0f565b7759e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe089450600080516020612d638339815191528586099150600080516020612d638339815191528583099150600080516020612d6383398151915260038308915060006113a283611790565b909350905080156113ea57846113cd576113ca83600080516020612d63833981519152612d0f565b92505b505060408051808201909152938452602084015250909392505050565b600080516020612d638339815191526001870861141590600080516020612d63833981519152612d0f565b9550600080516020612d638339815191528687099250600080516020612d638339815191528684099250600080516020612d6383398151915260038408925061145d83611790565b9093509050801561148557846113cd576113ca83600080516020612d63833981519152612d0f565b600080516020612d638339815191528485099550600080516020612d638339815191528687099550600080516020612d638339815191528287099550600080516020612d638339815191528287099550600080516020612d63833981519152600187089550600080516020612d638339815191528687099250600080516020612d638339815191528684099250600080516020612d6383398151915260038408925061153083611790565b90935090508061158d5760405162461bcd60e51b815260206004820152602260248201527f424c533a20626164206674206d617070696e6720696d706c656d656e7461746960448201526137b760f11b60648201526084016103d9565b846113cd576113ca83600080516020612d63833981519152612d0f565b600081516020830151600080516020612d63833981519152828309600080516020612d638339815191528382099050600080516020612d63833981519152600382089050600080516020612d6383398151915282830914949350505050565b60008060006040518061018001604052808760006002811061162d5761162d612b06565b602002013581526020018760016002811061164a5761164a612b06565b60200201358152602001600080516020612d438339815191528152602001600080516020612d238339815191528152602001600080516020612d838339815191528152602001600080516020612da38339815191528152602001856000600281106116b7576116b7612b06565b60200201358152602001856001600281106116d4576116d4612b06565b60200201358152602001866001600481106116f1576116f1612b06565b602002013581526020018660006004811061170e5761170e612b06565b602002013581526020018660036004811061172b5761172b612b06565b602002013581526020018660026004811061174857611748612b06565b602002013590529050611759612640565b60006020826101808560085afa90508061177c5760008094509450505050611788565b50511515925060019150505b935093915050565b60008061179c836117c4565b915082600080516020612d63833981519152838409149050915091565b60006103b282611ef9565b6000600080516020612d638339815191528083840991508083830981838209828283098385830984848309858484098684850997508684840987858409945087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087838a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985050868889099750868889099750868889099750868889099750868889099750868889099750868489099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868689099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868189099750508587880996508587880996508587880996508585880996508587880996508587880996508587880996508585880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508587880996508581880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508584880996508587880996508587880996508587880996508587880996508587880996508581880996505050505050808283099392505050565b6000600080516020612d638339815191528083840991508083830981838209828283098385830984848309858484098684850997508684840987858409945087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087838a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985050868889099750868889099750868889099750868889099750868889099750868889099750868489099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868689099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868189099750508587880996508587880996508587880996508585880996508587880996508587880996508587880996508585880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508587880996508581880996505050838586099450838586099450838586099450838586099450838186099450508284850993508284850993508284850993508281850993508284850993508284850993508285850993508284850993508284850993508284850993508284850993508284850993508284850993508281850995945050505050565b60405180602001604052806001906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156126d2576126d261269a565b60405290565b604051601f8201601f191681016001600160401b03811182821017156127005761270061269a565b604052919050565b60006080828403121561271a57600080fd5b82601f83011261272957600080fd5b604051608081018181106001600160401b038211171561274b5761274b61269a565b60405280608084018581111561276057600080fd5b845b8181101561277a578035835260209283019201612762565b509195945050505050565b60006040828403121561279757600080fd5b82601f8301126127a657600080fd5b6127ae6126b0565b8060408401858111156127c057600080fd5b845b818110156127da5780358452602093840193016127c2565b509095945050505050565b80604081018310156103b257600080fd5b60008083601f84011261280857600080fd5b5081356001600160401b0381111561281f57600080fd5b6020830191508360208260071b850101111561283a57600080fd5b9250929050565b60008060008060a0858703121561285757600080fd5b61286186866127e5565b935060408501356001600160401b0381111561287c57600080fd5b612888878288016127f6565b909450925061289c905086606087016127e5565b905092959194509250565b60006001600160401b038211156128c0576128c061269a565b50601f01601f191660200190565b600080604083850312156128e157600080fd5b8235915060208301356001600160401b038111156128fe57600080fd5b8301601f8101851361290f57600080fd5b803561292261291d826128a7565b6126d8565b81815286602083850101111561293757600080fd5b816020840160208301376000602083830101528093505050509250929050565b60408101818360005b600281101561297f578151835260209283019290910190600101612960565b50505092915050565b6000806000806000608086880312156129a057600080fd5b6129aa87876127e5565b945060408601356001600160401b03808211156129c657600080fd5b6129d289838a016127f6565b909650945060608801359150808211156129eb57600080fd5b818801915088601f8301126129ff57600080fd5b813581811115612a0e57600080fd5b8960208260061b8501011115612a2357600080fd5b9699959850939650602001949392505050565b60005b83811015612a51578181015183820152602001612a39565b50506000910152565b60008151808452612a72816020860160208601612a36565b601f01601f19169290920160200192915050565b602081526000612a996020830184612a5a565b9392505050565b600060208284031215612ab257600080fd5b5035919050565b60008060006101008486031215612acf57600080fd5b612ad985856127e5565b925060c0840185811115612aec57600080fd5b604085019250612afc86826127e5565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612b2e57600080fd5b81518015158114612a9957600080fd5b60208082526021908201527f424c533a206e756d626572206f66207075626c6963206b6579206973207a65726040820152606f60f81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b808201808211156103b2576103b2612b7f565b80820281158282048414176103b2576103b2612b7f565b600060018201612bd157612bd1612b7f565b5060010190565b828152604060208201526000612bf16040830184612a5a565b949350505050565b600060208284031215612c0b57600080fd5b81516001600160401b03811115612c2157600080fd5b8201601f81018413612c3257600080fd5b8051612c4061291d826128a7565b818152856020838501011115612c5557600080fd5b612c66826020830160208601612a36565b95945050505050565b60008251612c81818460208701612a36565b9190910192915050565b600060208284031215612c9d57600080fd5b5051919050565b600060408284031215612cb657600080fd5b82601f830112612cc557600080fd5b612ccd6126b0565b806040840185811115612cdf57600080fd5b845b818110156127da578051845260209384019301612ce1565b634e487b7160e01b600052601260045260246000fd5b818103818111156103b2576103b2612b7f56fe1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9da264697066735822122026307d7712f2d905c1e8d78be9a5b3a609a6d61f5bdebb114a32bfdb7fdfb8ce64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061009e5760003560e01c806391ec2d2b1161006657806391ec2d2b1461013b578063a850a9091461015b578063d58e77331461016e578063e242cce914610181578063ebbdac911461019457600080fd5b8063115000fe146100a3578063247dd9fb146100cb5780633e5476ce146100de5780638669026f146101085780639141376314610128575b600080fd5b6100b66100b1366004612708565b6101a7565b60405190151581526020015b60405180910390f35b6100b66100d9366004612785565b61030e565b6100f16100ec366004612841565b6103b8565b6040805192151583529015156020830152016100c2565b61011b6101163660046128ce565b61079f565b6040516100c29190612957565b6100f1610136366004612988565b6108bb565b61014e6101493660046128ce565b610d5c565b6040516100c29190612a86565b61011b6101693660046128ce565b610ff8565b61011b61017c366004612aa0565b6111d4565b6100b661018f366004612785565b6115aa565b6100f16101a2366004612ab9565b611609565b600081516020830151600080516020612d63833981519152828309600080516020612d638339815191528283098182830101600080516020612d638339815191528283840108600080516020612d638339815191528682600080516020612d6383398151915203860109935050600080516020612d638339815191528483600080516020612d63833981519152038301099150600080516020612d638339815191527f2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e584089450600080516020612d638339815191527e9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2830893506040870151925060608701519150600080516020612d638339815191528083600080516020612d63833981519152038508600080516020612d63833981519152848608099050600080516020612d63833981519152828460011b0994149290931491909116949350505050565b8051600090600080516020612d6383398151915211158061034157506020820151600080516020612d6383398151915211155b1561034e57506000919050565b60405163e242cce960e01b8152309063e242cce990610371908590600401612957565b602060405180830381865afa15801561038e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b29190612b1c565b92915050565b60008083806103e25760405162461bcd60e51b81526004016103d990612b3e565b60405180910390fd5b60006103ef826001612b95565b6103fa906006612ba8565b90506000816001600160401b038111156104165761041661269a565b60405190808252806020026020018201604052801561043f578160200160208202803683370190505b50905088600060200201358160008151811061045d5761045d612b06565b602090810291909101015288600160200201358160018151811061048357610483612b06565b602002602001018181525050600080516020612d43833981519152816002815181106104b1576104b1612b06565b602002602001018181525050600080516020612d23833981519152816003815181106104df576104df612b06565b602002602001018181525050600080516020612d838339815191528160048151811061050d5761050d612b06565b602002602001018181525050600080516020612da38339815191528160058151811061053b5761053b612b06565b60200260200101818152505060005b8381101561075a57863582610560836006612ba8565b61056b906006612b95565b8151811061057b5761057b612b06565b602090810291909101015286600160200201358261059a836006612ba8565b6105a5906007612b95565b815181106105b5576105b5612b06565b6020026020010181815250508888828181106105d3576105d3612b06565b9050608002016001600481106105eb576105eb612b06565b6020020135826105fc836006612ba8565b610607906008612b95565b8151811061061757610617612b06565b60200260200101818152505088888281811061063557610635612b06565b90506080020160006004811061064d5761064d612b06565b60200201358261065e836006612ba8565b610669906009612b95565b8151811061067957610679612b06565b60200260200101818152505088888281811061069757610697612b06565b9050608002016003600481106106af576106af612b06565b6020020135826106c0836006612ba8565b6106cb90600a612b95565b815181106106db576106db612b06565b6020026020010181815250508888828181106106f9576106f9612b06565b90506080020160026004811061071157610711612b06565b602002013582610722836006612ba8565b61072d90600b612b95565b8151811061073d5761073d612b06565b60209081029190910101528061075281612bbf565b91505061054a565b50610763612640565b602081602085026020850160085afa945084610789576000809550955050505050610796565b5115159450600193505050505b94509492505050565b6107a761265e565b6040516391ec2d2b60e01b815260009030906391ec2d2b906107cf9087908790600401612bd8565b600060405180830381865afa1580156107ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108149190810190612bf9565b9050600080600080601885016001600160c01b0381511693506030860190506001600160c01b038151169450600080516020612d6383398151915285600080516020612d63833981519152600160c01b870908604887015160608801516001600160c01b0390811697501694509250600080516020612d6383398151915290508481600160c01b860908604080518082019091529283526020830152509695505050505050565b60008084806108dc5760405162461bcd60e51b81526004016103d990612b3e565b8084146109495760405162461bcd60e51b815260206004820152603560248201527f424c533a206e756d626572206f66207075626c6963206b65797320616e64206d604482015274195cdcd859d95cc81b5d5cdd08189948195c5d585b605a1b60648201526084016103d9565b6000610956826001612b95565b610961906006612ba8565b90506000816001600160401b0381111561097d5761097d61269a565b6040519080825280602002602001820160405280156109a6578160200160208202803683370190505b5090508960006020020135816000815181106109c4576109c4612b06565b60209081029190910101528960016020020135816001815181106109ea576109ea612b06565b602002602001018181525050600080516020612d4383398151915281600281518110610a1857610a18612b06565b602002602001018181525050600080516020612d2383398151915281600381518110610a4657610a46612b06565b602002602001018181525050600080516020612d8383398151915281600481518110610a7457610a74612b06565b602002602001018181525050600080516020612da383398151915281600581518110610aa257610aa2612b06565b60200260200101818152505060005b83811015610d1657878782818110610acb57610acb612b06565b905060400201600060028110610ae357610ae3612b06565b602002013582610af4836006612ba8565b610aff906006612b95565b81518110610b0f57610b0f612b06565b602002602001018181525050878782818110610b2d57610b2d612b06565b905060400201600160028110610b4557610b45612b06565b602002013582610b56836006612ba8565b610b61906007612b95565b81518110610b7157610b71612b06565b602002602001018181525050898982818110610b8f57610b8f612b06565b905060800201600160048110610ba757610ba7612b06565b602002013582610bb8836006612ba8565b610bc3906008612b95565b81518110610bd357610bd3612b06565b602002602001018181525050898982818110610bf157610bf1612b06565b905060800201600060048110610c0957610c09612b06565b602002013582610c1a836006612ba8565b610c25906009612b95565b81518110610c3557610c35612b06565b602002602001018181525050898982818110610c5357610c53612b06565b905060800201600360048110610c6b57610c6b612b06565b602002013582610c7c836006612ba8565b610c8790600a612b95565b81518110610c9757610c97612b06565b602002602001018181525050898982818110610cb557610cb5612b06565b905060800201600260048110610ccd57610ccd612b06565b602002013582610cde836006612ba8565b610ce990600b612b95565b81518110610cf957610cf9612b06565b602090810291909101015280610d0e81612bbf565b915050610ab1565b50610d1f612640565b602081602085026020850160085afa945084610d45576000809550955050505050610d52565b5115159450600193505050505b9550959350505050565b80516060906000610d6e826020612b95565b610d79906040612b95565b610d84906004612b95565b6001600160401b03811115610d9b57610d9b61269a565b6040519080825280601f01601f191660200182016040528015610dc5576020820181803683370190505b5060408051606080825260808201909252919250600091906020820181803683370190505090506060820160005b84811015610e0d5760208188018101518383015201610df3565b5083016000815360010160608153600101600081536001810187905260210160208153506000600283604051610e439190612c6f565b602060405180830381855afa158015610e60573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610e839190612c8b565b9050600060429450848452816020850152600160408501536041840188905260206061850153600284604051610eb99190612c6f565b602060405180830381855afa158015610ed6573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610ef99190612c8b565b905080602084015280821880602086015250600260408501536041840188905260206061850153600284604051610f309190612c6f565b602060405180830381855afa158015610f4d573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610f709190612c8b565b905080604084015280821880602086015250600360408501536041840188905260206061850153600284604051610fa79190612c6f565b602060405180830381855afa158015610fc4573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610fe79190612c8b565b606084015250909695505050505050565b61100061265e565b604051638669026f60e01b81526000903090638669026f906110289087908790600401612bd8565b6040805180830381865afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110689190612ca4565b805160405163d58e773360e01b81526004810191909152909150600090309063d58e7733906024016040805180830381865afa1580156110ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d09190612ca4565b602083015160405163d58e773360e01b81526004810191909152909150600090309063d58e7733906024016040805180830381865afa158015611117573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113b9190612ca4565b905061114561267c565b825181526020808401518282015282516040808401919091529083015160608301526000908460808460066107d05a03fa9050808061118057fe5b50806111c85760405162461bcd60e51b8152602060048201526017602482015276109314ce88189b881859190818d85b1b0819985a5b1959604a1b60448201526064016103d9565b50919695505050505050565b6111dc61265e565b600080516020612d6383398151915282106112455760405162461bcd60e51b815260206004820152602360248201527f6d6170546f506f696e7446543a20696e76616c6964206669656c6420656c656d604482015262195b9d60ea1b60648201526084016103d9565b81600061125182611790565b9150506000600080516020612d638339815191528061127257611272612cf9565b8384099050600080516020612d638339815191526004820890506000600080516020612d6383398151915277b3c4d79d41a91759a9e4c7e359b6b89eaec68e62effffffd850990506000600080516020612d6383398151915283830990506112d9816117b9565b9050600080516020612d638339815191528283099150600080516020612d638339815191528183099150600080516020612d638339815191528286099150600080516020612d6383398151915261133e83600080516020612d63833981519152612d0f565b7759e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe089450600080516020612d638339815191528586099150600080516020612d638339815191528583099150600080516020612d6383398151915260038308915060006113a283611790565b909350905080156113ea57846113cd576113ca83600080516020612d63833981519152612d0f565b92505b505060408051808201909152938452602084015250909392505050565b600080516020612d638339815191526001870861141590600080516020612d63833981519152612d0f565b9550600080516020612d638339815191528687099250600080516020612d638339815191528684099250600080516020612d6383398151915260038408925061145d83611790565b9093509050801561148557846113cd576113ca83600080516020612d63833981519152612d0f565b600080516020612d638339815191528485099550600080516020612d638339815191528687099550600080516020612d638339815191528287099550600080516020612d638339815191528287099550600080516020612d63833981519152600187089550600080516020612d638339815191528687099250600080516020612d638339815191528684099250600080516020612d6383398151915260038408925061153083611790565b90935090508061158d5760405162461bcd60e51b815260206004820152602260248201527f424c533a20626164206674206d617070696e6720696d706c656d656e7461746960448201526137b760f11b60648201526084016103d9565b846113cd576113ca83600080516020612d63833981519152612d0f565b600081516020830151600080516020612d63833981519152828309600080516020612d638339815191528382099050600080516020612d63833981519152600382089050600080516020612d6383398151915282830914949350505050565b60008060006040518061018001604052808760006002811061162d5761162d612b06565b602002013581526020018760016002811061164a5761164a612b06565b60200201358152602001600080516020612d438339815191528152602001600080516020612d238339815191528152602001600080516020612d838339815191528152602001600080516020612da38339815191528152602001856000600281106116b7576116b7612b06565b60200201358152602001856001600281106116d4576116d4612b06565b60200201358152602001866001600481106116f1576116f1612b06565b602002013581526020018660006004811061170e5761170e612b06565b602002013581526020018660036004811061172b5761172b612b06565b602002013581526020018660026004811061174857611748612b06565b602002013590529050611759612640565b60006020826101808560085afa90508061177c5760008094509450505050611788565b50511515925060019150505b935093915050565b60008061179c836117c4565b915082600080516020612d63833981519152838409149050915091565b60006103b282611ef9565b6000600080516020612d638339815191528083840991508083830981838209828283098385830984848309858484098684850997508684840987858409945087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087838a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985050868889099750868889099750868889099750868889099750868889099750868889099750868489099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868689099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868189099750508587880996508587880996508587880996508585880996508587880996508587880996508587880996508585880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508587880996508581880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508584880996508587880996508587880996508587880996508587880996508587880996508581880996505050505050808283099392505050565b6000600080516020612d638339815191528083840991508083830981838209828283098385830984848309858484098684850997508684840987858409945087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087838a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985050868889099750868889099750868889099750868889099750868889099750868889099750868489099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868689099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868189099750508587880996508587880996508587880996508585880996508587880996508587880996508587880996508585880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508587880996508581880996505050838586099450838586099450838586099450838586099450838186099450508284850993508284850993508284850993508281850993508284850993508284850993508285850993508284850993508284850993508284850993508284850993508284850993508284850993508281850995945050505050565b60405180602001604052806001906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156126d2576126d261269a565b60405290565b604051601f8201601f191681016001600160401b03811182821017156127005761270061269a565b604052919050565b60006080828403121561271a57600080fd5b82601f83011261272957600080fd5b604051608081018181106001600160401b038211171561274b5761274b61269a565b60405280608084018581111561276057600080fd5b845b8181101561277a578035835260209283019201612762565b509195945050505050565b60006040828403121561279757600080fd5b82601f8301126127a657600080fd5b6127ae6126b0565b8060408401858111156127c057600080fd5b845b818110156127da5780358452602093840193016127c2565b509095945050505050565b80604081018310156103b257600080fd5b60008083601f84011261280857600080fd5b5081356001600160401b0381111561281f57600080fd5b6020830191508360208260071b850101111561283a57600080fd5b9250929050565b60008060008060a0858703121561285757600080fd5b61286186866127e5565b935060408501356001600160401b0381111561287c57600080fd5b612888878288016127f6565b909450925061289c905086606087016127e5565b905092959194509250565b60006001600160401b038211156128c0576128c061269a565b50601f01601f191660200190565b600080604083850312156128e157600080fd5b8235915060208301356001600160401b038111156128fe57600080fd5b8301601f8101851361290f57600080fd5b803561292261291d826128a7565b6126d8565b81815286602083850101111561293757600080fd5b816020840160208301376000602083830101528093505050509250929050565b60408101818360005b600281101561297f578151835260209283019290910190600101612960565b50505092915050565b6000806000806000608086880312156129a057600080fd5b6129aa87876127e5565b945060408601356001600160401b03808211156129c657600080fd5b6129d289838a016127f6565b909650945060608801359150808211156129eb57600080fd5b818801915088601f8301126129ff57600080fd5b813581811115612a0e57600080fd5b8960208260061b8501011115612a2357600080fd5b9699959850939650602001949392505050565b60005b83811015612a51578181015183820152602001612a39565b50506000910152565b60008151808452612a72816020860160208601612a36565b601f01601f19169290920160200192915050565b602081526000612a996020830184612a5a565b9392505050565b600060208284031215612ab257600080fd5b5035919050565b60008060006101008486031215612acf57600080fd5b612ad985856127e5565b925060c0840185811115612aec57600080fd5b604085019250612afc86826127e5565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612b2e57600080fd5b81518015158114612a9957600080fd5b60208082526021908201527f424c533a206e756d626572206f66207075626c6963206b6579206973207a65726040820152606f60f81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b808201808211156103b2576103b2612b7f565b80820281158282048414176103b2576103b2612b7f565b600060018201612bd157612bd1612b7f565b5060010190565b828152604060208201526000612bf16040830184612a5a565b949350505050565b600060208284031215612c0b57600080fd5b81516001600160401b03811115612c2157600080fd5b8201601f81018413612c3257600080fd5b8051612c4061291d826128a7565b818152856020838501011115612c5557600080fd5b612c66826020830160208601612a36565b95945050505050565b60008251612c81818460208701612a36565b9190910192915050565b600060208284031215612c9d57600080fd5b5051919050565b600060408284031215612cb657600080fd5b82601f830112612cc557600080fd5b612ccd6126b0565b806040840185811115612cdf57600080fd5b845b818110156127da578051845260209384019301612ce1565b634e487b7160e01b600052601260045260246000fd5b818103818111156103b2576103b2612b7f56fe1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9da264697066735822122026307d7712f2d905c1e8d78be9a5b3a609a6d61f5bdebb114a32bfdb7fdfb8ce64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var BN256G2Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"BN256G2\",\n \"sourceName\": \"contracts/common/BN256G2.sol\",\n \"abi\": [\n {\n \"inputs\": [],\n \"name\": \"G2_NEG_X_IM\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"G2_NEG_X_RE\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"G2_NEG_Y_IM\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"G2_NEG_Y_RE\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1xx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1xy\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1yx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1yy\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt2xx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt2xy\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt2yx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt2yy\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ecTwistAdd\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"s\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1xx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1xy\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1yx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1yy\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ecTwistMul\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"getFieldModulus\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610dfd806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c80635120675214610072578063779d890d146100ac578063783bde80146100c05780639b0c399a146100e7578063ad50f9c11461010e578063cbe96a5014610135578063defbcdee14610168575b600080fd5b6100997f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d81565b6040519081526020015b60405180910390f35b600080516020610da8833981519152610099565b6100997f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c281565b6100997f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed81565b6100997f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec81565b610148610143366004610c8c565b61017b565b6040805194855260208501939093529183015260608201526080016100a3565b610148610176366004610ce1565b61031a565b60008080808b15801561018c57508a155b8015610196575089155b80156101a0575088155b1561020a57871580156101b1575086155b80156101bb575085155b80156101c5575084155b6101fa576101d5888888886103b1565b6101fa5760405162461bcd60e51b81526004016101f190610d1c565b60405180910390fd5b508692508591508490508361030b565b87158015610216575086155b8015610220575085155b801561022a575084155b156102675761023b8c8c8c8c6103b1565b6102575760405162461bcd60e51b81526004016101f190610d1c565b508a92508991508890508761030b565b6102738c8c8c8c6103b1565b61028f5760405162461bcd60e51b81526004016101f190610d1c565b61029b888888886103b1565b6102b75760405162461bcd60e51b81526004016101f190610d1c565b60006102d18d8d8d8d600160008f8f8f8f60016000610466565b90506103018160005b602090810291909101519083015160408401516060850151608086015160a08701516106f1565b9450945094509450505b98509850985098945050505050565b600080808060018815801561032d575087155b8015610337575086155b8015610341575085155b15610355575060019750879550600061037d565b610361898989896103b1565b61037d5760405162461bcd60e51b81526004016101f190610d1c565b600061038f8b8b8b8b8b87600061075c565b905061039c8160006102da565b929e919d509b50909950975050505050505050565b60008060008060006103c5878789896107df565b90945092506103d6898981816107df565b90925090506103e782828b8b6107df565b90925090506103f884848484610850565b909450925061044884847f2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e57e9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2610850565b909450925083158015610459575082155b9998505050505050505050565b61046e610c50565b8815801561047a575087155b156104bc578686868686868660005b60a089019290925260808801929092526060870192909252604086019290925260208581019390935290910201526106e1565b821580156104c8575081155b156104db578c8c8c8c8c8c866000610489565b6104e785858b8b6107df565b90955093506104f88b8b85856107df565b6060830152604082015261050e87878b8b6107df565b909750955061051f8d8d85856107df565b60a0830152608082018190528714801561053c575060a081015186145b15610581576040810151851480156105575750606081015184145b156105725761056a8d8d8d8d8d8d610892565b866000610489565b60016000818180808681610489565b61058d898985856107df565b90935091506105ad858583600260200201518460035b6020020151610850565b909d509b506105c887878360045b60200201518460056105a3565b909b5099506105d98b8b81816107df565b90995097506105fa89898360045b60200201518460055b60200201516107df565b909550935061060b89898d8d6107df565b909950975061061c898985856107df565b60a083015260808201526106328d8d81816107df565b9097509550610643878785856107df565b909750955061065487878b8b610850565b909750955061066585856002610ada565b909350915061067687878585610850565b90975095506106878b8b89896107df565b6020830152815261069a85858989610850565b909b5099506106ab8d8d8d8d6107df565b909b5099506106c5898983600260200201518460036105f0565b909d509b506106d68b8b8f8f610850565b606083015260408201525b9c9b505050505050505050505050565b600080600080600080610702610c6e565b61070c8989610b0d565b909350915061071d8d8d85856107df565b602083015281526107308b8b85856107df565b60608301819052604083018290528251602090930151929f929e50909c509a5098505050505050505050565b610764610c50565b87156107d45760018816156107a5578051602082015160408301516060840151608085015160a08601516107a29594939291908d8d8d8d8d8d610466565b90505b6107b3878787878787610892565b949b509299509097509550935091506107cd600289610d5e565b9750610764565b979650505050505050565b60008061081d600080516020610da8833981519152858809600080516020610da8833981519152858809600080516020610da8833981519152610b98565b600080516020610da883398151915280868809600080516020610da8833981519152868a09089150915094509492505050565b60008061086c8685600080516020610da8833981519152610b98565b6108858685600080516020610da8833981519152610b98565b9150915094509492505050565b6000806000806000806108a3610c50565b6108af8d8d6003610ada565b602083018190528183526108c591908f8f6107df565b602083015281526108d88b8b8b8b6107df565b90995097506108e98d8d8d8d6107df565b606083015260408201819052610909908260035b60200201518b8b6107df565b60608301526040820152805161092c908260015b602002015183518460016105f0565b6040830151919e509c5061094a908260035b60200201516008610ada565b60a083015260808201526109618d8d8360046105bb565b909d509b50610972898981816107df565b60a083015260808201526040810151606082015161099291906004610ada565b60608301819052604083018290526109ac91908f8f610850565b6060830152604082018190526109c49082600361091d565b606083015260408201526109da8b8b6008610ada565b602083018190528183526109f091908d8d6107df565b60208301819052818352610a0791908360046105e7565b602083015280825260408201516060830151610a25928460016105a3565b60608301526040820152610a3b8d8d6002610ada565b6020830152808252610a4f908260016108fd565b60208301528152610a6389898360046105e7565b60a083015260808201819052610a7b9082600561093e565b826004602002018360056020020191909152528060006020020151816001602002015182600260200201518360036020020151846004602002015185600560200201519650965096509650965096505096509650965096509650969050565b600080600080516020610da8833981519152838609600080516020610da883398151915284860991509150935093915050565b60008080610b4e600080516020610da883398151915280878809600080516020610da883398151915287880908600080516020610da8833981519152610bbc565b9050600080516020610da8833981519152818609600080516020610da8833981519152828609610b8c90600080516020610da8833981519152610d80565b92509250509250929050565b60008180610ba857610ba8610d48565b610bb28484610d80565b8508949350505050565b60008060405160208152602080820152602060408201528460608201526002840360808201528360a082015260208160c08360056107d05a03fa90519250905080610c495760405162461bcd60e51b815260206004820152601a60248201527f6572726f722077697468206d6f64756c617220696e766572736500000000000060448201526064016101f1565b5092915050565b6040518060c001604052806006906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b600080600080600080600080610100898b031215610ca957600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b600080600080600060a08688031215610cf957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b602080825260129082015271706f696e74206e6f7420696e20637572766560701b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082610d7b57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610da157634e487b7160e01b600052601160045260246000fd5b9291505056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47a2646970667358221220bef62bc28068690954bff720632bf34d282621c8a9da6cc064b8d7b5b6d91bb564736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061006d5760003560e01c80635120675214610072578063779d890d146100ac578063783bde80146100c05780639b0c399a146100e7578063ad50f9c11461010e578063cbe96a5014610135578063defbcdee14610168575b600080fd5b6100997f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d81565b6040519081526020015b60405180910390f35b600080516020610da8833981519152610099565b6100997f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c281565b6100997f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed81565b6100997f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec81565b610148610143366004610c8c565b61017b565b6040805194855260208501939093529183015260608201526080016100a3565b610148610176366004610ce1565b61031a565b60008080808b15801561018c57508a155b8015610196575089155b80156101a0575088155b1561020a57871580156101b1575086155b80156101bb575085155b80156101c5575084155b6101fa576101d5888888886103b1565b6101fa5760405162461bcd60e51b81526004016101f190610d1c565b60405180910390fd5b508692508591508490508361030b565b87158015610216575086155b8015610220575085155b801561022a575084155b156102675761023b8c8c8c8c6103b1565b6102575760405162461bcd60e51b81526004016101f190610d1c565b508a92508991508890508761030b565b6102738c8c8c8c6103b1565b61028f5760405162461bcd60e51b81526004016101f190610d1c565b61029b888888886103b1565b6102b75760405162461bcd60e51b81526004016101f190610d1c565b60006102d18d8d8d8d600160008f8f8f8f60016000610466565b90506103018160005b602090810291909101519083015160408401516060850151608086015160a08701516106f1565b9450945094509450505b98509850985098945050505050565b600080808060018815801561032d575087155b8015610337575086155b8015610341575085155b15610355575060019750879550600061037d565b610361898989896103b1565b61037d5760405162461bcd60e51b81526004016101f190610d1c565b600061038f8b8b8b8b8b87600061075c565b905061039c8160006102da565b929e919d509b50909950975050505050505050565b60008060008060006103c5878789896107df565b90945092506103d6898981816107df565b90925090506103e782828b8b6107df565b90925090506103f884848484610850565b909450925061044884847f2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e57e9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2610850565b909450925083158015610459575082155b9998505050505050505050565b61046e610c50565b8815801561047a575087155b156104bc578686868686868660005b60a089019290925260808801929092526060870192909252604086019290925260208581019390935290910201526106e1565b821580156104c8575081155b156104db578c8c8c8c8c8c866000610489565b6104e785858b8b6107df565b90955093506104f88b8b85856107df565b6060830152604082015261050e87878b8b6107df565b909750955061051f8d8d85856107df565b60a0830152608082018190528714801561053c575060a081015186145b15610581576040810151851480156105575750606081015184145b156105725761056a8d8d8d8d8d8d610892565b866000610489565b60016000818180808681610489565b61058d898985856107df565b90935091506105ad858583600260200201518460035b6020020151610850565b909d509b506105c887878360045b60200201518460056105a3565b909b5099506105d98b8b81816107df565b90995097506105fa89898360045b60200201518460055b60200201516107df565b909550935061060b89898d8d6107df565b909950975061061c898985856107df565b60a083015260808201526106328d8d81816107df565b9097509550610643878785856107df565b909750955061065487878b8b610850565b909750955061066585856002610ada565b909350915061067687878585610850565b90975095506106878b8b89896107df565b6020830152815261069a85858989610850565b909b5099506106ab8d8d8d8d6107df565b909b5099506106c5898983600260200201518460036105f0565b909d509b506106d68b8b8f8f610850565b606083015260408201525b9c9b505050505050505050505050565b600080600080600080610702610c6e565b61070c8989610b0d565b909350915061071d8d8d85856107df565b602083015281526107308b8b85856107df565b60608301819052604083018290528251602090930151929f929e50909c509a5098505050505050505050565b610764610c50565b87156107d45760018816156107a5578051602082015160408301516060840151608085015160a08601516107a29594939291908d8d8d8d8d8d610466565b90505b6107b3878787878787610892565b949b509299509097509550935091506107cd600289610d5e565b9750610764565b979650505050505050565b60008061081d600080516020610da8833981519152858809600080516020610da8833981519152858809600080516020610da8833981519152610b98565b600080516020610da883398151915280868809600080516020610da8833981519152868a09089150915094509492505050565b60008061086c8685600080516020610da8833981519152610b98565b6108858685600080516020610da8833981519152610b98565b9150915094509492505050565b6000806000806000806108a3610c50565b6108af8d8d6003610ada565b602083018190528183526108c591908f8f6107df565b602083015281526108d88b8b8b8b6107df565b90995097506108e98d8d8d8d6107df565b606083015260408201819052610909908260035b60200201518b8b6107df565b60608301526040820152805161092c908260015b602002015183518460016105f0565b6040830151919e509c5061094a908260035b60200201516008610ada565b60a083015260808201526109618d8d8360046105bb565b909d509b50610972898981816107df565b60a083015260808201526040810151606082015161099291906004610ada565b60608301819052604083018290526109ac91908f8f610850565b6060830152604082018190526109c49082600361091d565b606083015260408201526109da8b8b6008610ada565b602083018190528183526109f091908d8d6107df565b60208301819052818352610a0791908360046105e7565b602083015280825260408201516060830151610a25928460016105a3565b60608301526040820152610a3b8d8d6002610ada565b6020830152808252610a4f908260016108fd565b60208301528152610a6389898360046105e7565b60a083015260808201819052610a7b9082600561093e565b826004602002018360056020020191909152528060006020020151816001602002015182600260200201518360036020020151846004602002015185600560200201519650965096509650965096505096509650965096509650969050565b600080600080516020610da8833981519152838609600080516020610da883398151915284860991509150935093915050565b60008080610b4e600080516020610da883398151915280878809600080516020610da883398151915287880908600080516020610da8833981519152610bbc565b9050600080516020610da8833981519152818609600080516020610da8833981519152828609610b8c90600080516020610da8833981519152610d80565b92509250509250929050565b60008180610ba857610ba8610d48565b610bb28484610d80565b8508949350505050565b60008060405160208152602080820152602060408201528460608201526002840360808201528360a082015260208160c08360056107d05a03fa90519250905080610c495760405162461bcd60e51b815260206004820152601a60248201527f6572726f722077697468206d6f64756c617220696e766572736500000000000060448201526064016101f1565b5092915050565b6040518060c001604052806006906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b600080600080600080600080610100898b031215610ca957600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b600080600080600060a08688031215610cf957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b602080825260129082015271706f696e74206e6f7420696e20637572766560701b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082610d7b57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610da157634e487b7160e01b600052601160045260246000fd5b9291505056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47a2646970667358221220bef62bc28068690954bff720632bf34d282621c8a9da6cc064b8d7b5b6d91bb564736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var MerkleArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"Merkle\",\n \"sourceName\": \"contracts/common/Merkle.sol\",\n \"abi\": [],\n \"bytecode\": \"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220fb95e4956e03415a17fac86b59ad7d42d699865638cab948804a84759122547a64736f6c63430008110033\",\n \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220fb95e4956e03415a17fac86b59ad7d42d699865638cab948804a84759122547a64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var CheckpointManagerArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"CheckpointManager\",\n \"sourceName\": \"contracts/root/CheckpointManager.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DOMAIN\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"bls\",\n \"outputs\": [\n {\n \"internalType\": \"contract IBLS\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"bn256G2\",\n \"outputs\": [\n {\n \"internalType\": \"contract IBN256G2\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"chainId\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"checkpointBlockNumbers\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"checkpoints\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"eventRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentCheckpointBlockNumber\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentEpoch\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"currentValidatorSet\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentValidatorSetHash\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentValidatorSetLength\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getCheckpointBlock\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"leaf\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"getEventMembershipByBlockNumber\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"leaf\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"getEventMembershipByEpoch\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getEventRootByBlock\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IBLS\",\n \"name\": \"newBls\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"contract IBN256G2\",\n \"name\": \"newBn256G2\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"chainId_\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Validator[]\",\n \"name\": \"newValidatorSet\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"blockHash\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockRound\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"currentValidatorSetHash\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.CheckpointMetadata\",\n \"name\": \"checkpointMetadata\",\n \"type\": \"tuple\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"eventRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Checkpoint\",\n \"name\": \"checkpoint\",\n \"type\": \"tuple\"\n },\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Validator[]\",\n \"name\": \"newValidatorSet\",\n \"type\": \"tuple[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"bitmap\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"submit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalVotingPower\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506116f2806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806376671808116100a2578063babd4ee411610071578063babd4ee4146102c8578063d4c8e3e8146102db578063e416d677146102ee578063e9193d2b146102f7578063f896f1a51461030a57600080fd5b8063766718081461024157806395b0b0271461024a5780639a8a059214610275578063b8a242521461027e57600080fd5b806361a02208116100e957806361a022081461019b578063671b3793146101be5780636969a25c146101c7578063729e7c6e1461021957806373cb1a111461022c57600080fd5b80631d1d4f261461011b57806322fd1818146101375780633569ed931461016157806352a9674b14610174575b600080fd5b61012460035481565b6040519081526020015b60405180910390f35b61014a610145366004610fdb565b610313565b60408051921515835260208301919091520161012e565b61012461016f366004610fdb565b610364565b6101247fbee7fa562a38908559e4a988e62d6c08b84ef05f2ebd5d2bb2b855dc19d19fe281565b6101ae6101a9366004610ff4565b610398565b604051901515815260200161012e565b61012460055481565b6101fa6101d5366004610fdb565b600960205260009081526040902080546005909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161012e565b6101ae610227366004610ff4565b610410565b61023f61023a3660046110e8565b610469565b005b61012460025481565b60065461025d906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b61012460015481565b6102ad61028c366004610fdb565b60086020526000908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161012e565b61023f6102d6366004611173565b6105bb565b60075461025d906001600160a01b031681565b61012460045481565b610124610305366004610fdb565b610820565b610124600b5481565b60008080610322600a85610841565b600a54909150810361033a5750600093849350915050565b6001600a828154811061034f5761034f61124c565b90600052602060002001549250925050915091565b6000600881610374600a85610841565b61037f906001611278565b8152602001908152602001600020600201549050919050565b6000806103a487610364565b9050806103f85760405162461bcd60e51b815260206004820152601e60248201527f4e4f5f4556454e545f524f4f545f464f525f424c4f434b5f4e554d424552000060448201526064015b60405180910390fd5b61040586868387876108f0565b979650505050505050565b600085815260086020526040812060020154806103f85760405162461bcd60e51b815260206004820152601760248201527609c9ebe8aac8a9ca8bea49e9ea8be8c9ea4be8aa09e869604b1b60448201526064016103ef565b600054610100900460ff16158080156104895750600054600160ff909116105b806104a35750303b1580156104a3575060005460ff166001145b6105065760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103ef565b6000805460ff191660011790558015610529576000805461ff0019166101001790555b6001849055600680546001600160a01b038089166001600160a01b0319928316179092556007805492881692909116919091179055600382905561056d8383610a45565b80156105b3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b8660400135600b54146106105760405162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f56414c494441544f525f5345545f4841534800000000000060448201526064016103ef565b6000600154876020013589600001358a602001358a600001358b604001358d604001358b8b60405160200161064692919061128b565b604051602081830303815290604052805190602001206040516020016106739897969594939291906112ee565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529082905260065463a850a90960e01b835290925061073f916001600160a01b039091169063a850a909906106f7907fbee7fa562a38908559e4a988e62d6c08b84ef05f2ebd5d2bb2b855dc19d19fe2908690600401611324565b6040805180830381865afa158015610713573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610737919061137a565b878585610b4b565b60025461074c8189610e55565b8735600081815260086020908152604091829020838155908b01356001820155908a01356002909101558110156107cf57600a8054600181018255600091825260208a01357fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890910155600280549091906107c690611408565b90915550610803565b600a805460208a013591906107e690600190611421565b815481106107f6576107f661124c565b6000918252602090912001555b60208801356004556108158686610a45565b505050505050505050565b600a818154811061083057600080fd5b600091825260209091200154905081565b81546000908103610854575060006108ea565b82546000905b808210156108a157600061086e8383610f32565b6000878152602090209091508590820154111561088d5780915061089b565b610898816001611278565b92505b5061085a565b6000821180156108cd5750836108ca866108bc600186611421565b600091825260209091200190565b54145b156108e6576108dd600183611421565b925050506108ea565b5090505b92915050565b6000816108fe816002611518565b86106109415760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b60448201526064016103ef565b8661097d5760405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa622a0a360a11b60448201526064016103ef565b8660005b82811015610a3757600086868381811061099d5761099d61124c565b9050602002013590506002896109b3919061153a565b6000036109eb576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a18565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b610a2360028a61154e565b98505080610a3090611408565b9050610981565b509094149695505050505050565b60038190556040518190610a5f908490839060200161128b565b60408051601f198184030181529190528051602090910120600b556000805b82811015610b42576000858583818110610a9a57610a9a61124c565b905060c0020160a00135905060008111610aea5760405162461bcd60e51b8152602060048201526011602482015270564f54494e475f504f5745525f5a45524f60781b60448201526064016103ef565b610af48184611278565b9250858583818110610b0857610b0861124c565b905060c00201600960008481526020019081526020016000208181610b2d9190611579565b9050505080610b3b90611408565b9050610a7e565b50600555505050565b600354610b56610fbd565b6000805b83811015610cda57610b6d868683610f54565b15610cd25781600003610bc1576000818152600960205260409081902081516080810190925260010160048282826020028201915b815481526020019060010190808311610ba25750505050509250610cb3565b60008181526009602052604080822081516080810190925260010160048282826020028201915b815481526020019060010190808311610be857505060075488516020808b01516040808d01516060808f01518b51958c0151848d0151928d01519451630cbe96a560e41b81529c9d506001600160a01b039098169b63cbe96a509b50610c5f9a5096985093969195939493919290916004016112ee565b608060405180830381865afa158015610c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca091906115d8565b6060880152604087015260208601528452505b600081815260096020526040902060050154610ccf9083611278565b91505b600101610b5a565b5080600003610d1d5760405162461bcd60e51b815260206004820152600f60248201526e4249544d41505f49535f454d50545960881b60448201526064016103ef565b60036005546002610d2e9190611562565b610d38919061154e565b8111610d825760405162461bcd60e51b815260206004820152601960248201527824a729aaa32324a1a4a2a72a2fab27aa24a723afa827aba2a960391b60448201526064016103ef565b60065460405163ebbdac9160e01b815260009182916001600160a01b039091169063ebbdac9190610dbb908b9088908e9060040161160e565b6040805180830381865afa158015610dd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfb9190611689565b91509150818015610e095750805b6108155760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c454400000060448201526064016103ef565b600082815260086020908152604091829020825160608101845281548082526001830154938201939093526002909101549281019290925282351480610ea757508051610ea3906001611278565b8235145b610ee35760405162461bcd60e51b815260206004820152600d60248201526c0929cac82989288be8aa09e869609b1b60448201526064016103ef565b8060200151826020013511610f2d5760405162461bcd60e51b815260206004820152601060248201526f115354151657d0d21150d2d413d2539560821b60448201526064016103ef565b505050565b6000610f41600284841861154e565b610f4d90848416611278565b9392505050565b600080610f6260088461154e565b90506000610f7160088561153a565b9050848210610f8557600092505050610f4d565b6000600160ff83161b878785818110610fa057610fa061124c565b9050013560f81c60f81b60f81c60ff161611925050509392505050565b60405180608001604052806004906020820280368337509192915050565b600060208284031215610fed57600080fd5b5035919050565b60008060008060006080868803121561100c57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8082111561103957600080fd5b818801915088601f83011261104d57600080fd5b81358181111561105c57600080fd5b8960208260051b850101111561107157600080fd5b9699959850939650602001949392505050565b6001600160a01b038116811461109957600080fd5b50565b60008083601f8401126110ae57600080fd5b50813567ffffffffffffffff8111156110c657600080fd5b60208301915083602060c0830285010111156110e157600080fd5b9250929050565b60008060008060006080868803121561110057600080fd5b853561110b81611084565b9450602086013561111b81611084565b935060408601359250606086013567ffffffffffffffff81111561113e57600080fd5b61114a8882890161109c565b969995985093965092949392505050565b60006060828403121561116d57600080fd5b50919050565b6000806000806000806000610140888a03121561118f57600080fd5b611199898961115b565b96506111a88960608a0161115b565b95506101008801898111156111bc57600080fd5b60c0890195503567ffffffffffffffff808211156111d957600080fd5b6111e58b838c0161109c565b90965094506101208a01359150808211156111ff57600080fd5b818a0191508a601f83011261121357600080fd5b81358181111561122257600080fd5b8b602082850101111561123457600080fd5b60208301945080935050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156108ea576108ea611262565b60208082528181018390526000908460408401835b868110156112e35782356112b381611084565b6001600160a01b0316825260808385018584013760a0838101359083015260c092830192909101906001016112a0565b509695505050505050565b978852602088019690965260408701949094526060860192909252608085015260a084015260c083015260e08201526101000190565b82815260006020604081840152835180604085015260005b818110156113585785810183015185820160600152820161133c565b506000606082860101526060601f19601f830116850101925050509392505050565b60006040828403121561138c57600080fd5b82601f83011261139b57600080fd5b6040516040810181811067ffffffffffffffff821117156113cc57634e487b7160e01b600052604160045260246000fd5b80604052508060408401858111156113e357600080fd5b845b818110156113fd5780518352602092830192016113e5565b509195945050505050565b60006001820161141a5761141a611262565b5060010190565b818103818111156108ea576108ea611262565b600181815b8085111561146f57816000190482111561145557611455611262565b8085161561146257918102915b93841c9390800290611439565b509250929050565b600082611486575060016108ea565b81611493575060006108ea565b81600181146114a957600281146114b3576114cf565b60019150506108ea565b60ff8411156114c4576114c4611262565b50506001821b6108ea565b5060208310610133831016604e8410600b84101617156114f2575081810a6108ea565b6114fc8383611434565b806000190482111561151057611510611262565b029392505050565b6000610f4d8383611477565b634e487b7160e01b600052601260045260246000fd5b60008261154957611549611524565b500690565b60008261155d5761155d611524565b500490565b80820281158282048414176108ea576108ea611262565b813561158481611084565b81546001600160a01b0319166001600160a01b0391909116178155602082810160005b60048110156115c7578135600182860181019190915591830191016115a7565b50505060a082013560058201555050565b600080600080608085870312156115ee57600080fd5b505082516020840151604085015160609095015191969095509092509050565b61010081016040858337604082018460005b600481101561163f578151835260209283019290910190600101611620565b50505060c082018360005b600281101561166957815183526020928301929091019060010161164a565b505050949350505050565b8051801515811461168457600080fd5b919050565b6000806040838503121561169c57600080fd5b6116a583611674565b91506116b360208401611674565b9050925092905056fea2646970667358221220a7bbc925b936828d67df832f2932e0f475f5fa7058472853cfff77d2f8eded9464736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101165760003560e01c806376671808116100a2578063babd4ee411610071578063babd4ee4146102c8578063d4c8e3e8146102db578063e416d677146102ee578063e9193d2b146102f7578063f896f1a51461030a57600080fd5b8063766718081461024157806395b0b0271461024a5780639a8a059214610275578063b8a242521461027e57600080fd5b806361a02208116100e957806361a022081461019b578063671b3793146101be5780636969a25c146101c7578063729e7c6e1461021957806373cb1a111461022c57600080fd5b80631d1d4f261461011b57806322fd1818146101375780633569ed931461016157806352a9674b14610174575b600080fd5b61012460035481565b6040519081526020015b60405180910390f35b61014a610145366004610fdb565b610313565b60408051921515835260208301919091520161012e565b61012461016f366004610fdb565b610364565b6101247fbee7fa562a38908559e4a988e62d6c08b84ef05f2ebd5d2bb2b855dc19d19fe281565b6101ae6101a9366004610ff4565b610398565b604051901515815260200161012e565b61012460055481565b6101fa6101d5366004610fdb565b600960205260009081526040902080546005909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161012e565b6101ae610227366004610ff4565b610410565b61023f61023a3660046110e8565b610469565b005b61012460025481565b60065461025d906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b61012460015481565b6102ad61028c366004610fdb565b60086020526000908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161012e565b61023f6102d6366004611173565b6105bb565b60075461025d906001600160a01b031681565b61012460045481565b610124610305366004610fdb565b610820565b610124600b5481565b60008080610322600a85610841565b600a54909150810361033a5750600093849350915050565b6001600a828154811061034f5761034f61124c565b90600052602060002001549250925050915091565b6000600881610374600a85610841565b61037f906001611278565b8152602001908152602001600020600201549050919050565b6000806103a487610364565b9050806103f85760405162461bcd60e51b815260206004820152601e60248201527f4e4f5f4556454e545f524f4f545f464f525f424c4f434b5f4e554d424552000060448201526064015b60405180910390fd5b61040586868387876108f0565b979650505050505050565b600085815260086020526040812060020154806103f85760405162461bcd60e51b815260206004820152601760248201527609c9ebe8aac8a9ca8bea49e9ea8be8c9ea4be8aa09e869604b1b60448201526064016103ef565b600054610100900460ff16158080156104895750600054600160ff909116105b806104a35750303b1580156104a3575060005460ff166001145b6105065760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103ef565b6000805460ff191660011790558015610529576000805461ff0019166101001790555b6001849055600680546001600160a01b038089166001600160a01b0319928316179092556007805492881692909116919091179055600382905561056d8383610a45565b80156105b3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b8660400135600b54146106105760405162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f56414c494441544f525f5345545f4841534800000000000060448201526064016103ef565b6000600154876020013589600001358a602001358a600001358b604001358d604001358b8b60405160200161064692919061128b565b604051602081830303815290604052805190602001206040516020016106739897969594939291906112ee565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529082905260065463a850a90960e01b835290925061073f916001600160a01b039091169063a850a909906106f7907fbee7fa562a38908559e4a988e62d6c08b84ef05f2ebd5d2bb2b855dc19d19fe2908690600401611324565b6040805180830381865afa158015610713573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610737919061137a565b878585610b4b565b60025461074c8189610e55565b8735600081815260086020908152604091829020838155908b01356001820155908a01356002909101558110156107cf57600a8054600181018255600091825260208a01357fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890910155600280549091906107c690611408565b90915550610803565b600a805460208a013591906107e690600190611421565b815481106107f6576107f661124c565b6000918252602090912001555b60208801356004556108158686610a45565b505050505050505050565b600a818154811061083057600080fd5b600091825260209091200154905081565b81546000908103610854575060006108ea565b82546000905b808210156108a157600061086e8383610f32565b6000878152602090209091508590820154111561088d5780915061089b565b610898816001611278565b92505b5061085a565b6000821180156108cd5750836108ca866108bc600186611421565b600091825260209091200190565b54145b156108e6576108dd600183611421565b925050506108ea565b5090505b92915050565b6000816108fe816002611518565b86106109415760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b60448201526064016103ef565b8661097d5760405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa622a0a360a11b60448201526064016103ef565b8660005b82811015610a3757600086868381811061099d5761099d61124c565b9050602002013590506002896109b3919061153a565b6000036109eb576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a18565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b610a2360028a61154e565b98505080610a3090611408565b9050610981565b509094149695505050505050565b60038190556040518190610a5f908490839060200161128b565b60408051601f198184030181529190528051602090910120600b556000805b82811015610b42576000858583818110610a9a57610a9a61124c565b905060c0020160a00135905060008111610aea5760405162461bcd60e51b8152602060048201526011602482015270564f54494e475f504f5745525f5a45524f60781b60448201526064016103ef565b610af48184611278565b9250858583818110610b0857610b0861124c565b905060c00201600960008481526020019081526020016000208181610b2d9190611579565b9050505080610b3b90611408565b9050610a7e565b50600555505050565b600354610b56610fbd565b6000805b83811015610cda57610b6d868683610f54565b15610cd25781600003610bc1576000818152600960205260409081902081516080810190925260010160048282826020028201915b815481526020019060010190808311610ba25750505050509250610cb3565b60008181526009602052604080822081516080810190925260010160048282826020028201915b815481526020019060010190808311610be857505060075488516020808b01516040808d01516060808f01518b51958c0151848d0151928d01519451630cbe96a560e41b81529c9d506001600160a01b039098169b63cbe96a509b50610c5f9a5096985093969195939493919290916004016112ee565b608060405180830381865afa158015610c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca091906115d8565b6060880152604087015260208601528452505b600081815260096020526040902060050154610ccf9083611278565b91505b600101610b5a565b5080600003610d1d5760405162461bcd60e51b815260206004820152600f60248201526e4249544d41505f49535f454d50545960881b60448201526064016103ef565b60036005546002610d2e9190611562565b610d38919061154e565b8111610d825760405162461bcd60e51b815260206004820152601960248201527824a729aaa32324a1a4a2a72a2fab27aa24a723afa827aba2a960391b60448201526064016103ef565b60065460405163ebbdac9160e01b815260009182916001600160a01b039091169063ebbdac9190610dbb908b9088908e9060040161160e565b6040805180830381865afa158015610dd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfb9190611689565b91509150818015610e095750805b6108155760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c454400000060448201526064016103ef565b600082815260086020908152604091829020825160608101845281548082526001830154938201939093526002909101549281019290925282351480610ea757508051610ea3906001611278565b8235145b610ee35760405162461bcd60e51b815260206004820152600d60248201526c0929cac82989288be8aa09e869609b1b60448201526064016103ef565b8060200151826020013511610f2d5760405162461bcd60e51b815260206004820152601060248201526f115354151657d0d21150d2d413d2539560821b60448201526064016103ef565b505050565b6000610f41600284841861154e565b610f4d90848416611278565b9392505050565b600080610f6260088461154e565b90506000610f7160088561153a565b9050848210610f8557600092505050610f4d565b6000600160ff83161b878785818110610fa057610fa061124c565b9050013560f81c60f81b60f81c60ff161611925050509392505050565b60405180608001604052806004906020820280368337509192915050565b600060208284031215610fed57600080fd5b5035919050565b60008060008060006080868803121561100c57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8082111561103957600080fd5b818801915088601f83011261104d57600080fd5b81358181111561105c57600080fd5b8960208260051b850101111561107157600080fd5b9699959850939650602001949392505050565b6001600160a01b038116811461109957600080fd5b50565b60008083601f8401126110ae57600080fd5b50813567ffffffffffffffff8111156110c657600080fd5b60208301915083602060c0830285010111156110e157600080fd5b9250929050565b60008060008060006080868803121561110057600080fd5b853561110b81611084565b9450602086013561111b81611084565b935060408601359250606086013567ffffffffffffffff81111561113e57600080fd5b61114a8882890161109c565b969995985093965092949392505050565b60006060828403121561116d57600080fd5b50919050565b6000806000806000806000610140888a03121561118f57600080fd5b611199898961115b565b96506111a88960608a0161115b565b95506101008801898111156111bc57600080fd5b60c0890195503567ffffffffffffffff808211156111d957600080fd5b6111e58b838c0161109c565b90965094506101208a01359150808211156111ff57600080fd5b818a0191508a601f83011261121357600080fd5b81358181111561122257600080fd5b8b602082850101111561123457600080fd5b60208301945080935050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156108ea576108ea611262565b60208082528181018390526000908460408401835b868110156112e35782356112b381611084565b6001600160a01b0316825260808385018584013760a0838101359083015260c092830192909101906001016112a0565b509695505050505050565b978852602088019690965260408701949094526060860192909252608085015260a084015260c083015260e08201526101000190565b82815260006020604081840152835180604085015260005b818110156113585785810183015185820160600152820161133c565b506000606082860101526060601f19601f830116850101925050509392505050565b60006040828403121561138c57600080fd5b82601f83011261139b57600080fd5b6040516040810181811067ffffffffffffffff821117156113cc57634e487b7160e01b600052604160045260246000fd5b80604052508060408401858111156113e357600080fd5b845b818110156113fd5780518352602092830192016113e5565b509195945050505050565b60006001820161141a5761141a611262565b5060010190565b818103818111156108ea576108ea611262565b600181815b8085111561146f57816000190482111561145557611455611262565b8085161561146257918102915b93841c9390800290611439565b509250929050565b600082611486575060016108ea565b81611493575060006108ea565b81600181146114a957600281146114b3576114cf565b60019150506108ea565b60ff8411156114c4576114c4611262565b50506001821b6108ea565b5060208310610133831016604e8410600b84101617156114f2575081810a6108ea565b6114fc8383611434565b806000190482111561151057611510611262565b029392505050565b6000610f4d8383611477565b634e487b7160e01b600052601260045260246000fd5b60008261154957611549611524565b500690565b60008261155d5761155d611524565b500490565b80820281158282048414176108ea576108ea611262565b813561158481611084565b81546001600160a01b0319166001600160a01b0391909116178155602082810160005b60048110156115c7578135600182860181019190915591830191016115a7565b50505060a082013560058201555050565b600080600080608085870312156115ee57600080fd5b505082516020840151604085015160609095015191969095509092509050565b61010081016040858337604082018460005b600481101561163f578151835260209283019290910190600101611620565b50505060c082018360005b600281101561166957815183526020928301929091019060010161164a565b505050949350505050565b8051801515811461168457600080fd5b919050565b6000806040838503121561169c57600080fd5b6116a583611674565b91506116b360208401611674565b9050925092905056fea2646970667358221220a7bbc925b936828d67df832f2932e0f475f5fa7058472853cfff77d2f8eded9464736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var ExitHelperArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ExitHelper\",\n \"sourceName\": \"contracts/root/ExitHelper.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"success\",\n \"type\": \"bool\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"returnData\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"ExitProcessed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"unhashedLeaf\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"internalType\": \"struct IExitHelper.BatchExitInput[]\",\n \"name\": \"inputs\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"batchExit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"checkpointManager\",\n \"outputs\": [\n {\n \"internalType\": \"contract ICheckpointManager\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"unhashedLeaf\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"exit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract ICheckpointManager\",\n \"name\": \"newCheckpointManager\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"processedExits\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610b62806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806350607b351461005c578063aa209cc314610071578063bd88ea7914610084578063c0857ba0146100bc578063c4d66de8146100e7575b600080fd5b61006f61006a3660046106c9565b6100fa565b005b61006f61007f36600461070b565b610200565b6100a76100923660046107bc565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6002546100cf906001600160a01b031681565b6040516001600160a01b0390911681526020016100b3565b61006f6100f53660046107ed565b610240565b6002546001600160a01b031661012b5760405162461bcd60e51b815260040161012290610811565b60405180910390fd5b8060005b818110156101fa576101f284848381811061014c5761014c610848565b905060200281019061015e919061085e565b3585858481811061017157610171610848565b9050602002810190610183919061085e565b6020013586868581811061019957610199610848565b90506020028101906101ab919061085e565b6101b990604081019061087e565b8888878181106101cb576101cb610848565b90506020028101906101dd919061085e565b6101eb9060608101906108c5565b60016103d2565b60010161012f565b50505050565b6002546001600160a01b03166102285760405162461bcd60e51b815260040161012290610811565b61023886868686868660006103d2565b505050505050565b600054610100900460ff16158080156102605750600054600160ff909116105b8061027a5750303b15801561027a575060005460ff166001145b6102dd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610122565b6000805460ff191660011790558015610300576000805461ff0019166101001790555b6001600160a01b0382161580159061032157506001600160a01b0382163b15155b61036d5760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a20494e56414c49445f4144445245535300000000006044820152606401610122565b600280546001600160a01b0319166001600160a01b03841617905580156103ce576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60008080806103e3888a018a610925565b935093509350935084156104165760008481526001602052604090205460ff16156104115750505050610674565b610480565b60008481526001602052604090205460ff16156104805760405162461bcd60e51b815260206004820152602260248201527f4578697448656c7065723a20455849545f414c52454144595f50524f43455353604482015261115160f21b6064820152608401610122565b6002546040516001600160a01b03909116906361a02208908d906104a7908d908d90610a05565b6040519081900381206001600160e01b031960e085901b1682526104d492918f908d908d90600401610a15565b602060405180830381865afa1580156104f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105159190610a62565b61055d5760405162461bcd60e51b815260206004820152601960248201527822bc34ba2432b63832b91d1024a72b20a624a22fa82927a7a360391b6044820152606401610122565b6000848152600160208190526040808320805460ff19169092179091555181906001600160a01b0385169061059a90889088908790602401610ad4565b60408051601f198184030181529181526020820180516001600160e01b031663f43cda8b60e01b179052516105cf9190610b07565b6000604051808303816000865af19150503d806000811461060c576040519150601f19603f3d011682016040523d82523d6000602084013e610611565b606091505b509150915081610632576000868152600160205260409020805460ff191690555b811515867f8bbfa0c9bee3785c03700d2a909592286efb83fc7e7002be5764424b9842f7ec836040516106659190610b19565b60405180910390a35050505050505b50505050505050565b60008083601f84011261068f57600080fd5b50813567ffffffffffffffff8111156106a757600080fd5b6020830191508360208260051b85010111156106c257600080fd5b9250929050565b600080602083850312156106dc57600080fd5b823567ffffffffffffffff8111156106f357600080fd5b6106ff8582860161067d565b90969095509350505050565b6000806000806000806080878903121561072457600080fd5b8635955060208701359450604087013567ffffffffffffffff8082111561074a57600080fd5b818901915089601f83011261075e57600080fd5b81358181111561076d57600080fd5b8a602082850101111561077f57600080fd5b60208301965080955050606089013591508082111561079d57600080fd5b506107aa89828a0161067d565b979a9699509497509295939492505050565b6000602082840312156107ce57600080fd5b5035919050565b6001600160a01b03811681146107ea57600080fd5b50565b6000602082840312156107ff57600080fd5b813561080a816107d5565b9392505050565b6020808252601b908201527f4578697448656c7065723a204e4f545f494e495449414c495a45440000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261087457600080fd5b9190910192915050565b6000808335601e1984360301811261089557600080fd5b83018035915067ffffffffffffffff8211156108b057600080fd5b6020019150368190038213156106c257600080fd5b6000808335601e198436030181126108dc57600080fd5b83018035915067ffffffffffffffff8211156108f757600080fd5b6020019150600581901b36038213156106c257600080fd5b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561093b57600080fd5b84359350602085013561094d816107d5565b9250604085013561095d816107d5565b9150606085013567ffffffffffffffff8082111561097a57600080fd5b818701915087601f83011261098e57600080fd5b8135818111156109a0576109a061090f565b604051601f8201601f19908116603f011681019083821181831017156109c8576109c861090f565b816040528281528a60208487010111156109e157600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b85815284602082015283604082015260806060820152816080820152600060018060fb1b03831115610a4657600080fd5b8260051b808560a08501379190910160a0019695505050505050565b600060208284031215610a7457600080fd5b8151801515811461080a57600080fd5b60005b83811015610a9f578181015183820152602001610a87565b50506000910152565b60008151808452610ac0816020860160208601610a84565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090610afe90830184610aa8565b95945050505050565b60008251610874818460208701610a84565b60208152600061080a6020830184610aa856fea264697066735822122008943fed61b7c9037d83d6de6f81699e05bf9650fa3394883bac4a072bac958b64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100575760003560e01c806350607b351461005c578063aa209cc314610071578063bd88ea7914610084578063c0857ba0146100bc578063c4d66de8146100e7575b600080fd5b61006f61006a3660046106c9565b6100fa565b005b61006f61007f36600461070b565b610200565b6100a76100923660046107bc565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6002546100cf906001600160a01b031681565b6040516001600160a01b0390911681526020016100b3565b61006f6100f53660046107ed565b610240565b6002546001600160a01b031661012b5760405162461bcd60e51b815260040161012290610811565b60405180910390fd5b8060005b818110156101fa576101f284848381811061014c5761014c610848565b905060200281019061015e919061085e565b3585858481811061017157610171610848565b9050602002810190610183919061085e565b6020013586868581811061019957610199610848565b90506020028101906101ab919061085e565b6101b990604081019061087e565b8888878181106101cb576101cb610848565b90506020028101906101dd919061085e565b6101eb9060608101906108c5565b60016103d2565b60010161012f565b50505050565b6002546001600160a01b03166102285760405162461bcd60e51b815260040161012290610811565b61023886868686868660006103d2565b505050505050565b600054610100900460ff16158080156102605750600054600160ff909116105b8061027a5750303b15801561027a575060005460ff166001145b6102dd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610122565b6000805460ff191660011790558015610300576000805461ff0019166101001790555b6001600160a01b0382161580159061032157506001600160a01b0382163b15155b61036d5760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a20494e56414c49445f4144445245535300000000006044820152606401610122565b600280546001600160a01b0319166001600160a01b03841617905580156103ce576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60008080806103e3888a018a610925565b935093509350935084156104165760008481526001602052604090205460ff16156104115750505050610674565b610480565b60008481526001602052604090205460ff16156104805760405162461bcd60e51b815260206004820152602260248201527f4578697448656c7065723a20455849545f414c52454144595f50524f43455353604482015261115160f21b6064820152608401610122565b6002546040516001600160a01b03909116906361a02208908d906104a7908d908d90610a05565b6040519081900381206001600160e01b031960e085901b1682526104d492918f908d908d90600401610a15565b602060405180830381865afa1580156104f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105159190610a62565b61055d5760405162461bcd60e51b815260206004820152601960248201527822bc34ba2432b63832b91d1024a72b20a624a22fa82927a7a360391b6044820152606401610122565b6000848152600160208190526040808320805460ff19169092179091555181906001600160a01b0385169061059a90889088908790602401610ad4565b60408051601f198184030181529181526020820180516001600160e01b031663f43cda8b60e01b179052516105cf9190610b07565b6000604051808303816000865af19150503d806000811461060c576040519150601f19603f3d011682016040523d82523d6000602084013e610611565b606091505b509150915081610632576000868152600160205260409020805460ff191690555b811515867f8bbfa0c9bee3785c03700d2a909592286efb83fc7e7002be5764424b9842f7ec836040516106659190610b19565b60405180910390a35050505050505b50505050505050565b60008083601f84011261068f57600080fd5b50813567ffffffffffffffff8111156106a757600080fd5b6020830191508360208260051b85010111156106c257600080fd5b9250929050565b600080602083850312156106dc57600080fd5b823567ffffffffffffffff8111156106f357600080fd5b6106ff8582860161067d565b90969095509350505050565b6000806000806000806080878903121561072457600080fd5b8635955060208701359450604087013567ffffffffffffffff8082111561074a57600080fd5b818901915089601f83011261075e57600080fd5b81358181111561076d57600080fd5b8a602082850101111561077f57600080fd5b60208301965080955050606089013591508082111561079d57600080fd5b506107aa89828a0161067d565b979a9699509497509295939492505050565b6000602082840312156107ce57600080fd5b5035919050565b6001600160a01b03811681146107ea57600080fd5b50565b6000602082840312156107ff57600080fd5b813561080a816107d5565b9392505050565b6020808252601b908201527f4578697448656c7065723a204e4f545f494e495449414c495a45440000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261087457600080fd5b9190910192915050565b6000808335601e1984360301811261089557600080fd5b83018035915067ffffffffffffffff8211156108b057600080fd5b6020019150368190038213156106c257600080fd5b6000808335601e198436030181126108dc57600080fd5b83018035915067ffffffffffffffff8211156108f757600080fd5b6020019150600581901b36038213156106c257600080fd5b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561093b57600080fd5b84359350602085013561094d816107d5565b9250604085013561095d816107d5565b9150606085013567ffffffffffffffff8082111561097a57600080fd5b818701915087601f83011261098e57600080fd5b8135818111156109a0576109a061090f565b604051601f8201601f19908116603f011681019083821181831017156109c8576109c861090f565b816040528281528a60208487010111156109e157600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b85815284602082015283604082015260806060820152816080820152600060018060fb1b03831115610a4657600080fd5b8260051b808560a08501379190910160a0019695505050505050565b600060208284031215610a7457600080fd5b8151801515811461080a57600080fd5b60005b83811015610a9f578181015183820152602001610a87565b50506000910152565b60008151808452610ac0816020860160208601610a84565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090610afe90830184610aa8565b95945050505050565b60008251610874818460208701610a84565b60208152600061080a6020830184610aa856fea264697066735822122008943fed61b7c9037d83d6de6f81699e05bf9650fa3394883bac4a072bac958b64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var StateSenderArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"StateSender\",\n \"sourceName\": \"contracts/root/StateSender.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"StateSynced\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAX_LENGTH\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"counter\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"syncState\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610297806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806316f198311461004657806361bc221a1461005b578063a6f9885c14610076575b600080fd5b61005961005436600461017a565b61007f565b005b61006460005481565b60405190815260200160405180910390f35b61006461080081565b6001600160a01b0383166100cd5760405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b60448201526064015b60405180910390fd5b6108008111156101145760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b60448201526064016100c4565b826001600160a01b0316336001600160a01b031660008081546101369061020b565b9190508190557fd1d7f6609674cc5871fdb4b0bcd4f0a214118411de9e38983866514f22659165858560405161016d929190610232565b60405180910390a4505050565b60008060006040848603121561018f57600080fd5b83356001600160a01b03811681146101a657600080fd5b9250602084013567ffffffffffffffff808211156101c357600080fd5b818601915086601f8301126101d757600080fd5b8135818111156101e657600080fd5b8760208285010111156101f857600080fd5b6020830194508093505050509250925092565b60006001820161022b57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122001854f5b142666bc44e5f66226d8f0a84e2c503b8ab6002552f648cf58e3336c64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806316f198311461004657806361bc221a1461005b578063a6f9885c14610076575b600080fd5b61005961005436600461017a565b61007f565b005b61006460005481565b60405190815260200160405180910390f35b61006461080081565b6001600160a01b0383166100cd5760405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b60448201526064015b60405180910390fd5b6108008111156101145760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b60448201526064016100c4565b826001600160a01b0316336001600160a01b031660008081546101369061020b565b9190508190557fd1d7f6609674cc5871fdb4b0bcd4f0a214118411de9e38983866514f22659165858560405161016d929190610232565b60405180910390a4505050565b60008060006040848603121561018f57600080fd5b83356001600160a01b03811681146101a657600080fd5b9250602084013567ffffffffffffffff808211156101c357600080fd5b818601915086601f8301126101d757600080fd5b8135818111156101e657600080fd5b8760208285010111156101f857600080fd5b6020830194508093505050509250925092565b60006001820161022b57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122001854f5b142666bc44e5f66226d8f0a84e2c503b8ab6002552f648cf58e3336c64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var RootERC20PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootERC20Predicate\",\n \"sourceName\": \"contracts/root/RootERC20Predicate.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ERC20Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ERC20Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"exitHelper\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newExitHelper\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"nativeTokenRootAddress\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onL2StateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506113c8806100206000396000f3fe608060405234801561001057600080fd5b50600436106100bf5760003560e01c8063cb10f94c1161007c578063cb10f94c1461018d578063d41f1771146101a6578063d57184e4146101cd578063f213159c146101e0578063f43cda8b146101f3578063f4a120f714610206578063f64512551461021957600080fd5b80631459457a146100c457806347e7ef24146100d95780637efab4f5146100ec57806395c7041c14610132578063b176806514610145578063b68ad1e41461017a575b600080fd5b6100d76100d2366004610f4c565b610240565b005b6100d76100e7366004610fbd565b6104ae565b6101156100fa366004610fe9565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600154610115906001600160a01b031681565b61016c7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610129565b600354610115906001600160a01b031681565b600054610115906201000090046001600160a01b031681565b61016c7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b600254610115906001600160a01b031681565b6100d76101ee36600461100d565b6104bd565b6100d761020136600461104e565b6104cd565b6100d7610214366004610fe9565b610654565b61016c7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b600054610100900460ff16158080156102605750600054600160ff909116105b8061027a5750303b15801561027a575060005460ff166001145b6102e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610305576000805461ff0019166101001790555b6001600160a01b0386161580159061032557506001600160a01b03851615155b801561033957506001600160a01b03841615155b801561034d57506001600160a01b03831615155b6103a85760405162461bcd60e51b815260206004820152602660248201527f526f6f7445524332305072656469636174653a204241445f494e495449414c496044820152652d20aa24a7a760d11b60648201526084016102d9565b6000805462010000600160b01b031916620100006001600160a01b038981169190910291909117909155600180546001600160a01b03199081168884161790915560028054821687841617905560038054909116858316179055821615610460576001600160a01b03821660008181526004602052604080822080546001600160a01b03191661101090811790915590519092917f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61791a35b80156104a6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6104b9823383610a0b565b5050565b6104c8838383610a0b565b505050565b6001546001600160a01b031633146105335760405162461bcd60e51b8152602060048201526024808201527f526f6f7445524332305072656469636174653a204f4e4c595f455849545f4845604482015263262822a960e11b60648201526084016102d9565b6002546001600160a01b038481169116146105a15760405162461bcd60e51b815260206004820152602860248201527f526f6f7445524332305072656469636174653a204f4e4c595f4348494c445f50604482015267524544494341544560c01b60648201526084016102d9565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696105d06020600084866110d7565b6105d991611101565b036105f8576105f36105ee82602081866110d7565b610b90565b61064e565b60405162461bcd60e51b815260206004820152602560248201527f526f6f7445524332305072656469636174653a20494e56414c49445f5349474e604482015264415455524560d81b60648201526084016102d9565b50505050565b6001600160a01b0381166106b45760405162461bcd60e51b815260206004820152602160248201527f526f6f7445524332305072656469636174653a20494e56414c49445f544f4b456044820152602760f91b60648201526084016102d9565b6001600160a01b0381811660009081526004602052604090205416156107275760405162461bcd60e51b815260206004820152602260248201527f526f6f7445524332305072656469636174653a20414c52454144595f4d415050604482015261115160f21b60648201526084016102d9565b60035460408051606084901b6bffffffffffffffffffffffff19166020808301919091528251601481840301815260348301808552815191909201206002546001600160a01b03908116606c8501526f5af43d82803e903d91602b57fd5bf3ff60588501529094166048830152733d602d80600a3d3981f3363d3d373d3d3d363d739052608c81019290925260379082012060ac82015260556077909101206000906001600160a01b03838116600081815260046020819052604080832080546001600160a01b031916878716179055825460025482516306fdde0360e01b81529251979850620100009091048616966316f198319691909116947f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad948a9491936306fdde03938184019390918290030181865afa15801561086d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610895919081019061115a565b876001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108d3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108fb919081019061115a565b886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610939573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095d91906111fc565b60405160200161097195949392919061124b565b6040516020818303038152906040526040518363ffffffff1660e01b815260040161099d92919061129d565b600060405180830381600087803b1580156109b757600080fd5b505af11580156109cb573d6000803e3d6000fd5b50506040516001600160a01b038085169350851691507f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61790600090a35050565b6001600160a01b0383811660009081526004602052604090205416610a3357610a3383610654565b6001600160a01b038084166000908152600460205260409020541680610a5b57610a5b6112c1565b610a706001600160a01b038516333085610c48565b600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b0388811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352620100009094048416936316f1983193610b019391169160c40161129d565b600060405180830381600087803b158015610b1b57600080fd5b505af1158015610b2f573d6000803e3d6000fd5b50505050826001600160a01b0316816001600160a01b0316856001600160a01b03167f8be9001bb612c7123a1861dc0d9d94e683261f6cbbd7c7438b708975bc4908a33386604051610b829291906112d7565b60405180910390a450505050565b6000808080610ba1858701876112f0565b6001600160a01b0380851660009081526004602052604090205494985092965090945092501680610bd457610bd46112c1565b610be86001600160a01b0386168484610cb3565b826001600160a01b0316816001600160a01b0316866001600160a01b03167f9c4f744b2e971d7058a9d8f43977e0e17bf7d57a48659f0e18541b7ee3d022e48786604051610c379291906112d7565b60405180910390a450505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905261064e9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610cd2565b6104c88363a9059cbb60e01b8484604051602401610c7c9291906112d7565b6000610d27826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610da49092919063ffffffff16565b8051909150156104c85780806020019051810190610d459190611341565b6104c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102d9565b6060610db38484600085610dbb565b949350505050565b606082471015610e1c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102d9565b600080866001600160a01b03168587604051610e389190611363565b60006040518083038185875af1925050503d8060008114610e75576040519150601f19603f3d011682016040523d82523d6000602084013e610e7a565b606091505b5091509150610e8b87838387610e96565b979650505050505050565b60608315610f05578251600003610efe576001600160a01b0385163b610efe5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d9565b5081610db3565b610db38383815115610f1a5781518083602001fd5b8060405162461bcd60e51b81526004016102d9919061137f565b6001600160a01b0381168114610f4957600080fd5b50565b600080600080600060a08688031215610f6457600080fd5b8535610f6f81610f34565b94506020860135610f7f81610f34565b93506040860135610f8f81610f34565b92506060860135610f9f81610f34565b91506080860135610faf81610f34565b809150509295509295909350565b60008060408385031215610fd057600080fd5b8235610fdb81610f34565b946020939093013593505050565b600060208284031215610ffb57600080fd5b813561100681610f34565b9392505050565b60008060006060848603121561102257600080fd5b833561102d81610f34565b9250602084013561103d81610f34565b929592945050506040919091013590565b6000806000806060858703121561106457600080fd5b84359350602085013561107681610f34565b9250604085013567ffffffffffffffff8082111561109357600080fd5b818701915087601f8301126110a757600080fd5b8135818111156110b657600080fd5b8860208285010111156110c857600080fd5b95989497505060200194505050565b600080858511156110e757600080fd5b838611156110f457600080fd5b5050820193919092039150565b8035602083101561111a57600019602084900360031b1b165b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015611151578181015183820152602001611139565b50506000910152565b60006020828403121561116c57600080fd5b815167ffffffffffffffff8082111561118457600080fd5b818401915084601f83011261119857600080fd5b8151818111156111aa576111aa611120565b604051601f8201601f19908116603f011681019083821181831017156111d2576111d2611120565b816040528281528760208487010111156111eb57600080fd5b610e8b836020830160208801611136565b60006020828403121561120e57600080fd5b815160ff8116811461100657600080fd5b60008151808452611237816020860160208601611136565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260a0604082018190526000906112759083018661121f565b8281036060840152611287818661121f565b91505060ff831660808301529695505050505050565b6001600160a01b0383168152604060208201819052600090610db39083018461121f565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b6000806000806080858703121561130657600080fd5b843561131181610f34565b9350602085013561132181610f34565b9250604085013561133181610f34565b9396929550929360600135925050565b60006020828403121561135357600080fd5b8151801515811461100657600080fd5b60008251611375818460208701611136565b9190910192915050565b602081526000611006602083018461121f56fea264697066735822122071186a5f68a0e568193775380eab31143f89ff0d61291b20e262c95a735f1d7b64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100bf5760003560e01c8063cb10f94c1161007c578063cb10f94c1461018d578063d41f1771146101a6578063d57184e4146101cd578063f213159c146101e0578063f43cda8b146101f3578063f4a120f714610206578063f64512551461021957600080fd5b80631459457a146100c457806347e7ef24146100d95780637efab4f5146100ec57806395c7041c14610132578063b176806514610145578063b68ad1e41461017a575b600080fd5b6100d76100d2366004610f4c565b610240565b005b6100d76100e7366004610fbd565b6104ae565b6101156100fa366004610fe9565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600154610115906001600160a01b031681565b61016c7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610129565b600354610115906001600160a01b031681565b600054610115906201000090046001600160a01b031681565b61016c7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b600254610115906001600160a01b031681565b6100d76101ee36600461100d565b6104bd565b6100d761020136600461104e565b6104cd565b6100d7610214366004610fe9565b610654565b61016c7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b600054610100900460ff16158080156102605750600054600160ff909116105b8061027a5750303b15801561027a575060005460ff166001145b6102e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610305576000805461ff0019166101001790555b6001600160a01b0386161580159061032557506001600160a01b03851615155b801561033957506001600160a01b03841615155b801561034d57506001600160a01b03831615155b6103a85760405162461bcd60e51b815260206004820152602660248201527f526f6f7445524332305072656469636174653a204241445f494e495449414c496044820152652d20aa24a7a760d11b60648201526084016102d9565b6000805462010000600160b01b031916620100006001600160a01b038981169190910291909117909155600180546001600160a01b03199081168884161790915560028054821687841617905560038054909116858316179055821615610460576001600160a01b03821660008181526004602052604080822080546001600160a01b03191661101090811790915590519092917f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61791a35b80156104a6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6104b9823383610a0b565b5050565b6104c8838383610a0b565b505050565b6001546001600160a01b031633146105335760405162461bcd60e51b8152602060048201526024808201527f526f6f7445524332305072656469636174653a204f4e4c595f455849545f4845604482015263262822a960e11b60648201526084016102d9565b6002546001600160a01b038481169116146105a15760405162461bcd60e51b815260206004820152602860248201527f526f6f7445524332305072656469636174653a204f4e4c595f4348494c445f50604482015267524544494341544560c01b60648201526084016102d9565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696105d06020600084866110d7565b6105d991611101565b036105f8576105f36105ee82602081866110d7565b610b90565b61064e565b60405162461bcd60e51b815260206004820152602560248201527f526f6f7445524332305072656469636174653a20494e56414c49445f5349474e604482015264415455524560d81b60648201526084016102d9565b50505050565b6001600160a01b0381166106b45760405162461bcd60e51b815260206004820152602160248201527f526f6f7445524332305072656469636174653a20494e56414c49445f544f4b456044820152602760f91b60648201526084016102d9565b6001600160a01b0381811660009081526004602052604090205416156107275760405162461bcd60e51b815260206004820152602260248201527f526f6f7445524332305072656469636174653a20414c52454144595f4d415050604482015261115160f21b60648201526084016102d9565b60035460408051606084901b6bffffffffffffffffffffffff19166020808301919091528251601481840301815260348301808552815191909201206002546001600160a01b03908116606c8501526f5af43d82803e903d91602b57fd5bf3ff60588501529094166048830152733d602d80600a3d3981f3363d3d373d3d3d363d739052608c81019290925260379082012060ac82015260556077909101206000906001600160a01b03838116600081815260046020819052604080832080546001600160a01b031916878716179055825460025482516306fdde0360e01b81529251979850620100009091048616966316f198319691909116947f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad948a9491936306fdde03938184019390918290030181865afa15801561086d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610895919081019061115a565b876001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108d3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108fb919081019061115a565b886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610939573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061095d91906111fc565b60405160200161097195949392919061124b565b6040516020818303038152906040526040518363ffffffff1660e01b815260040161099d92919061129d565b600060405180830381600087803b1580156109b757600080fd5b505af11580156109cb573d6000803e3d6000fd5b50506040516001600160a01b038085169350851691507f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61790600090a35050565b6001600160a01b0383811660009081526004602052604090205416610a3357610a3383610654565b6001600160a01b038084166000908152600460205260409020541680610a5b57610a5b6112c1565b610a706001600160a01b038516333085610c48565b600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b0388811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352620100009094048416936316f1983193610b019391169160c40161129d565b600060405180830381600087803b158015610b1b57600080fd5b505af1158015610b2f573d6000803e3d6000fd5b50505050826001600160a01b0316816001600160a01b0316856001600160a01b03167f8be9001bb612c7123a1861dc0d9d94e683261f6cbbd7c7438b708975bc4908a33386604051610b829291906112d7565b60405180910390a450505050565b6000808080610ba1858701876112f0565b6001600160a01b0380851660009081526004602052604090205494985092965090945092501680610bd457610bd46112c1565b610be86001600160a01b0386168484610cb3565b826001600160a01b0316816001600160a01b0316866001600160a01b03167f9c4f744b2e971d7058a9d8f43977e0e17bf7d57a48659f0e18541b7ee3d022e48786604051610c379291906112d7565b60405180910390a450505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905261064e9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610cd2565b6104c88363a9059cbb60e01b8484604051602401610c7c9291906112d7565b6000610d27826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610da49092919063ffffffff16565b8051909150156104c85780806020019051810190610d459190611341565b6104c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102d9565b6060610db38484600085610dbb565b949350505050565b606082471015610e1c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102d9565b600080866001600160a01b03168587604051610e389190611363565b60006040518083038185875af1925050503d8060008114610e75576040519150601f19603f3d011682016040523d82523d6000602084013e610e7a565b606091505b5091509150610e8b87838387610e96565b979650505050505050565b60608315610f05578251600003610efe576001600160a01b0385163b610efe5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d9565b5081610db3565b610db38383815115610f1a5781518083602001fd5b8060405162461bcd60e51b81526004016102d9919061137f565b6001600160a01b0381168114610f4957600080fd5b50565b600080600080600060a08688031215610f6457600080fd5b8535610f6f81610f34565b94506020860135610f7f81610f34565b93506040860135610f8f81610f34565b92506060860135610f9f81610f34565b91506080860135610faf81610f34565b809150509295509295909350565b60008060408385031215610fd057600080fd5b8235610fdb81610f34565b946020939093013593505050565b600060208284031215610ffb57600080fd5b813561100681610f34565b9392505050565b60008060006060848603121561102257600080fd5b833561102d81610f34565b9250602084013561103d81610f34565b929592945050506040919091013590565b6000806000806060858703121561106457600080fd5b84359350602085013561107681610f34565b9250604085013567ffffffffffffffff8082111561109357600080fd5b818701915087601f8301126110a757600080fd5b8135818111156110b657600080fd5b8860208285010111156110c857600080fd5b95989497505060200194505050565b600080858511156110e757600080fd5b838611156110f457600080fd5b5050820193919092039150565b8035602083101561111a57600019602084900360031b1b165b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015611151578181015183820152602001611139565b50506000910152565b60006020828403121561116c57600080fd5b815167ffffffffffffffff8082111561118457600080fd5b818401915084601f83011261119857600080fd5b8151818111156111aa576111aa611120565b604051601f8201601f19908116603f011681019083821181831017156111d2576111d2611120565b816040528281528760208487010111156111eb57600080fd5b610e8b836020830160208801611136565b60006020828403121561120e57600080fd5b815160ff8116811461100657600080fd5b60008151808452611237816020860160208601611136565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260a0604082018190526000906112759083018661121f565b8281036060840152611287818661121f565b91505060ff831660808301529695505050505050565b6001600160a01b0383168152604060208201819052600090610db39083018461121f565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b6000806000806080858703121561130657600080fd5b843561131181610f34565b9350602085013561132181610f34565b9250604085013561133181610f34565b9396929550929360600135925050565b60006020828403121561135357600080fd5b8151801515811461100657600080fd5b60008251611375818460208701611136565b9190910192915050565b602081526000611006602083018461121f56fea264697066735822122071186a5f68a0e568193775380eab31143f89ff0d61291b20e262c95a735f1d7b64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" -var MockERC20Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"MockERC20\",\n \"sourceName\": \"contracts/mocks/MockERC20.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Paused\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"previousAdminRole\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"newAdminRole\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"RoleAdminChanged\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RoleGranted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RoleRevoked\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Unpaused\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEFAULT_ADMIN_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MINTER_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"PAUSER_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burnFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"getRoleAdmin\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"index\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getRoleMember\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"getRoleMemberCount\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"grantRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"hasRole\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pause\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"paused\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"renounceRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"revokeRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"unpause\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x60806040523480156200001157600080fd5b50604080518082018252600480825263151154d560e21b60208084018290528451808601909552918452908301529081816005620000508382620002e2565b5060066200005f8282620002e2565b50506007805460ff191690555062000079600033620000d9565b620000a57f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633620000d9565b620000d17f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33620000d9565b5050620003ae565b620000e58282620000e9565b5050565b6200010082826200012c60201b620008871760201c565b6000828152600160209081526040909120620001279183906200090b620001cc821b17901c565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000e5576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001883390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620001e3836001600160a01b038416620001ec565b90505b92915050565b60008181526001830160205260408120546200023557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620001e6565b506000620001e6565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200026957607f821691505b6020821081036200028a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200012757600081815260208120601f850160051c81016020861015620002b95750805b601f850160051c820191505b81811015620002da57828155600101620002c5565b505050505050565b81516001600160401b03811115620002fe57620002fe6200023e565b62000316816200030f845462000254565b8462000290565b602080601f8311600181146200034e5760008415620003355750858301515b600019600386901b1c1916600185901b178555620002da565b600085815260208120601f198616915b828110156200037f578886015182559484019460019091019084016200035e565b50858210156200039e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6117fa80620003be6000396000f3fe608060405234801561001057600080fd5b50600436106101845760003560e01c806370a08231116100d9578063a457c2d711610087578063a457c2d714610336578063a9059cbb14610349578063ca15c8731461035c578063d53913931461036f578063d547741f14610396578063dd62ed3e146103a9578063e63ab1e9146103bc57600080fd5b806370a08231146102a457806379cc6790146102cd5780638456cb59146102e05780639010d07c146102e857806391d148541461031357806395d89b4114610326578063a217fddf1461032e57600080fd5b8063313ce56711610136578063313ce5671461023657806336568abe1461024557806339509351146102585780633f4ba83a1461026b57806340c10f191461027357806342966c68146102865780635c975abb1461029957600080fd5b806301ffc9a71461018957806306fdde03146101b1578063095ea7b3146101c657806318160ddd146101d957806323b872dd146101eb578063248a9ca3146101fe5780632f2ff15d14610221575b600080fd5b61019c610197366004611460565b6103d1565b60405190151581526020015b60405180910390f35b6101b96103fc565b6040516101a891906114ae565b61019c6101d43660046114fd565b61048e565b6004545b6040519081526020016101a8565b61019c6101f9366004611527565b6104a6565b6101dd61020c366004611563565b60009081526020819052604090206001015490565b61023461022f36600461157c565b6104ca565b005b604051601281526020016101a8565b61023461025336600461157c565b6104f4565b61019c6102663660046114fd565b610577565b610234610599565b6102346102813660046114fd565b610617565b610234610294366004611563565b6106a4565b60075460ff1661019c565b6101dd6102b23660046115a8565b6001600160a01b031660009081526002602052604090205490565b6102346102db3660046114fd565b6106b1565b6102346106c6565b6102fb6102f63660046115c3565b610740565b6040516001600160a01b0390911681526020016101a8565b61019c61032136600461157c565b61075f565b6101b9610788565b6101dd600081565b61019c6103443660046114fd565b610797565b61019c6103573660046114fd565b610812565b6101dd61036a366004611563565b610820565b6101dd7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102346103a436600461157c565b610837565b6101dd6103b73660046115e5565b61085c565b6101dd60008051602061178583398151915281565b60006001600160e01b03198216635a05180f60e01b14806103f657506103f682610920565b92915050565b60606005805461040b9061160f565b80601f01602080910402602001604051908101604052809291908181526020018280546104379061160f565b80156104845780601f1061045957610100808354040283529160200191610484565b820191906000526020600020905b81548152906001019060200180831161046757829003601f168201915b5050505050905090565b60003361049c818585610955565b5060019392505050565b6000336104b4858285610a79565b6104bf858585610af3565b506001949350505050565b6000828152602081905260409020600101546104e581610c97565b6104ef8383610ca1565b505050565b6001600160a01b03811633146105695760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6105738282610cc3565b5050565b60003361049c81858561058a838361085c565b610594919061165f565b610955565b6105b16000805160206117858339815191523361075f565b61060d5760405162461bcd60e51b8152602060048201526039602482015260008051602061176583398151915260448201527876652070617573657220726f6c6520746f20756e706175736560381b6064820152608401610560565b610615610ce5565b565b6106417f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63361075f565b61069a5760405162461bcd60e51b815260206004820152603660248201526000805160206117658339815191526044820152751d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60521b6064820152608401610560565b6105738282610d37565b6106ae3382610df2565b50565b6106bc823383610a79565b6105738282610df2565b6106de6000805160206117858339815191523361075f565b6107385760405162461bcd60e51b8152602060048201526037602482015260008051602061176583398151915260448201527676652070617573657220726f6c6520746f20706175736560481b6064820152608401610560565b610615610f20565b60008281526001602052604081206107589083610f5d565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606006805461040b9061160f565b600033816107a5828661085c565b9050838110156108055760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610560565b6104bf8286868403610955565b60003361049c818585610af3565b60008181526001602052604081206103f690610f69565b60008281526020819052604090206001015461085281610c97565b6104ef8383610cc3565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b610891828261075f565b610573576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556108c73390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610758836001600160a01b038416610f73565b60006001600160e01b03198216637965db0b60e01b14806103f657506301ffc9a760e01b6001600160e01b03198316146103f6565b6001600160a01b0383166109b75760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610560565b6001600160a01b038216610a185760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610560565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000610a85848461085c565b90506000198114610aed5781811015610ae05760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610560565b610aed8484848403610955565b50505050565b6001600160a01b038316610b575760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610560565b6001600160a01b038216610bb95760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610560565b610bc4838383610fc2565b6001600160a01b03831660009081526002602052604090205481811015610c3c5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610560565b6001600160a01b0380851660008181526002602052604080822086860390559286168082529083902080548601905591516000805160206117a583398151915290610c8a9086815260200190565b60405180910390a3610aed565b6106ae8133610fcd565b610cab8282610887565b60008281526001602052604090206104ef908261090b565b610ccd8282611026565b60008281526001602052604090206104ef908261108b565b610ced6110a0565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216610d8d5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610560565b610d9960008383610fc2565b8060046000828254610dab919061165f565b90915550506001600160a01b0382166000818152600260209081526040808320805486019055518481526000805160206117a5833981519152910160405180910390a35050565b6001600160a01b038216610e525760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610560565b610e5e82600083610fc2565b6001600160a01b03821660009081526002602052604090205481811015610ed25760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610560565b6001600160a01b03831660008181526002602090815260408083208686039055600480548790039055518581529192916000805160206117a5833981519152910160405180910390a3505050565b610f286110e9565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610d1a3390565b6000610758838361112f565b60006103f6825490565b6000818152600183016020526040812054610fba575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556103f6565b5060006103f6565b6104ef838383611159565b610fd7828261075f565b61057357610fe4816111bf565b610fef8360206111d1565b604051602001611000929190611672565b60408051601f198184030181529082905262461bcd60e51b8252610560916004016114ae565b611030828261075f565b15610573576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610758836001600160a01b03841661136d565b60075460ff166106155760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610560565b60075460ff16156106155760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610560565b6000826000018281548110611146576111466116e1565b9060005260206000200154905092915050565b60075460ff16156104ef5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610560565b60606103f66001600160a01b03831660145b606060006111e08360026116f7565b6111eb90600261165f565b67ffffffffffffffff8111156112035761120361170e565b6040519080825280601f01601f19166020018201604052801561122d576020820181803683370190505b509050600360fc1b81600081518110611248576112486116e1565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611277576112776116e1565b60200101906001600160f81b031916908160001a905350600061129b8460026116f7565b6112a690600161165f565b90505b600181111561131e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106112da576112da6116e1565b1a60f81b8282815181106112f0576112f06116e1565b60200101906001600160f81b031916908160001a90535060049490941c9361131781611724565b90506112a9565b5083156107585760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610560565b6000818152600183016020526040812054801561145657600061139160018361173b565b85549091506000906113a59060019061173b565b905081811461140a5760008660000182815481106113c5576113c56116e1565b90600052602060002001549050808760000184815481106113e8576113e86116e1565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061141b5761141b61174e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506103f6565b60009150506103f6565b60006020828403121561147257600080fd5b81356001600160e01b03198116811461075857600080fd5b60005b838110156114a557818101518382015260200161148d565b50506000910152565b60208152600082518060208401526114cd81604085016020870161148a565b601f01601f19169190910160400192915050565b80356001600160a01b03811681146114f857600080fd5b919050565b6000806040838503121561151057600080fd5b611519836114e1565b946020939093013593505050565b60008060006060848603121561153c57600080fd5b611545846114e1565b9250611553602085016114e1565b9150604084013590509250925092565b60006020828403121561157557600080fd5b5035919050565b6000806040838503121561158f57600080fd5b8235915061159f602084016114e1565b90509250929050565b6000602082840312156115ba57600080fd5b610758826114e1565b600080604083850312156115d657600080fd5b50508035926020909101359150565b600080604083850312156115f857600080fd5b611601836114e1565b915061159f602084016114e1565b600181811c9082168061162357607f821691505b60208210810361164357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103f6576103f6611649565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516116a481601785016020880161148a565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516116d581602884016020880161148a565b01602801949350505050565b634e487b7160e01b600052603260045260246000fd5b80820281158282048414176103f6576103f6611649565b634e487b7160e01b600052604160045260246000fd5b60008161173357611733611649565b506000190190565b818103818111156103f6576103f6611649565b634e487b7160e01b600052603160045260246000fdfe45524332305072657365744d696e7465725061757365723a206d75737420686165d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220869bafd8796afcbd2b83d9ab479f7920e24272bf48f6b43b28917d060a789e4d64736f6c63430008110033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101845760003560e01c806370a08231116100d9578063a457c2d711610087578063a457c2d714610336578063a9059cbb14610349578063ca15c8731461035c578063d53913931461036f578063d547741f14610396578063dd62ed3e146103a9578063e63ab1e9146103bc57600080fd5b806370a08231146102a457806379cc6790146102cd5780638456cb59146102e05780639010d07c146102e857806391d148541461031357806395d89b4114610326578063a217fddf1461032e57600080fd5b8063313ce56711610136578063313ce5671461023657806336568abe1461024557806339509351146102585780633f4ba83a1461026b57806340c10f191461027357806342966c68146102865780635c975abb1461029957600080fd5b806301ffc9a71461018957806306fdde03146101b1578063095ea7b3146101c657806318160ddd146101d957806323b872dd146101eb578063248a9ca3146101fe5780632f2ff15d14610221575b600080fd5b61019c610197366004611460565b6103d1565b60405190151581526020015b60405180910390f35b6101b96103fc565b6040516101a891906114ae565b61019c6101d43660046114fd565b61048e565b6004545b6040519081526020016101a8565b61019c6101f9366004611527565b6104a6565b6101dd61020c366004611563565b60009081526020819052604090206001015490565b61023461022f36600461157c565b6104ca565b005b604051601281526020016101a8565b61023461025336600461157c565b6104f4565b61019c6102663660046114fd565b610577565b610234610599565b6102346102813660046114fd565b610617565b610234610294366004611563565b6106a4565b60075460ff1661019c565b6101dd6102b23660046115a8565b6001600160a01b031660009081526002602052604090205490565b6102346102db3660046114fd565b6106b1565b6102346106c6565b6102fb6102f63660046115c3565b610740565b6040516001600160a01b0390911681526020016101a8565b61019c61032136600461157c565b61075f565b6101b9610788565b6101dd600081565b61019c6103443660046114fd565b610797565b61019c6103573660046114fd565b610812565b6101dd61036a366004611563565b610820565b6101dd7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102346103a436600461157c565b610837565b6101dd6103b73660046115e5565b61085c565b6101dd60008051602061178583398151915281565b60006001600160e01b03198216635a05180f60e01b14806103f657506103f682610920565b92915050565b60606005805461040b9061160f565b80601f01602080910402602001604051908101604052809291908181526020018280546104379061160f565b80156104845780601f1061045957610100808354040283529160200191610484565b820191906000526020600020905b81548152906001019060200180831161046757829003601f168201915b5050505050905090565b60003361049c818585610955565b5060019392505050565b6000336104b4858285610a79565b6104bf858585610af3565b506001949350505050565b6000828152602081905260409020600101546104e581610c97565b6104ef8383610ca1565b505050565b6001600160a01b03811633146105695760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6105738282610cc3565b5050565b60003361049c81858561058a838361085c565b610594919061165f565b610955565b6105b16000805160206117858339815191523361075f565b61060d5760405162461bcd60e51b8152602060048201526039602482015260008051602061176583398151915260448201527876652070617573657220726f6c6520746f20756e706175736560381b6064820152608401610560565b610615610ce5565b565b6106417f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63361075f565b61069a5760405162461bcd60e51b815260206004820152603660248201526000805160206117658339815191526044820152751d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60521b6064820152608401610560565b6105738282610d37565b6106ae3382610df2565b50565b6106bc823383610a79565b6105738282610df2565b6106de6000805160206117858339815191523361075f565b6107385760405162461bcd60e51b8152602060048201526037602482015260008051602061176583398151915260448201527676652070617573657220726f6c6520746f20706175736560481b6064820152608401610560565b610615610f20565b60008281526001602052604081206107589083610f5d565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606006805461040b9061160f565b600033816107a5828661085c565b9050838110156108055760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610560565b6104bf8286868403610955565b60003361049c818585610af3565b60008181526001602052604081206103f690610f69565b60008281526020819052604090206001015461085281610c97565b6104ef8383610cc3565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b610891828261075f565b610573576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556108c73390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610758836001600160a01b038416610f73565b60006001600160e01b03198216637965db0b60e01b14806103f657506301ffc9a760e01b6001600160e01b03198316146103f6565b6001600160a01b0383166109b75760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610560565b6001600160a01b038216610a185760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610560565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000610a85848461085c565b90506000198114610aed5781811015610ae05760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610560565b610aed8484848403610955565b50505050565b6001600160a01b038316610b575760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610560565b6001600160a01b038216610bb95760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610560565b610bc4838383610fc2565b6001600160a01b03831660009081526002602052604090205481811015610c3c5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610560565b6001600160a01b0380851660008181526002602052604080822086860390559286168082529083902080548601905591516000805160206117a583398151915290610c8a9086815260200190565b60405180910390a3610aed565b6106ae8133610fcd565b610cab8282610887565b60008281526001602052604090206104ef908261090b565b610ccd8282611026565b60008281526001602052604090206104ef908261108b565b610ced6110a0565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216610d8d5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610560565b610d9960008383610fc2565b8060046000828254610dab919061165f565b90915550506001600160a01b0382166000818152600260209081526040808320805486019055518481526000805160206117a5833981519152910160405180910390a35050565b6001600160a01b038216610e525760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610560565b610e5e82600083610fc2565b6001600160a01b03821660009081526002602052604090205481811015610ed25760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610560565b6001600160a01b03831660008181526002602090815260408083208686039055600480548790039055518581529192916000805160206117a5833981519152910160405180910390a3505050565b610f286110e9565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610d1a3390565b6000610758838361112f565b60006103f6825490565b6000818152600183016020526040812054610fba575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556103f6565b5060006103f6565b6104ef838383611159565b610fd7828261075f565b61057357610fe4816111bf565b610fef8360206111d1565b604051602001611000929190611672565b60408051601f198184030181529082905262461bcd60e51b8252610560916004016114ae565b611030828261075f565b15610573576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610758836001600160a01b03841661136d565b60075460ff166106155760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610560565b60075460ff16156106155760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610560565b6000826000018281548110611146576111466116e1565b9060005260206000200154905092915050565b60075460ff16156104ef5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610560565b60606103f66001600160a01b03831660145b606060006111e08360026116f7565b6111eb90600261165f565b67ffffffffffffffff8111156112035761120361170e565b6040519080825280601f01601f19166020018201604052801561122d576020820181803683370190505b509050600360fc1b81600081518110611248576112486116e1565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611277576112776116e1565b60200101906001600160f81b031916908160001a905350600061129b8460026116f7565b6112a690600161165f565b90505b600181111561131e576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106112da576112da6116e1565b1a60f81b8282815181106112f0576112f06116e1565b60200101906001600160f81b031916908160001a90535060049490941c9361131781611724565b90506112a9565b5083156107585760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610560565b6000818152600183016020526040812054801561145657600061139160018361173b565b85549091506000906113a59060019061173b565b905081811461140a5760008660000182815481106113c5576113c56116e1565b90600052602060002001549050808760000184815481106113e8576113e86116e1565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061141b5761141b61174e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506103f6565b60009150506103f6565b60006020828403121561147257600080fd5b81356001600160e01b03198116811461075857600080fd5b60005b838110156114a557818101518382015260200161148d565b50506000910152565b60208152600082518060208401526114cd81604085016020870161148a565b601f01601f19169190910160400192915050565b80356001600160a01b03811681146114f857600080fd5b919050565b6000806040838503121561151057600080fd5b611519836114e1565b946020939093013593505050565b60008060006060848603121561153c57600080fd5b611545846114e1565b9250611553602085016114e1565b9150604084013590509250925092565b60006020828403121561157557600080fd5b5035919050565b6000806040838503121561158f57600080fd5b8235915061159f602084016114e1565b90509250929050565b6000602082840312156115ba57600080fd5b610758826114e1565b600080604083850312156115d657600080fd5b50508035926020909101359150565b600080604083850312156115f857600080fd5b611601836114e1565b915061159f602084016114e1565b600181811c9082168061162357607f821691505b60208210810361164357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103f6576103f6611649565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516116a481601785016020880161148a565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516116d581602884016020880161148a565b01602801949350505050565b634e487b7160e01b600052603260045260246000fd5b80820281158282048414176103f6576103f6611649565b634e487b7160e01b600052604160045260246000fd5b60008161173357611733611649565b506000190190565b818103818111156103f6576103f6611649565b634e487b7160e01b600052603160045260246000fdfe45524332305072657365744d696e7465725061757365723a206d75737420686165d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220869bafd8796afcbd2b83d9ab479f7920e24272bf48f6b43b28917d060a789e4d64736f6c63430008110033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var L2StateSenderArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"L2StateSender\",\n \"sourceName\": \"contracts/child/L2StateSender.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"L2StateSynced\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAX_LENGTH\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"counter\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"syncState\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610297806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806316f198311461004657806361bc221a1461005b578063a6f9885c14610076575b600080fd5b61005961005436600461017a565b61007f565b005b61006460005481565b60405190815260200160405180910390f35b61006461080081565b6001600160a01b0383166100cd5760405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b60448201526064015b60405180910390fd5b6108008111156101145760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b60448201526064016100c4565b826001600160a01b0316336001600160a01b031660008081546101369061020b565b9190508190557fedaf3c471ebd67d60c29efe34b639ede7d6a1d92eaeb3f503e784971e67118a5858560405161016d929190610232565b60405180910390a4505050565b60008060006040848603121561018f57600080fd5b83356001600160a01b03811681146101a657600080fd5b9250602084013567ffffffffffffffff808211156101c357600080fd5b818601915086601f8301126101d757600080fd5b8135818111156101e657600080fd5b8760208285010111156101f857600080fd5b6020830194508093505050509250925092565b60006001820161022b57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122041815082e2111df07ce129b83f0000ecca6c4886247dffeae7090f8f048b665164736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806316f198311461004657806361bc221a1461005b578063a6f9885c14610076575b600080fd5b61005961005436600461017a565b61007f565b005b61006460005481565b60405190815260200160405180910390f35b61006461080081565b6001600160a01b0383166100cd5760405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b60448201526064015b60405180910390fd5b6108008111156101145760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b60448201526064016100c4565b826001600160a01b0316336001600160a01b031660008081546101369061020b565b9190508190557fedaf3c471ebd67d60c29efe34b639ede7d6a1d92eaeb3f503e784971e67118a5858560405161016d929190610232565b60405180910390a4505050565b60008060006040848603121561018f57600080fd5b83356001600160a01b03811681146101a657600080fd5b9250602084013567ffffffffffffffff808211156101c357600080fd5b818601915086601f8301126101d757600080fd5b8135818111156101e657600080fd5b8760208285010111156101f857600080fd5b6020830194508093505050509250925092565b60006001820161022b57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122041815082e2111df07ce129b83f0000ecca6c4886247dffeae7090f8f048b665164736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var StateReceiverArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"StateReceiver\",\n \"sourceName\": \"contracts/child/StateReceiver.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"startId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"endId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes32\",\n \"name\": \"root\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"NewCommitment\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"counter\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"message\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"StateSyncResult\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32[][]\",\n \"name\": \"proofs\",\n \"type\": \"bytes32[][]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"internalType\": \"struct StateReceiver.StateSync[]\",\n \"name\": \"objs\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"batchExecute\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"root\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct StateReceiver.StateSyncCommitment\",\n \"name\": \"commitment\",\n \"type\": \"tuple\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"signature\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"bitmap\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"commit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"commitmentCounter\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"commitmentIds\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"commitments\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"root\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"internalType\": \"struct StateReceiver.StateSync\",\n \"name\": \"obj\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"execute\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getCommitmentByStateSyncId\",\n \"outputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"root\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct StateReceiver.StateSyncCommitment\",\n \"name\": \"\",\n \"type\": \"tuple\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getRootByStateSyncId\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"lastCommittedId\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"processedStateSyncs\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b5061148e806100206000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806355b01e4d116100ad578063ad240c2a11610071578063ad240c2a1461026a578063c59a18f714610273578063c6df461714610286578063e0563ab114610299578063eb70ef44146102a257600080fd5b806355b01e4d1461022d5780635ea5df791461023b5780639017c12714610244578063947287cf1461025757806397e5230d1461026057600080fd5b80633b878c22116100f45780633b878c221461018457806349ce89971461018d57806350d5b95b146101d757806351351d53146101ec578063544c5e0f146101fa57600080fd5b806307b3e25214610126578063196f1b2d1461015157806323e281cf14610172578063284017f51461017b575b600080fd5b6101346004600360981b0181565b6040516001600160a01b0390911681526020015b60405180910390f35b61016461015f366004610eee565b6102d7565b604051908152602001610148565b61016460325481565b61013461202081565b61013461101081565b6101bc61019b366004610eee565b60356020526000908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610148565b6101ea6101e5366004610f52565b610356565b005b6101346002600160a01b0381565b61021d610208366004610eee565b60346020526000908152604090205460ff1681565b6040519015158152602001610148565b6101346004600160991b0181565b61016461138881565b6101ea610252366004610fc1565b61041d565b61016461520881565b610164620249f081565b61016460335481565b610164610281366004610eee565b6105bd565b6101ea61029436600461106d565b6105de565b61013461203081565b6102b56102b0366004610eee565b6107c2565b6040805182518152602080840151908201529181015190820152606001610148565b6000806035816102e8603686610885565b81526020810191909152604001600020600201549050806103505760405162461bcd60e51b815260206004820152601d60248201527f537461746552656365697665723a204e4f5f524f4f545f464f525f494400000060448201526064015b60405180910390fd5b92915050565b600061036282356107c2565b80519091506103d29061037690843561110b565b82516020840151610387919061110b565b61039290600161111e565b83604001518787876040516020016103aa9190611176565b604051602081830303815290604052805190602001206109329095949392919063ffffffff16565b61040e5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa82927a7a360991b6044820152606401610347565b61041782610ace565b50505050565b828181146104805760405162461bcd60e51b815260206004820152602a60248201527f537461746552656365697665723a20554e4d4154434845445f4c454e4754485f604482015269504152414d455445525360b01b6064820152608401610347565b60005b818110156105b55760006104ba8585848181106104a2576104a2611212565b90506020028101906104b49190611228565b356107c2565b9050600061056e82600001518787868181106104d8576104d8611212565b90506020028101906104ea9190611228565b6104f591903561110b565b83516020850151610506919061110b565b61051190600161111e565b84604001518b8b8881811061052857610528611212565b905060200281019061053a9190611248565b8b8b8a81811061054c5761054c611212565b905060200281019061055e9190611228565b6040516020016103aa9190611176565b90508061057f575050600101610483565b6105ab86868581811061059457610594611212565b90506020028101906105a69190611228565b610ace565b5050600101610483565b505050505050565b603681815481106105cd57600080fd5b600091825260209091200154905081565b336002600160a01b03146106225760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b6044820152606401610347565b60335461063090600161111e565b8535146106725760405162461bcd60e51b815260206004820152601060248201526f1253959053125117d4d510549517d25160821b6044820152606401610347565b8435602086013510156106b85760405162461bcd60e51b815260206004820152600e60248201526d1253959053125117d1539117d25160921b6044820152606401610347565b604080518635602080830191909152870135818301529086013560608201526106fd906080016040516020818303038152906040528051906020012085858585610ce9565b6032805486916035916000918261071383611291565b90915550815260208082019290925260409081016000208335815591830135600183015582013560028201555050603680546001810182556000919091526020868101357f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b89092018290556033829055604080519088013581528735917f11efd893530b26afc66d488ff54cb15df117cb6e0e4a08c6dcb166d766c3bf3b910160405180910390a35050505050565b60408051606081018252600080825260208201819052918101829052906107ea603684610885565b603654909150810361084a5760405162461bcd60e51b815260206004820152602360248201527f537461746552656365697665723a204e4f5f434f4d4d49544d454e545f464f5260448201526217d25160ea1b6064820152608401610347565b600090815260356020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915292915050565b8154600090810361089857506000610350565b82546000905b808210156108e55760006108b28383610ded565b600087815260209020909150859082015411156108d1578091506108df565b6108dc81600161111e565b92505b5061089e565b60008211801561091157508361090e8661090060018661110b565b600091825260209091200190565b54145b1561092a5761092160018361110b565b92505050610350565b509392505050565b600081610940866001610e0f565b81146109855760405162461bcd60e51b81526020600482015260146024820152730929cac82989288bea0a49e9e8cbe988a9c8ea8960631b6044820152606401610347565b8587106109c95760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b6044820152606401610347565b87610a055760405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa622a0a360a11b6044820152606401610347565b8760005b82811015610abf576000868683818110610a2557610a25611212565b90506020020135905060028a610a3b91906112c0565b600003610a73576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610aa0565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b610aab60028b6112d4565b99505080610ab890611291565b9050610a09565b50909414979650505050505050565b803560009081526034602052604090205460ff1615610b3e5760405162461bcd60e51b815260206004820152602660248201527f537461746552656365697665723a2053544154455f53594e435f49535f50524f60448201526510d154d4d15160d21b6064820152608401610347565b610b4e60608201604083016112e8565b6001600160a01b03163b600003610ba2576040805160208082526000908201819052918335917f31c652130602f3ce96ceaf8a4c2b8b49f049166c6fcf2eb31943a75ec7c936ae910160405180910390a350565b8035600090815260346020526040808220805460ff191660011790558190610bd090606085019085016112e8565b6001600160a01b03168335610beb60408601602087016112e8565b610bf86060870187611303565b604051602401610c0b9493929190611349565b60408051601f198184030181529181526020820180516001600160e01b031663eeb4994560e01b17905251610c4091906113a2565b6000604051808303816000865af19150503d8060008114610c7d576040519150601f19603f3d011682016040523d82523d6000602084013e610c82565b606091505b509150915081610ca55782356000908152603460205260409020805460ff191690555b81151583600001357f31c652130602f3ce96ceaf8a4c2b8b49f049166c6fcf2eb31943a75ec7c936ae83604051610cdc91906113b4565b60405180910390a3505050565b6000806120306001600160a01b0316620249f08888888888604051602001610d159594939291906113e7565b60408051601f1981840301815290829052610d2f916113a2565b6000604051808303818686fa925050503d8060008114610d6b576040519150601f19603f3d011682016040523d82523d6000602084013e610d70565b606091505b5091509150600081806020019051810190610d8b9190611420565b9050828015610d975750805b610de35760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c45440000006044820152606401610347565b5050505050505050565b6000610dfc60028484186112d4565b610e089084841661111e565b9392505050565b600080610e1b84610e5a565b90506001836002811115610e3157610e31611442565b148015610e41575083816001901b105b610e4c576000610e4f565b60015b60ff16019392505050565b600080608083901c15610e6f57608092831c92015b604083901c15610e8157604092831c92015b602083901c15610e9357602092831c92015b601083901c15610ea557601092831c92015b600883901c15610eb757600892831c92015b600483901c15610ec957600492831c92015b600283901c15610edb57600292831c92015b600183901c156103505760010192915050565b600060208284031215610f0057600080fd5b5035919050565b60008083601f840112610f1957600080fd5b5081356001600160401b03811115610f3057600080fd5b6020830191508360208260051b8501011115610f4b57600080fd5b9250929050565b600080600060408486031215610f6757600080fd5b83356001600160401b0380821115610f7e57600080fd5b610f8a87838801610f07565b90955093506020860135915080821115610fa357600080fd5b50840160808187031215610fb657600080fd5b809150509250925092565b60008060008060408587031215610fd757600080fd5b84356001600160401b0380821115610fee57600080fd5b610ffa88838901610f07565b9096509450602087013591508082111561101357600080fd5b5061102087828801610f07565b95989497509550505050565b60008083601f84011261103e57600080fd5b5081356001600160401b0381111561105557600080fd5b602083019150836020828501011115610f4b57600080fd5b600080600080600085870360a081121561108657600080fd5b606081121561109457600080fd5b5085945060608601356001600160401b03808211156110b257600080fd5b6110be89838a0161102c565b909650945060808801359150808211156110d757600080fd5b506110e48882890161102c565b969995985093965092949392505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610350576103506110f5565b80820180821115610350576103506110f5565b80356001600160a01b038116811461114857600080fd5b919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815281356020820152600061118f60208401611131565b60018060a01b038082166040850152806111ab60408701611131565b16606085015250506060830135601e198436030181126111ca57600080fd5b83016020810190356001600160401b038111156111e657600080fd5b8036038213156111f557600080fd5b60808085015261120960a08501828461114d565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261123e57600080fd5b9190910192915050565b6000808335601e1984360301811261125f57600080fd5b8301803591506001600160401b0382111561127957600080fd5b6020019150600581901b3603821315610f4b57600080fd5b6000600182016112a3576112a36110f5565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826112cf576112cf6112aa565b500690565b6000826112e3576112e36112aa565b500490565b6000602082840312156112fa57600080fd5b610e0882611131565b6000808335601e1984360301811261131a57600080fd5b8301803591506001600160401b0382111561133457600080fd5b602001915036819003821315610f4b57600080fd5b8481526001600160a01b0384166020820152606060408201819052600090611374908301848661114d565b9695505050505050565b60005b83811015611399578181015183820152602001611381565b50506000910152565b6000825161123e81846020870161137e565b60208152600082518060208401526113d381604085016020870161137e565b601f01601f19169190910160400192915050565b85815260606020820152600061140160608301868861114d565b828103604084015261141481858761114d565b98975050505050505050565b60006020828403121561143257600080fd5b81518015158114610e0857600080fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220b20879873df719d87d6f5bd189c1e73b75a62db3cf5246e748eddebe4b54eacd64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101215760003560e01c806355b01e4d116100ad578063ad240c2a11610071578063ad240c2a1461026a578063c59a18f714610273578063c6df461714610286578063e0563ab114610299578063eb70ef44146102a257600080fd5b806355b01e4d1461022d5780635ea5df791461023b5780639017c12714610244578063947287cf1461025757806397e5230d1461026057600080fd5b80633b878c22116100f45780633b878c221461018457806349ce89971461018d57806350d5b95b146101d757806351351d53146101ec578063544c5e0f146101fa57600080fd5b806307b3e25214610126578063196f1b2d1461015157806323e281cf14610172578063284017f51461017b575b600080fd5b6101346004600360981b0181565b6040516001600160a01b0390911681526020015b60405180910390f35b61016461015f366004610eee565b6102d7565b604051908152602001610148565b61016460325481565b61013461202081565b61013461101081565b6101bc61019b366004610eee565b60356020526000908152604090208054600182015460029092015490919083565b60408051938452602084019290925290820152606001610148565b6101ea6101e5366004610f52565b610356565b005b6101346002600160a01b0381565b61021d610208366004610eee565b60346020526000908152604090205460ff1681565b6040519015158152602001610148565b6101346004600160991b0181565b61016461138881565b6101ea610252366004610fc1565b61041d565b61016461520881565b610164620249f081565b61016460335481565b610164610281366004610eee565b6105bd565b6101ea61029436600461106d565b6105de565b61013461203081565b6102b56102b0366004610eee565b6107c2565b6040805182518152602080840151908201529181015190820152606001610148565b6000806035816102e8603686610885565b81526020810191909152604001600020600201549050806103505760405162461bcd60e51b815260206004820152601d60248201527f537461746552656365697665723a204e4f5f524f4f545f464f525f494400000060448201526064015b60405180910390fd5b92915050565b600061036282356107c2565b80519091506103d29061037690843561110b565b82516020840151610387919061110b565b61039290600161111e565b83604001518787876040516020016103aa9190611176565b604051602081830303815290604052805190602001206109329095949392919063ffffffff16565b61040e5760405162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22fa82927a7a360991b6044820152606401610347565b61041782610ace565b50505050565b828181146104805760405162461bcd60e51b815260206004820152602a60248201527f537461746552656365697665723a20554e4d4154434845445f4c454e4754485f604482015269504152414d455445525360b01b6064820152608401610347565b60005b818110156105b55760006104ba8585848181106104a2576104a2611212565b90506020028101906104b49190611228565b356107c2565b9050600061056e82600001518787868181106104d8576104d8611212565b90506020028101906104ea9190611228565b6104f591903561110b565b83516020850151610506919061110b565b61051190600161111e565b84604001518b8b8881811061052857610528611212565b905060200281019061053a9190611248565b8b8b8a81811061054c5761054c611212565b905060200281019061055e9190611228565b6040516020016103aa9190611176565b90508061057f575050600101610483565b6105ab86868581811061059457610594611212565b90506020028101906105a69190611228565b610ace565b5050600101610483565b505050505050565b603681815481106105cd57600080fd5b600091825260209091200154905081565b336002600160a01b03146106225760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b6044820152606401610347565b60335461063090600161111e565b8535146106725760405162461bcd60e51b815260206004820152601060248201526f1253959053125117d4d510549517d25160821b6044820152606401610347565b8435602086013510156106b85760405162461bcd60e51b815260206004820152600e60248201526d1253959053125117d1539117d25160921b6044820152606401610347565b604080518635602080830191909152870135818301529086013560608201526106fd906080016040516020818303038152906040528051906020012085858585610ce9565b6032805486916035916000918261071383611291565b90915550815260208082019290925260409081016000208335815591830135600183015582013560028201555050603680546001810182556000919091526020868101357f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b89092018290556033829055604080519088013581528735917f11efd893530b26afc66d488ff54cb15df117cb6e0e4a08c6dcb166d766c3bf3b910160405180910390a35050505050565b60408051606081018252600080825260208201819052918101829052906107ea603684610885565b603654909150810361084a5760405162461bcd60e51b815260206004820152602360248201527f537461746552656365697665723a204e4f5f434f4d4d49544d454e545f464f5260448201526217d25160ea1b6064820152608401610347565b600090815260356020908152604091829020825160608101845281548152600182015492810192909252600201549181019190915292915050565b8154600090810361089857506000610350565b82546000905b808210156108e55760006108b28383610ded565b600087815260209020909150859082015411156108d1578091506108df565b6108dc81600161111e565b92505b5061089e565b60008211801561091157508361090e8661090060018661110b565b600091825260209091200190565b54145b1561092a5761092160018361110b565b92505050610350565b509392505050565b600081610940866001610e0f565b81146109855760405162461bcd60e51b81526020600482015260146024820152730929cac82989288bea0a49e9e8cbe988a9c8ea8960631b6044820152606401610347565b8587106109c95760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b6044820152606401610347565b87610a055760405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa622a0a360a11b6044820152606401610347565b8760005b82811015610abf576000868683818110610a2557610a25611212565b90506020020135905060028a610a3b91906112c0565b600003610a73576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610aa0565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b610aab60028b6112d4565b99505080610ab890611291565b9050610a09565b50909414979650505050505050565b803560009081526034602052604090205460ff1615610b3e5760405162461bcd60e51b815260206004820152602660248201527f537461746552656365697665723a2053544154455f53594e435f49535f50524f60448201526510d154d4d15160d21b6064820152608401610347565b610b4e60608201604083016112e8565b6001600160a01b03163b600003610ba2576040805160208082526000908201819052918335917f31c652130602f3ce96ceaf8a4c2b8b49f049166c6fcf2eb31943a75ec7c936ae910160405180910390a350565b8035600090815260346020526040808220805460ff191660011790558190610bd090606085019085016112e8565b6001600160a01b03168335610beb60408601602087016112e8565b610bf86060870187611303565b604051602401610c0b9493929190611349565b60408051601f198184030181529181526020820180516001600160e01b031663eeb4994560e01b17905251610c4091906113a2565b6000604051808303816000865af19150503d8060008114610c7d576040519150601f19603f3d011682016040523d82523d6000602084013e610c82565b606091505b509150915081610ca55782356000908152603460205260409020805460ff191690555b81151583600001357f31c652130602f3ce96ceaf8a4c2b8b49f049166c6fcf2eb31943a75ec7c936ae83604051610cdc91906113b4565b60405180910390a3505050565b6000806120306001600160a01b0316620249f08888888888604051602001610d159594939291906113e7565b60408051601f1981840301815290829052610d2f916113a2565b6000604051808303818686fa925050503d8060008114610d6b576040519150601f19603f3d011682016040523d82523d6000602084013e610d70565b606091505b5091509150600081806020019051810190610d8b9190611420565b9050828015610d975750805b610de35760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c45440000006044820152606401610347565b5050505050505050565b6000610dfc60028484186112d4565b610e089084841661111e565b9392505050565b600080610e1b84610e5a565b90506001836002811115610e3157610e31611442565b148015610e41575083816001901b105b610e4c576000610e4f565b60015b60ff16019392505050565b600080608083901c15610e6f57608092831c92015b604083901c15610e8157604092831c92015b602083901c15610e9357602092831c92015b601083901c15610ea557601092831c92015b600883901c15610eb757600892831c92015b600483901c15610ec957600492831c92015b600283901c15610edb57600292831c92015b600183901c156103505760010192915050565b600060208284031215610f0057600080fd5b5035919050565b60008083601f840112610f1957600080fd5b5081356001600160401b03811115610f3057600080fd5b6020830191508360208260051b8501011115610f4b57600080fd5b9250929050565b600080600060408486031215610f6757600080fd5b83356001600160401b0380821115610f7e57600080fd5b610f8a87838801610f07565b90955093506020860135915080821115610fa357600080fd5b50840160808187031215610fb657600080fd5b809150509250925092565b60008060008060408587031215610fd757600080fd5b84356001600160401b0380821115610fee57600080fd5b610ffa88838901610f07565b9096509450602087013591508082111561101357600080fd5b5061102087828801610f07565b95989497509550505050565b60008083601f84011261103e57600080fd5b5081356001600160401b0381111561105557600080fd5b602083019150836020828501011115610f4b57600080fd5b600080600080600085870360a081121561108657600080fd5b606081121561109457600080fd5b5085945060608601356001600160401b03808211156110b257600080fd5b6110be89838a0161102c565b909650945060808801359150808211156110d757600080fd5b506110e48882890161102c565b969995985093965092949392505050565b634e487b7160e01b600052601160045260246000fd5b81810381811115610350576103506110f5565b80820180821115610350576103506110f5565b80356001600160a01b038116811461114857600080fd5b919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815281356020820152600061118f60208401611131565b60018060a01b038082166040850152806111ab60408701611131565b16606085015250506060830135601e198436030181126111ca57600080fd5b83016020810190356001600160401b038111156111e657600080fd5b8036038213156111f557600080fd5b60808085015261120960a08501828461114d565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261123e57600080fd5b9190910192915050565b6000808335601e1984360301811261125f57600080fd5b8301803591506001600160401b0382111561127957600080fd5b6020019150600581901b3603821315610f4b57600080fd5b6000600182016112a3576112a36110f5565b5060010190565b634e487b7160e01b600052601260045260246000fd5b6000826112cf576112cf6112aa565b500690565b6000826112e3576112e36112aa565b500490565b6000602082840312156112fa57600080fd5b610e0882611131565b6000808335601e1984360301811261131a57600080fd5b8301803591506001600160401b0382111561133457600080fd5b602001915036819003821315610f4b57600080fd5b8481526001600160a01b0384166020820152606060408201819052600090611374908301848661114d565b9695505050505050565b60005b83811015611399578181015183820152602001611381565b50506000910152565b6000825161123e81846020870161137e565b60208152600082518060208401526113d381604085016020870161137e565b601f01601f19169190910160400192915050565b85815260606020820152600061140160608301868861114d565b828103604084015261141481858761114d565b98975050505050505050565b60006020828403121561143257600080fd5b81518015158114610e0857600080fd5b634e487b7160e01b600052602160045260246000fdfea2646970667358221220b20879873df719d87d6f5bd189c1e73b75a62db3cf5246e748eddebe4b54eacd64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var NativeERC20Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"NativeERC20\",\n \"sourceName\": \"contracts/child/NativeERC20.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"predicate_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"rootToken_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"name_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"symbol_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"decimals_\",\n \"type\": \"uint8\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenSupply_\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b5061121c806100206000396000f3fe608060405234801561001057600080fd5b50600436106101635760003560e01c806355b01e4d116100ce57806397e5230d1161008757806397e5230d146102b85780639dc29fac146102c2578063a457c2d7146102d5578063a9059cbb146102e8578063dd62ed3e146102fb578063e0563ab11461030e578063e61987051461031757600080fd5b806355b01e4d146102605780635ea5df791461026e57806370a0823114610277578063740b08dc14610292578063947287cf146102a757806395d89b41146102b057600080fd5b8063284017f511610120578063284017f514610205578063313ce5671461020e57806339509351146102235780633b878c221461023657806340c10f191461023f57806351351d531461025257600080fd5b806306fdde031461016857806307b3e25214610186578063095ea7b3146101ac57806318160ddd146101cf5780631f2d0065146101e157806323b872dd146101f2575b600080fd5b610170610328565b60405161017d9190610d4d565b60405180910390f35b6101946004600360981b0181565b6040516001600160a01b03909116815260200161017d565b6101bf6101ba366004610d9c565b6103ba565b604051901515815260200161017d565b6034545b60405190815260200161017d565b6036546001600160a01b0316610194565b6101bf610200366004610dc6565b6103d4565b61019461202081565b60395460405160ff909116815260200161017d565b6101bf610231366004610d9c565b6103f8565b61019461101081565b6101bf61024d366004610d9c565b61041a565b6101946002600160a01b0381565b6101946004600160991b0181565b6101d361138881565b6101d3610285366004610e02565b6001600160a01b03163190565b6102a56102a0366004610e6d565b610463565b005b6101d361520881565b610170610618565b6101d3620249f081565b6101bf6102d0366004610d9c565b610627565b6101bf6102e3366004610d9c565b61065e565b6101bf6102f6366004610d9c565b6106d9565b6101d3610309366004610f21565b6106e7565b61019461203081565b6035546001600160a01b0316610194565b60606037805461033790610f54565b80601f016020809104026020016040519081016040528092919081815260200182805461036390610f54565b80156103b05780601f10610385576101008083540402835291602001916103b0565b820191906000526020600020905b81548152906001019060200180831161039357829003601f168201915b5050505050905090565b6000336103c8818585610712565b60019150505b92915050565b6000336103e2858285610836565b6103ed8585856108b0565b506001949350505050565b6000336103c881858561040b83836106e7565b6104159190610fa4565b610712565b6035546000906001600160a01b031633146104505760405162461bcd60e51b815260040161044790610fb7565b60405180910390fd5b61045a8383610a75565b50600192915050565b600054610100900460ff16158080156104835750600054600160ff909116105b8061049d5750303b15801561049d575060005460ff166001145b6105005760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610447565b6000805460ff191660011790558015610523576000805461ff0019166101001790555b336002600160a01b03146105675760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b6044820152606401610447565b603580546001600160a01b03808c166001600160a01b03199283161790925560368054928b169290911691909117905560376105a4878983611060565b5060386105b2858783611060565b506039805460ff191660ff85161790556034829055801561060d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b60606038805461033790610f54565b6035546000906001600160a01b031633146106545760405162461bcd60e51b815260040161044790610fb7565b61045a8383610bcf565b6000338161066c82866106e7565b9050838110156106cc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610447565b6103ed8286868403610712565b6000336103c88185856108b0565b6001600160a01b03918216600090815260336020908152604080832093909416825291909152205490565b6001600160a01b0383166107745760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610447565b6001600160a01b0382166107d55760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610447565b6001600160a01b0383811660008181526033602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061084284846106e7565b905060001981146108aa578181101561089d5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610447565b6108aa8484848403610712565b50505050565b6001600160a01b0383166109145760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610447565b6001600160a01b0382166109765760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610447565b6000806120206001600160a01b031685858560405160200161099a93929190611121565b60408051601f19818403018152908290526109b491611145565b6000604051808303816000865af19150503d80600081146109f1576040519150601f19603f3d011682016040523d82523d6000602084013e6109f6565b606091505b5091509150818015610a17575080806020019051810190610a179190611161565b610a335760405162461bcd60e51b815260040161044790611183565b836001600160a01b0316856001600160a01b03166000805160206111c783398151915285604051610a6691815260200190565b60405180910390a35050505050565b6001600160a01b038216610acb5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610447565b8060346000828254610add9190610fa4565b9091555050604051600090819061202090610b0090839087908790602001611121565b60408051601f1981840301815290829052610b1a91611145565b6000604051808303816000865af19150503d8060008114610b57576040519150601f19603f3d011682016040523d82523d6000602084013e610b5c565b606091505b5091509150818015610b7d575080806020019051810190610b7d9190611161565b610b995760405162461bcd60e51b815260040161044790611183565b6040518381526001600160a01b038516906000906000805160206111c7833981519152906020015b60405180910390a350505050565b6001600160a01b038216610c2f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610447565b8060346000828254610c4191906111b3565b9091555050604051600090819061202090610c6490869084908790602001611121565b60408051601f1981840301815290829052610c7e91611145565b6000604051808303816000865af19150503d8060008114610cbb576040519150601f19603f3d011682016040523d82523d6000602084013e610cc0565b606091505b5091509150818015610ce1575080806020019051810190610ce19190611161565b610cfd5760405162461bcd60e51b815260040161044790611183565b6040518381526000906001600160a01b038616906000805160206111c783398151915290602001610bc1565b60005b83811015610d44578181015183820152602001610d2c565b50506000910152565b6020815260008251806020840152610d6c816040850160208701610d29565b601f01601f19169190910160400192915050565b80356001600160a01b0381168114610d9757600080fd5b919050565b60008060408385031215610daf57600080fd5b610db883610d80565b946020939093013593505050565b600080600060608486031215610ddb57600080fd5b610de484610d80565b9250610df260208501610d80565b9150604084013590509250925092565b600060208284031215610e1457600080fd5b610e1d82610d80565b9392505050565b60008083601f840112610e3657600080fd5b50813567ffffffffffffffff811115610e4e57600080fd5b602083019150836020828501011115610e6657600080fd5b9250929050565b60008060008060008060008060c0898b031215610e8957600080fd5b610e9289610d80565b9750610ea060208a01610d80565b9650604089013567ffffffffffffffff80821115610ebd57600080fd5b610ec98c838d01610e24565b909850965060608b0135915080821115610ee257600080fd5b50610eef8b828c01610e24565b909550935050608089013560ff81168114610f0957600080fd5b8092505060a089013590509295985092959890939650565b60008060408385031215610f3457600080fd5b610f3d83610d80565b9150610f4b60208401610d80565b90509250929050565b600181811c90821680610f6857607f821691505b602082108103610f8857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103ce576103ce610f8e565b60208082526024908201527f4e617469766545524332303a204f6e6c79207072656469636174652063616e2060408201526318d85b1b60e21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561105b57600081815260208120601f850160051c810160208610156110385750805b601f850160051c820191505b8181101561105757828155600101611044565b5050505b505050565b67ffffffffffffffff83111561107857611078610ffb565b61108c836110868354610f54565b83611011565b6000601f8411600181146110c057600085156110a85750838201355b600019600387901b1c1916600186901b17835561111a565b600083815260209020601f19861690835b828110156110f157868501358255602094850194600190920191016110d1565b508682101561110e5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60008251611157818460208701610d29565b9190910192915050565b60006020828403121561117357600080fd5b81518015158114610e1d57600080fd5b60208082526016908201527514149150d3d35412531157d0d0531317d1905253115160521b604082015260600190565b818103818111156103ce576103ce610f8e56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220eff294dba2996c4337f07acdacd5b73dff2185b61e8f1aa3c312a46098b8b16e64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101635760003560e01c806355b01e4d116100ce57806397e5230d1161008757806397e5230d146102b85780639dc29fac146102c2578063a457c2d7146102d5578063a9059cbb146102e8578063dd62ed3e146102fb578063e0563ab11461030e578063e61987051461031757600080fd5b806355b01e4d146102605780635ea5df791461026e57806370a0823114610277578063740b08dc14610292578063947287cf146102a757806395d89b41146102b057600080fd5b8063284017f511610120578063284017f514610205578063313ce5671461020e57806339509351146102235780633b878c221461023657806340c10f191461023f57806351351d531461025257600080fd5b806306fdde031461016857806307b3e25214610186578063095ea7b3146101ac57806318160ddd146101cf5780631f2d0065146101e157806323b872dd146101f2575b600080fd5b610170610328565b60405161017d9190610d4d565b60405180910390f35b6101946004600360981b0181565b6040516001600160a01b03909116815260200161017d565b6101bf6101ba366004610d9c565b6103ba565b604051901515815260200161017d565b6034545b60405190815260200161017d565b6036546001600160a01b0316610194565b6101bf610200366004610dc6565b6103d4565b61019461202081565b60395460405160ff909116815260200161017d565b6101bf610231366004610d9c565b6103f8565b61019461101081565b6101bf61024d366004610d9c565b61041a565b6101946002600160a01b0381565b6101946004600160991b0181565b6101d361138881565b6101d3610285366004610e02565b6001600160a01b03163190565b6102a56102a0366004610e6d565b610463565b005b6101d361520881565b610170610618565b6101d3620249f081565b6101bf6102d0366004610d9c565b610627565b6101bf6102e3366004610d9c565b61065e565b6101bf6102f6366004610d9c565b6106d9565b6101d3610309366004610f21565b6106e7565b61019461203081565b6035546001600160a01b0316610194565b60606037805461033790610f54565b80601f016020809104026020016040519081016040528092919081815260200182805461036390610f54565b80156103b05780601f10610385576101008083540402835291602001916103b0565b820191906000526020600020905b81548152906001019060200180831161039357829003601f168201915b5050505050905090565b6000336103c8818585610712565b60019150505b92915050565b6000336103e2858285610836565b6103ed8585856108b0565b506001949350505050565b6000336103c881858561040b83836106e7565b6104159190610fa4565b610712565b6035546000906001600160a01b031633146104505760405162461bcd60e51b815260040161044790610fb7565b60405180910390fd5b61045a8383610a75565b50600192915050565b600054610100900460ff16158080156104835750600054600160ff909116105b8061049d5750303b15801561049d575060005460ff166001145b6105005760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610447565b6000805460ff191660011790558015610523576000805461ff0019166101001790555b336002600160a01b03146105675760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b6044820152606401610447565b603580546001600160a01b03808c166001600160a01b03199283161790925560368054928b169290911691909117905560376105a4878983611060565b5060386105b2858783611060565b506039805460ff191660ff85161790556034829055801561060d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b60606038805461033790610f54565b6035546000906001600160a01b031633146106545760405162461bcd60e51b815260040161044790610fb7565b61045a8383610bcf565b6000338161066c82866106e7565b9050838110156106cc5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610447565b6103ed8286868403610712565b6000336103c88185856108b0565b6001600160a01b03918216600090815260336020908152604080832093909416825291909152205490565b6001600160a01b0383166107745760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610447565b6001600160a01b0382166107d55760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610447565b6001600160a01b0383811660008181526033602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b600061084284846106e7565b905060001981146108aa578181101561089d5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610447565b6108aa8484848403610712565b50505050565b6001600160a01b0383166109145760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610447565b6001600160a01b0382166109765760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610447565b6000806120206001600160a01b031685858560405160200161099a93929190611121565b60408051601f19818403018152908290526109b491611145565b6000604051808303816000865af19150503d80600081146109f1576040519150601f19603f3d011682016040523d82523d6000602084013e6109f6565b606091505b5091509150818015610a17575080806020019051810190610a179190611161565b610a335760405162461bcd60e51b815260040161044790611183565b836001600160a01b0316856001600160a01b03166000805160206111c783398151915285604051610a6691815260200190565b60405180910390a35050505050565b6001600160a01b038216610acb5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610447565b8060346000828254610add9190610fa4565b9091555050604051600090819061202090610b0090839087908790602001611121565b60408051601f1981840301815290829052610b1a91611145565b6000604051808303816000865af19150503d8060008114610b57576040519150601f19603f3d011682016040523d82523d6000602084013e610b5c565b606091505b5091509150818015610b7d575080806020019051810190610b7d9190611161565b610b995760405162461bcd60e51b815260040161044790611183565b6040518381526001600160a01b038516906000906000805160206111c7833981519152906020015b60405180910390a350505050565b6001600160a01b038216610c2f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610447565b8060346000828254610c4191906111b3565b9091555050604051600090819061202090610c6490869084908790602001611121565b60408051601f1981840301815290829052610c7e91611145565b6000604051808303816000865af19150503d8060008114610cbb576040519150601f19603f3d011682016040523d82523d6000602084013e610cc0565b606091505b5091509150818015610ce1575080806020019051810190610ce19190611161565b610cfd5760405162461bcd60e51b815260040161044790611183565b6040518381526000906001600160a01b038616906000805160206111c783398151915290602001610bc1565b60005b83811015610d44578181015183820152602001610d2c565b50506000910152565b6020815260008251806020840152610d6c816040850160208701610d29565b601f01601f19169190910160400192915050565b80356001600160a01b0381168114610d9757600080fd5b919050565b60008060408385031215610daf57600080fd5b610db883610d80565b946020939093013593505050565b600080600060608486031215610ddb57600080fd5b610de484610d80565b9250610df260208501610d80565b9150604084013590509250925092565b600060208284031215610e1457600080fd5b610e1d82610d80565b9392505050565b60008083601f840112610e3657600080fd5b50813567ffffffffffffffff811115610e4e57600080fd5b602083019150836020828501011115610e6657600080fd5b9250929050565b60008060008060008060008060c0898b031215610e8957600080fd5b610e9289610d80565b9750610ea060208a01610d80565b9650604089013567ffffffffffffffff80821115610ebd57600080fd5b610ec98c838d01610e24565b909850965060608b0135915080821115610ee257600080fd5b50610eef8b828c01610e24565b909550935050608089013560ff81168114610f0957600080fd5b8092505060a089013590509295985092959890939650565b60008060408385031215610f3457600080fd5b610f3d83610d80565b9150610f4b60208401610d80565b90509250929050565b600181811c90821680610f6857607f821691505b602082108103610f8857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103ce576103ce610f8e565b60208082526024908201527f4e617469766545524332303a204f6e6c79207072656469636174652063616e2060408201526318d85b1b60e21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561105b57600081815260208120601f850160051c810160208610156110385750805b601f850160051c820191505b8181101561105757828155600101611044565b5050505b505050565b67ffffffffffffffff83111561107857611078610ffb565b61108c836110868354610f54565b83611011565b6000601f8411600181146110c057600085156110a85750838201355b600019600387901b1c1916600186901b17835561111a565b600083815260209020601f19861690835b828110156110f157868501358255602094850194600190920191016110d1565b508682101561110e5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60008251611157818460208701610d29565b9190910192915050565b60006020828403121561117357600080fd5b81518015158114610e1d57600080fd5b60208082526016908201527514149150d3d35412531157d0d0531317d1905253115160521b604082015260600190565b818103818111156103ce576103ce610f8e56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220eff294dba2996c4337f07acdacd5b73dff2185b61e8f1aa3c312a46098b8b16e64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var NativeERC20MintableArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"NativeERC20Mintable\",\n \"sourceName\": \"contracts/child/NativeERC20Mintable.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"predicate_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"owner_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"rootToken_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"name_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"symbol_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"decimals_\",\n \"type\": \"uint8\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenSupply_\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b5061001a3361001f565b61008d565b603480546001600160a01b03191690556100388161003b565b50565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b61150a8061009c6000396000f3fe608060405234801561001057600080fd5b506004361061019a5760003560e01c806370a08231116100e45780639dc29fac116100925780639dc29fac1461031a578063a457c2d71461032d578063a9059cbb14610340578063dd62ed3e14610353578063e0563ab114610366578063e30c39781461036f578063e619870514610380578063f2fde38b1461039157600080fd5b806370a08231146102c3578063715018a6146102de57806379ba5097146102e65780638da5cb5b146102ee578063947287cf146102ff57806395d89b411461030857806397e5230d1461031057600080fd5b8063313ce5671161014c578063313ce56714610245578063395093511461025a5780633b878c221461026d57806340c10f191461027657806351351d531461028957806355b01e4d146102975780635ea5df79146102a55780636091636b146102ae57600080fd5b806306fdde031461019f57806307b3e252146101bd578063095ea7b3146101e357806318160ddd146102065780631f2d00651461021857806323b872dd14610229578063284017f51461023c575b600080fd5b6101a76103a4565b6040516101b49190611022565b60405180910390f35b6101cb6004600360981b0181565b6040516001600160a01b0390911681526020016101b4565b6101f66101f1366004611071565b610436565b60405190151581526020016101b4565b6036545b6040519081526020016101b4565b6038546001600160a01b03166101cb565b6101f661023736600461109b565b610450565b6101cb61202081565b603b5460405160ff90911681526020016101b4565b6101f6610268366004611071565b610474565b6101cb61101081565b6101f6610284366004611071565b610496565b6101cb6002600160a01b0381565b6101cb6004600160991b0181565b61020a61138881565b6102c16102bc366004611120565b6104f4565b005b61020a6102d13660046111e4565b6001600160a01b03163190565b6102c1610714565b6102c1610728565b6033546001600160a01b03166101cb565b61020a61520881565b6101a76107a2565b61020a620249f081565b6101f6610328366004611071565b6107b1565b6101f661033b366004611071565b6107fd565b6101f661034e366004611071565b610878565b61020a610361366004611206565b610886565b6101cb61203081565b6034546001600160a01b03166101cb565b6037546001600160a01b03166101cb565b6102c161039f3660046111e4565b6108b1565b6060603980546103b390611239565b80601f01602080910402602001604051908101604052809291908181526020018280546103df90611239565b801561042c5780601f106104015761010080835404028352916020019161042c565b820191906000526020600020905b81548152906001019060200180831161040f57829003601f168201915b5050505050905090565b600033610444818585610922565b60019150505b92915050565b60003361045e858285610a46565b610469858585610ac0565b506001949350505050565b6000336104448185856104878383610886565b6104919190611289565b610922565b6037546000906001600160a01b03163314806104bc57506033546001600160a01b031633145b6104e15760405162461bcd60e51b81526004016104d89061129c565b60405180910390fd5b6104eb8383610c85565b50600192915050565b600054610100900460ff16158080156105145750600054600160ff909116105b8061052e5750303b15801561052e575060005460ff166001145b6105915760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016104d8565b6000805460ff1916600117905580156105b4576000805461ff0019166101001790555b336002600160a01b03146105f85760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064016104d8565b6001600160a01b0389166106595760405162461bcd60e51b815260206004820152602260248201527f4e617469766545524332303a20496e76616c6964206f776e6572206164647265604482015261737360f01b60648201526084016104d8565b603780546001600160a01b03808d166001600160a01b03199283161790925560388054928b1692909116919091179055603961069687898361134e565b50603a6106a485878361134e565b50603b805460ff191660ff851617905560368290556106c289610ddf565b8015610708576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61071c610df8565b6107266000610ddf565b565b60345433906001600160a01b031681146107965760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016104d8565b61079f81610ddf565b50565b6060603a80546103b390611239565b6037546000906001600160a01b03163314806107d757506033546001600160a01b031633145b6107f35760405162461bcd60e51b81526004016104d89061129c565b6104eb8383610e52565b6000338161080b8286610886565b90508381101561086b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016104d8565b6104698286868403610922565b600033610444818585610ac0565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6108b9610df8565b603480546001600160a01b0383166001600160a01b031990911681179091556108ea6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6001600160a01b0383166109845760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016104d8565b6001600160a01b0382166109e55760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016104d8565b6001600160a01b0383811660008181526035602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000610a528484610886565b90506000198114610aba5781811015610aad5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016104d8565b610aba8484848403610922565b50505050565b6001600160a01b038316610b245760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016104d8565b6001600160a01b038216610b865760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016104d8565b6000806120206001600160a01b0316858585604051602001610baa9392919061140f565b60408051601f1981840301815290829052610bc491611433565b6000604051808303816000865af19150503d8060008114610c01576040519150601f19603f3d011682016040523d82523d6000602084013e610c06565b606091505b5091509150818015610c27575080806020019051810190610c27919061144f565b610c435760405162461bcd60e51b81526004016104d890611471565b836001600160a01b0316856001600160a01b03166000805160206114b583398151915285604051610c7691815260200190565b60405180910390a35050505050565b6001600160a01b038216610cdb5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016104d8565b8060366000828254610ced9190611289565b9091555050604051600090819061202090610d109083908790879060200161140f565b60408051601f1981840301815290829052610d2a91611433565b6000604051808303816000865af19150503d8060008114610d67576040519150601f19603f3d011682016040523d82523d6000602084013e610d6c565b606091505b5091509150818015610d8d575080806020019051810190610d8d919061144f565b610da95760405162461bcd60e51b81526004016104d890611471565b6040518381526001600160a01b038516906000906000805160206114b5833981519152906020015b60405180910390a350505050565b603480546001600160a01b031916905561079f81610fac565b6033546001600160a01b031633146107265760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104d8565b6001600160a01b038216610eb25760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016104d8565b8060366000828254610ec491906114a1565b9091555050604051600090819061202090610ee79086908490879060200161140f565b60408051601f1981840301815290829052610f0191611433565b6000604051808303816000865af19150503d8060008114610f3e576040519150601f19603f3d011682016040523d82523d6000602084013e610f43565b606091505b5091509150818015610f64575080806020019051810190610f64919061144f565b610f805760405162461bcd60e51b81526004016104d890611471565b6040518381526000906001600160a01b038616906000805160206114b583398151915290602001610dd1565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60005b83811015611019578181015183820152602001611001565b50506000910152565b6020815260008251806020840152611041816040850160208701610ffe565b601f01601f19169190910160400192915050565b80356001600160a01b038116811461106c57600080fd5b919050565b6000806040838503121561108457600080fd5b61108d83611055565b946020939093013593505050565b6000806000606084860312156110b057600080fd5b6110b984611055565b92506110c760208501611055565b9150604084013590509250925092565b60008083601f8401126110e957600080fd5b50813567ffffffffffffffff81111561110157600080fd5b60208301915083602082850101111561111957600080fd5b9250929050565b600080600080600080600080600060e08a8c03121561113e57600080fd5b6111478a611055565b985061115560208b01611055565b975061116360408b01611055565b965060608a013567ffffffffffffffff8082111561118057600080fd5b61118c8d838e016110d7565b909850965060808c01359150808211156111a557600080fd5b506111b28c828d016110d7565b90955093505060a08a013560ff811681146111cc57600080fd5b8092505060c08a013590509295985092959850929598565b6000602082840312156111f657600080fd5b6111ff82611055565b9392505050565b6000806040838503121561121957600080fd5b61122283611055565b915061123060208401611055565b90509250929050565b600181811c9082168061124d57607f821691505b60208210810361126d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561044a5761044a611273565b6020808252602d908201527f4e617469766545524332303a204f6e6c7920707265646963617465206f72206f60408201526c1ddb995c8818d85b8818d85b1b609a1b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561134957600081815260208120601f850160051c810160208610156113265750805b601f850160051c820191505b8181101561134557828155600101611332565b5050505b505050565b67ffffffffffffffff831115611366576113666112e9565b61137a836113748354611239565b836112ff565b6000601f8411600181146113ae57600085156113965750838201355b600019600387901b1c1916600186901b178355611408565b600083815260209020601f19861690835b828110156113df57868501358255602094850194600190920191016113bf565b50868210156113fc5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60008251611445818460208701610ffe565b9190910192915050565b60006020828403121561146157600080fd5b815180151581146111ff57600080fd5b60208082526016908201527514149150d3d35412531157d0d0531317d1905253115160521b604082015260600190565b8181038181111561044a5761044a61127356feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122019716c645080b1365563f01a6cdf0f363af3491e7cb3880150d6d1f3389f759364736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061019a5760003560e01c806370a08231116100e45780639dc29fac116100925780639dc29fac1461031a578063a457c2d71461032d578063a9059cbb14610340578063dd62ed3e14610353578063e0563ab114610366578063e30c39781461036f578063e619870514610380578063f2fde38b1461039157600080fd5b806370a08231146102c3578063715018a6146102de57806379ba5097146102e65780638da5cb5b146102ee578063947287cf146102ff57806395d89b411461030857806397e5230d1461031057600080fd5b8063313ce5671161014c578063313ce56714610245578063395093511461025a5780633b878c221461026d57806340c10f191461027657806351351d531461028957806355b01e4d146102975780635ea5df79146102a55780636091636b146102ae57600080fd5b806306fdde031461019f57806307b3e252146101bd578063095ea7b3146101e357806318160ddd146102065780631f2d00651461021857806323b872dd14610229578063284017f51461023c575b600080fd5b6101a76103a4565b6040516101b49190611022565b60405180910390f35b6101cb6004600360981b0181565b6040516001600160a01b0390911681526020016101b4565b6101f66101f1366004611071565b610436565b60405190151581526020016101b4565b6036545b6040519081526020016101b4565b6038546001600160a01b03166101cb565b6101f661023736600461109b565b610450565b6101cb61202081565b603b5460405160ff90911681526020016101b4565b6101f6610268366004611071565b610474565b6101cb61101081565b6101f6610284366004611071565b610496565b6101cb6002600160a01b0381565b6101cb6004600160991b0181565b61020a61138881565b6102c16102bc366004611120565b6104f4565b005b61020a6102d13660046111e4565b6001600160a01b03163190565b6102c1610714565b6102c1610728565b6033546001600160a01b03166101cb565b61020a61520881565b6101a76107a2565b61020a620249f081565b6101f6610328366004611071565b6107b1565b6101f661033b366004611071565b6107fd565b6101f661034e366004611071565b610878565b61020a610361366004611206565b610886565b6101cb61203081565b6034546001600160a01b03166101cb565b6037546001600160a01b03166101cb565b6102c161039f3660046111e4565b6108b1565b6060603980546103b390611239565b80601f01602080910402602001604051908101604052809291908181526020018280546103df90611239565b801561042c5780601f106104015761010080835404028352916020019161042c565b820191906000526020600020905b81548152906001019060200180831161040f57829003601f168201915b5050505050905090565b600033610444818585610922565b60019150505b92915050565b60003361045e858285610a46565b610469858585610ac0565b506001949350505050565b6000336104448185856104878383610886565b6104919190611289565b610922565b6037546000906001600160a01b03163314806104bc57506033546001600160a01b031633145b6104e15760405162461bcd60e51b81526004016104d89061129c565b60405180910390fd5b6104eb8383610c85565b50600192915050565b600054610100900460ff16158080156105145750600054600160ff909116105b8061052e5750303b15801561052e575060005460ff166001145b6105915760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016104d8565b6000805460ff1916600117905580156105b4576000805461ff0019166101001790555b336002600160a01b03146105f85760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064016104d8565b6001600160a01b0389166106595760405162461bcd60e51b815260206004820152602260248201527f4e617469766545524332303a20496e76616c6964206f776e6572206164647265604482015261737360f01b60648201526084016104d8565b603780546001600160a01b03808d166001600160a01b03199283161790925560388054928b1692909116919091179055603961069687898361134e565b50603a6106a485878361134e565b50603b805460ff191660ff851617905560368290556106c289610ddf565b8015610708576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b61071c610df8565b6107266000610ddf565b565b60345433906001600160a01b031681146107965760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016104d8565b61079f81610ddf565b50565b6060603a80546103b390611239565b6037546000906001600160a01b03163314806107d757506033546001600160a01b031633145b6107f35760405162461bcd60e51b81526004016104d89061129c565b6104eb8383610e52565b6000338161080b8286610886565b90508381101561086b5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016104d8565b6104698286868403610922565b600033610444818585610ac0565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b6108b9610df8565b603480546001600160a01b0383166001600160a01b031990911681179091556108ea6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b6001600160a01b0383166109845760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016104d8565b6001600160a01b0382166109e55760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016104d8565b6001600160a01b0383811660008181526035602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000610a528484610886565b90506000198114610aba5781811015610aad5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016104d8565b610aba8484848403610922565b50505050565b6001600160a01b038316610b245760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016104d8565b6001600160a01b038216610b865760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016104d8565b6000806120206001600160a01b0316858585604051602001610baa9392919061140f565b60408051601f1981840301815290829052610bc491611433565b6000604051808303816000865af19150503d8060008114610c01576040519150601f19603f3d011682016040523d82523d6000602084013e610c06565b606091505b5091509150818015610c27575080806020019051810190610c27919061144f565b610c435760405162461bcd60e51b81526004016104d890611471565b836001600160a01b0316856001600160a01b03166000805160206114b583398151915285604051610c7691815260200190565b60405180910390a35050505050565b6001600160a01b038216610cdb5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016104d8565b8060366000828254610ced9190611289565b9091555050604051600090819061202090610d109083908790879060200161140f565b60408051601f1981840301815290829052610d2a91611433565b6000604051808303816000865af19150503d8060008114610d67576040519150601f19603f3d011682016040523d82523d6000602084013e610d6c565b606091505b5091509150818015610d8d575080806020019051810190610d8d919061144f565b610da95760405162461bcd60e51b81526004016104d890611471565b6040518381526001600160a01b038516906000906000805160206114b5833981519152906020015b60405180910390a350505050565b603480546001600160a01b031916905561079f81610fac565b6033546001600160a01b031633146107265760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104d8565b6001600160a01b038216610eb25760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016104d8565b8060366000828254610ec491906114a1565b9091555050604051600090819061202090610ee79086908490879060200161140f565b60408051601f1981840301815290829052610f0191611433565b6000604051808303816000865af19150503d8060008114610f3e576040519150601f19603f3d011682016040523d82523d6000602084013e610f43565b606091505b5091509150818015610f64575080806020019051810190610f64919061144f565b610f805760405162461bcd60e51b81526004016104d890611471565b6040518381526000906001600160a01b038616906000805160206114b583398151915290602001610dd1565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60005b83811015611019578181015183820152602001611001565b50506000910152565b6020815260008251806020840152611041816040850160208701610ffe565b601f01601f19169190910160400192915050565b80356001600160a01b038116811461106c57600080fd5b919050565b6000806040838503121561108457600080fd5b61108d83611055565b946020939093013593505050565b6000806000606084860312156110b057600080fd5b6110b984611055565b92506110c760208501611055565b9150604084013590509250925092565b60008083601f8401126110e957600080fd5b50813567ffffffffffffffff81111561110157600080fd5b60208301915083602082850101111561111957600080fd5b9250929050565b600080600080600080600080600060e08a8c03121561113e57600080fd5b6111478a611055565b985061115560208b01611055565b975061116360408b01611055565b965060608a013567ffffffffffffffff8082111561118057600080fd5b61118c8d838e016110d7565b909850965060808c01359150808211156111a557600080fd5b506111b28c828d016110d7565b90955093505060a08a013560ff811681146111cc57600080fd5b8092505060c08a013590509295985092959850929598565b6000602082840312156111f657600080fd5b6111ff82611055565b9392505050565b6000806040838503121561121957600080fd5b61122283611055565b915061123060208401611055565b90509250929050565b600181811c9082168061124d57607f821691505b60208210810361126d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561044a5761044a611273565b6020808252602d908201527f4e617469766545524332303a204f6e6c7920707265646963617465206f72206f60408201526c1ddb995c8818d85b8818d85b1b609a1b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f82111561134957600081815260208120601f850160051c810160208610156113265750805b601f850160051c820191505b8181101561134557828155600101611332565b5050505b505050565b67ffffffffffffffff831115611366576113666112e9565b61137a836113748354611239565b836112ff565b6000601f8411600181146113ae57600085156113965750838201355b600019600387901b1c1916600186901b178355611408565b600083815260209020601f19861690835b828110156113df57868501358255602094850194600190920191016113bf565b50868210156113fc5760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60008251611445818460208701610ffe565b9190910192915050565b60006020828403121561146157600080fd5b815180151581146111ff57600080fd5b60208082526016908201527514149150d3d35412531157d0d0531317d1905253115160521b604082015260600190565b8181038181111561044a5761044a61127356feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122019716c645080b1365563f01a6cdf0f363af3491e7cb3880150d6d1f3389f759364736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC20Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC20\",\n \"sourceName\": \"contracts/child/ChildERC20.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"userAddress\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"relayerAddress\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"functionSignature\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"MetaTransactionExecuted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"userAddress\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"functionSignature\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"sigR\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"sigS\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"sigV\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"executeMetaTransaction\",\n \"outputs\": [\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"user\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"getNonce\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"nonce\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"rootToken_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"name_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"symbol_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"decimals_\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"offset\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"invalidateNext\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611920806100206000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c806340c10f19116100ad578063a457c2d711610071578063a457c2d71461028b578063a9059cbb1461029e578063dd62ed3e146102b1578063e6198705146102c4578063f6d2ee86146102d557600080fd5b806340c10f191461021f57806370a082311461023257806395d89b411461025b5780639b77ef11146102635780639dc29fac1461027857600080fd5b80631f2d0065116100f45780631f2d00651461018c57806323b872dd146101b15780632d0335ab146101c4578063313ce567146101ed578063395093511461020c57600080fd5b806306fdde0314610126578063095ea7b3146101445780630c53c51c1461016757806318160ddd1461017a575b600080fd5b61012e6102e8565b60405161013b9190611395565b60405180910390f35b6101576101523660046113cb565b61037a565b604051901515815260200161013b565b61012e61017536600461144f565b61039e565b60a0545b60405190815260200161013b565b60d1546001600160a01b03165b6040516001600160a01b03909116815260200161013b565b6101576101bf3660046114c5565b610681565b61017e6101d2366004611501565b6001600160a01b031660009081526038602052604090205490565b60d154600160a01b900460ff1660405160ff909116815260200161013b565b61015761021a3660046113cb565b6106af565b61015761022d3660046113cb565b6106db565b61017e610240366004611501565b6001600160a01b03166000908152609e602052604090205490565b61012e61071b565b61027661027136600461151c565b61072a565b005b6101576102863660046113cb565b610751565b6101576102993660046113cb565b610788565b6101576102ac3660046113cb565b61080e565b61017e6102bf366004611535565b610826565b60d0546001600160a01b0316610199565b6102766102e3366004611568565b610851565b606060a180546102f7906115ec565b80601f0160208091040260200160405190810160405280929190818152602001828054610323906115ec565b80156103705780601f1061034557610100808354040283529160200191610370565b820191906000526020600020905b81548152906001019060200180831161035357829003601f168201915b5050505050905090565b600080610385610ad1565b9050610392818585610ae0565b60019150505b92915050565b606060006103e187878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c0592505050565b90506001600160e01b031960003581169082160361046c5760405162461bcd60e51b815260206004820152603d60248201527f66756e6374696f6e5369676e61747572652063616e206e6f74206265206f662060448201527f657865637574654d6574615472616e73616374696f6e206d6574686f6400000060648201526084015b60405180910390fd5b604080516060810182526001600160a01b038a16600081815260386020908152848220548452808401929092528351601f8b0183900483028101830185528a815290938301918b908b9081908401838280828437600092019190915250505091525090506104dd8982888888610c20565b6105335760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610463565b603860008a6001600160a01b03166001600160a01b031681526020019081526020016000206000815460010191905081905550600080306001600160a01b03168a8a8d60405160200161058893929190611626565b60408051601f19818403018152908290526105a29161164c565b6000604051808303816000865af19150503d80600081146105df576040519150601f19603f3d011682016040523d82523d6000602084013e6105e4565b606091505b5091509150816106365760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610463565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b8b338c8c60405161066b9493929190611668565b60405180910390a19a9950505050505050505050565b60008061068c610ad1565b9050610699858285610cfc565b6106a4858585610d76565b506001949350505050565b6000806106ba610ad1565b90506103928185856106cc8589610826565b6106d691906116b4565b610ae0565b60d0546000906001600160a01b031633146107085760405162461bcd60e51b8152600401610463906116d5565b6107128383610f0f565b50600192915050565b606060a280546102f7906115ec565b33600090815260386020526040812080548392906107499084906116b4565b909155505050565b60d0546000906001600160a01b0316331461077e5760405162461bcd60e51b8152600401610463906116d5565b6107128383610fbf565b600080610793610ad1565b905060006107a18286610826565b9050838110156108015760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610463565b6106a48286868403610ae0565b600080610819610ad1565b9050610392818585610d76565b6001600160a01b039182166000908152609f6020908152604080832093909416825291909152205490565b606b54610100900460ff16158080156108715750606b54600160ff909116105b8061088b5750303b15801561088b5750606b5460ff166001145b6108ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610463565b606b805460ff19166001179055801561091157606b805461ff0019166101001790555b6001600160a01b0387161580159061092857508415155b801561093357508215155b61097f5760405162461bcd60e51b815260206004820152601e60248201527f4368696c6445524332303a204241445f494e495449414c495a4154494f4e00006044820152606401610463565b60d1805460ff8416600160a01b026001600160a81b03199091166001600160a01b038a161717905560d080546001600160a01b03191633179055604080516020601f8801819004810282018101909252868152610a2a91889088908190840183828082843760009201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284376000920191909152506110de92505050565b610a8286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b6020820152915061110f9050565b8015610ac857606b805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6000610adb61117b565b905090565b6001600160a01b038316610b425760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610463565b6001600160a01b038216610ba35760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610463565b6001600160a01b038381166000818152609f602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60008151600003610c1857506000919050565b506020015190565b6000806001610c36610c31886111d7565b611254565b6040805160008152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015610c84573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610cdb5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610463565b866001600160a01b0316816001600160a01b03161491505095945050505050565b6000610d088484610826565b90506000198114610d705781811015610d635760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610463565b610d708484848403610ae0565b50505050565b6001600160a01b038316610dda5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610463565b6001600160a01b038216610e3c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610463565b6001600160a01b0383166000908152609e602052604090205481811015610eb45760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610463565b6001600160a01b038085166000818152609e602052604080822086860390559286168082529083902080548601905591516000805160206118cb83398151915290610f029086815260200190565b60405180910390a3610d70565b6001600160a01b038216610f655760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610463565b8060a06000828254610f7791906116b4565b90915550506001600160a01b0382166000818152609e60209081526040808320805486019055518481526000805160206118cb833981519152910160405180910390a35b5050565b6001600160a01b03821661101f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610463565b6001600160a01b0382166000908152609e6020526040902054818110156110935760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610463565b6001600160a01b0383166000818152609e60209081526040808320868603905560a080548790039055518581529192916000805160206118cb8339815191529101610bf8565b505050565b606b54610100900460ff166111055760405162461bcd60e51b815260040161046390611718565b610fbb8282611281565b815160208084019190912082519183019190912060038290556004819055466001557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61115d8184846112c1565b600055600280546001600160a01b0319163017905560055550505050565b60003033036111d157600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506111d49050565b50335b90565b60006040518060800160405280604381526020016118886043913980516020918201208351848301516040808701518051908601209051611237950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061039861126161130a565b8360405161190160f01b8152600281019290925260228201526042902090565b606b54610100900460ff166112a85760405162461bcd60e51b815260040161046390611718565b60a16112b483826117c7565b5060a26110d982826117c7565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6002546000906001600160a01b031630148015611328575060015446145b15611334575060005490565b610adb6005546003546004546112c1565b60005b83811015611360578181015183820152602001611348565b50506000910152565b60008151808452611381816020860160208601611345565b601f01601f19169290920160200192915050565b6020815260006113a86020830184611369565b9392505050565b80356001600160a01b03811681146113c657600080fd5b919050565b600080604083850312156113de57600080fd5b6113e7836113af565b946020939093013593505050565b60008083601f84011261140757600080fd5b50813567ffffffffffffffff81111561141f57600080fd5b60208301915083602082850101111561143757600080fd5b9250929050565b803560ff811681146113c657600080fd5b60008060008060008060a0878903121561146857600080fd5b611471876113af565b9550602087013567ffffffffffffffff81111561148d57600080fd5b61149989828a016113f5565b90965094505060408701359250606087013591506114b96080880161143e565b90509295509295509295565b6000806000606084860312156114da57600080fd5b6114e3846113af565b92506114f1602085016113af565b9150604084013590509250925092565b60006020828403121561151357600080fd5b6113a8826113af565b60006020828403121561152e57600080fd5b5035919050565b6000806040838503121561154857600080fd5b611551836113af565b915061155f602084016113af565b90509250929050565b6000806000806000806080878903121561158157600080fd5b61158a876113af565b9550602087013567ffffffffffffffff808211156115a757600080fd5b6115b38a838b016113f5565b909750955060408901359150808211156115cc57600080fd5b506115d989828a016113f5565b90945092506114b990506060880161143e565b600181811c9082168061160057607f821691505b60208210810361162057634e487b7160e01b600052602260045260246000fd5b50919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b6000825161165e818460208701611345565b9190910192915050565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b8082018082111561039857634e487b7160e01b600052601160045260246000fd5b60208082526023908201527f4368696c6445524332303a204f6e6c79207072656469636174652063616e2063604082015262185b1b60ea1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f8211156110d957600081815260208120601f850160051c810160208610156117a05750805b601f850160051c820191505b818110156117bf578281556001016117ac565b505050505050565b815167ffffffffffffffff8111156117e1576117e1611763565b6117f5816117ef84546115ec565b84611779565b602080601f83116001811461182a57600084156118125750858301515b600019600386901b1c1916600185901b1785556117bf565b600085815260208120601f198616915b828110156118595788860151825594840194600190910190840161183a565b50858210156118775787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122083d6b7bd85693305a7ba1e1fc5172e26e43168ef3c342fd05cb6ecd683a2bbac64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101215760003560e01c806340c10f19116100ad578063a457c2d711610071578063a457c2d71461028b578063a9059cbb1461029e578063dd62ed3e146102b1578063e6198705146102c4578063f6d2ee86146102d557600080fd5b806340c10f191461021f57806370a082311461023257806395d89b411461025b5780639b77ef11146102635780639dc29fac1461027857600080fd5b80631f2d0065116100f45780631f2d00651461018c57806323b872dd146101b15780632d0335ab146101c4578063313ce567146101ed578063395093511461020c57600080fd5b806306fdde0314610126578063095ea7b3146101445780630c53c51c1461016757806318160ddd1461017a575b600080fd5b61012e6102e8565b60405161013b9190611395565b60405180910390f35b6101576101523660046113cb565b61037a565b604051901515815260200161013b565b61012e61017536600461144f565b61039e565b60a0545b60405190815260200161013b565b60d1546001600160a01b03165b6040516001600160a01b03909116815260200161013b565b6101576101bf3660046114c5565b610681565b61017e6101d2366004611501565b6001600160a01b031660009081526038602052604090205490565b60d154600160a01b900460ff1660405160ff909116815260200161013b565b61015761021a3660046113cb565b6106af565b61015761022d3660046113cb565b6106db565b61017e610240366004611501565b6001600160a01b03166000908152609e602052604090205490565b61012e61071b565b61027661027136600461151c565b61072a565b005b6101576102863660046113cb565b610751565b6101576102993660046113cb565b610788565b6101576102ac3660046113cb565b61080e565b61017e6102bf366004611535565b610826565b60d0546001600160a01b0316610199565b6102766102e3366004611568565b610851565b606060a180546102f7906115ec565b80601f0160208091040260200160405190810160405280929190818152602001828054610323906115ec565b80156103705780601f1061034557610100808354040283529160200191610370565b820191906000526020600020905b81548152906001019060200180831161035357829003601f168201915b5050505050905090565b600080610385610ad1565b9050610392818585610ae0565b60019150505b92915050565b606060006103e187878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c0592505050565b90506001600160e01b031960003581169082160361046c5760405162461bcd60e51b815260206004820152603d60248201527f66756e6374696f6e5369676e61747572652063616e206e6f74206265206f662060448201527f657865637574654d6574615472616e73616374696f6e206d6574686f6400000060648201526084015b60405180910390fd5b604080516060810182526001600160a01b038a16600081815260386020908152848220548452808401929092528351601f8b0183900483028101830185528a815290938301918b908b9081908401838280828437600092019190915250505091525090506104dd8982888888610c20565b6105335760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610463565b603860008a6001600160a01b03166001600160a01b031681526020019081526020016000206000815460010191905081905550600080306001600160a01b03168a8a8d60405160200161058893929190611626565b60408051601f19818403018152908290526105a29161164c565b6000604051808303816000865af19150503d80600081146105df576040519150601f19603f3d011682016040523d82523d6000602084013e6105e4565b606091505b5091509150816106365760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610463565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b8b338c8c60405161066b9493929190611668565b60405180910390a19a9950505050505050505050565b60008061068c610ad1565b9050610699858285610cfc565b6106a4858585610d76565b506001949350505050565b6000806106ba610ad1565b90506103928185856106cc8589610826565b6106d691906116b4565b610ae0565b60d0546000906001600160a01b031633146107085760405162461bcd60e51b8152600401610463906116d5565b6107128383610f0f565b50600192915050565b606060a280546102f7906115ec565b33600090815260386020526040812080548392906107499084906116b4565b909155505050565b60d0546000906001600160a01b0316331461077e5760405162461bcd60e51b8152600401610463906116d5565b6107128383610fbf565b600080610793610ad1565b905060006107a18286610826565b9050838110156108015760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610463565b6106a48286868403610ae0565b600080610819610ad1565b9050610392818585610d76565b6001600160a01b039182166000908152609f6020908152604080832093909416825291909152205490565b606b54610100900460ff16158080156108715750606b54600160ff909116105b8061088b5750303b15801561088b5750606b5460ff166001145b6108ee5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610463565b606b805460ff19166001179055801561091157606b805461ff0019166101001790555b6001600160a01b0387161580159061092857508415155b801561093357508215155b61097f5760405162461bcd60e51b815260206004820152601e60248201527f4368696c6445524332303a204241445f494e495449414c495a4154494f4e00006044820152606401610463565b60d1805460ff8416600160a01b026001600160a81b03199091166001600160a01b038a161717905560d080546001600160a01b03191633179055604080516020601f8801819004810282018101909252868152610a2a91889088908190840183828082843760009201919091525050604080516020601f8a0181900481028201810190925288815292508891508790819084018382808284376000920191909152506110de92505050565b610a8286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b6020820152915061110f9050565b8015610ac857606b805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b6000610adb61117b565b905090565b6001600160a01b038316610b425760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610463565b6001600160a01b038216610ba35760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610463565b6001600160a01b038381166000818152609f602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60008151600003610c1857506000919050565b506020015190565b6000806001610c36610c31886111d7565b611254565b6040805160008152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015610c84573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610cdb5760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610463565b866001600160a01b0316816001600160a01b03161491505095945050505050565b6000610d088484610826565b90506000198114610d705781811015610d635760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610463565b610d708484848403610ae0565b50505050565b6001600160a01b038316610dda5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610463565b6001600160a01b038216610e3c5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610463565b6001600160a01b0383166000908152609e602052604090205481811015610eb45760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610463565b6001600160a01b038085166000818152609e602052604080822086860390559286168082529083902080548601905591516000805160206118cb83398151915290610f029086815260200190565b60405180910390a3610d70565b6001600160a01b038216610f655760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610463565b8060a06000828254610f7791906116b4565b90915550506001600160a01b0382166000818152609e60209081526040808320805486019055518481526000805160206118cb833981519152910160405180910390a35b5050565b6001600160a01b03821661101f5760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610463565b6001600160a01b0382166000908152609e6020526040902054818110156110935760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610463565b6001600160a01b0383166000818152609e60209081526040808320868603905560a080548790039055518581529192916000805160206118cb8339815191529101610bf8565b505050565b606b54610100900460ff166111055760405162461bcd60e51b815260040161046390611718565b610fbb8282611281565b815160208084019190912082519183019190912060038290556004819055466001557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61115d8184846112c1565b600055600280546001600160a01b0319163017905560055550505050565b60003033036111d157600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506111d49050565b50335b90565b60006040518060800160405280604381526020016118886043913980516020918201208351848301516040808701518051908601209051611237950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061039861126161130a565b8360405161190160f01b8152600281019290925260228201526042902090565b606b54610100900460ff166112a85760405162461bcd60e51b815260040161046390611718565b60a16112b483826117c7565b5060a26110d982826117c7565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6002546000906001600160a01b031630148015611328575060015446145b15611334575060005490565b610adb6005546003546004546112c1565b60005b83811015611360578181015183820152602001611348565b50506000910152565b60008151808452611381816020860160208601611345565b601f01601f19169290920160200192915050565b6020815260006113a86020830184611369565b9392505050565b80356001600160a01b03811681146113c657600080fd5b919050565b600080604083850312156113de57600080fd5b6113e7836113af565b946020939093013593505050565b60008083601f84011261140757600080fd5b50813567ffffffffffffffff81111561141f57600080fd5b60208301915083602082850101111561143757600080fd5b9250929050565b803560ff811681146113c657600080fd5b60008060008060008060a0878903121561146857600080fd5b611471876113af565b9550602087013567ffffffffffffffff81111561148d57600080fd5b61149989828a016113f5565b90965094505060408701359250606087013591506114b96080880161143e565b90509295509295509295565b6000806000606084860312156114da57600080fd5b6114e3846113af565b92506114f1602085016113af565b9150604084013590509250925092565b60006020828403121561151357600080fd5b6113a8826113af565b60006020828403121561152e57600080fd5b5035919050565b6000806040838503121561154857600080fd5b611551836113af565b915061155f602084016113af565b90509250929050565b6000806000806000806080878903121561158157600080fd5b61158a876113af565b9550602087013567ffffffffffffffff808211156115a757600080fd5b6115b38a838b016113f5565b909750955060408901359150808211156115cc57600080fd5b506115d989828a016113f5565b90945092506114b990506060880161143e565b600181811c9082168061160057607f821691505b60208210810361162057634e487b7160e01b600052602260045260246000fd5b50919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b6000825161165e818460208701611345565b9190910192915050565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b8082018082111561039857634e487b7160e01b600052601160045260246000fd5b60208082526023908201527f4368696c6445524332303a204f6e6c79207072656469636174652063616e2063604082015262185b1b60ea1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b601f8211156110d957600081815260208120601f850160051c810160208610156117a05750805b601f850160051c820191505b818110156117bf578281556001016117ac565b505050505050565b815167ffffffffffffffff8111156117e1576117e1611763565b6117f5816117ef84546115ec565b84611779565b602080601f83116001811461182a57600084156118125750858301515b600019600386901b1c1916600185901b1785556117bf565b600085815260208120601f198616915b828110156118595788860151825594840194600190910190840161183a565b50858210156118775787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa264697066735822122083d6b7bd85693305a7ba1e1fc5172e26e43168ef3c342fd05cb6ecd683a2bbac64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC20PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC20Predicate\",\n \"sourceName\": \"contracts/child/ChildERC20Predicate.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC20Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC20Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newNativeTokenRootAddress\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506114ea806100206000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c80637efab4f5116100b8578063c3b35a7e1161007c578063c3b35a7e14610270578063d41f177114610283578063e0563ab1146102aa578063eeb49945146102b3578063f3fef3a3146102c6578063f6451255146102d957600080fd5b80637efab4f5146101fa578063947287cf1461022357806397e5230d1461022c578063b176806514610236578063b68ad1e41461025d57600080fd5b80633b878c22116100ff5780633b878c22146101ab57806351351d53146101b457806355b01e4d146101c25780635ea5df79146101d057806371cf93b7146101e757600080fd5b806305dc2e8f1461013c57806307b3e2521461016c5780631459457a1461017a5780631bc114ba1461018f578063284017f5146101a2575b600080fd5b60345461014f906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61014f6004600360981b0181565b61018d610188366004610ff2565b610300565b005b60335461014f906001600160a01b031681565b61014f61202081565b61014f61101081565b61014f6002600160a01b0381565b61014f6004600160991b0181565b6101d961138881565b604051908152602001610163565b60355461014f906001600160a01b031681565b61014f610208366004611063565b6037602052600090815260409020546001600160a01b031681565b6101d961520881565b6101d9620249f081565b6101d97f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60365461014f906001600160a01b031681565b61018d61027e366004611087565b610464565b6101d97f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61014f61203081565b61018d6102c13660046110c8565b610474565b61018d6102d4366004611151565b610648565b6101d97f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b336002600160a01b03146103495760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064015b60405180910390fd5b600054610100900460ff16158080156103695750600054600160ff909116105b806103835750303b158015610383575060005460ff166001145b6103e65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610340565b6000805460ff191660011790558015610409576000805461ff0019166101001790555b6104168686868686610657565b801561045c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b61046f8383836107a7565b505050565b6034546001600160a01b031633146104df5760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f53544154455f6044820152672922a1a2a4ab22a960c11b6064820152608401610340565b6035546001600160a01b0384811691161461054d5760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f524f4f545f50604482015267524544494341544560c01b6064820152608401610340565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82161057c60206000848661117d565b610585916111a7565b036105a45761059f61059a826020818661117d565b610b1d565b610642565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6105d360206000848661117d565b6105dc916111a7565b036105eb5761059f8282610dc8565b60405162461bcd60e51b815260206004820152602660248201527f4368696c6445524332305072656469636174653a20494e56414c49445f5349476044820152654e415455524560d01b6064820152608401610340565b50505050565b6106538233836107a7565b5050565b6001600160a01b0385161580159061067757506001600160a01b03841615155b801561068b57506001600160a01b03831615155b801561069f57506001600160a01b03821615155b6106fb5760405162461bcd60e51b815260206004820152602760248201527f4368696c6445524332305072656469636174653a204241445f494e495449414c60448201526624ad20aa24a7a760c91b6064820152608401610340565b603380546001600160a01b03199081166001600160a01b0388811691909117909255603480548216878416179055603580548216868416179055603680549091168483161790558116156107a0576001600160a01b03811660008181526037602052604080822080546001600160a01b03191661101090811790915590519092917f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d91a35b5050505050565b826001600160a01b03163b60000361080b5760405162461bcd60e51b815260206004820152602160248201527f4368696c6445524332305072656469636174653a204e4f545f434f4e545241436044820152601560fa1b6064820152608401610340565b6000836001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906111c5565b6001600160a01b038181166000908152603760205260409020549192508581169116146108ae5760405162461bcd60e51b8152600401610340906111e2565b6001600160a01b0381166108c4576108c4611225565b306001600160a01b0316846001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561090c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093091906111c5565b6001600160a01b03161461094657610946611225565b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac90610974903390869060040161123b565b6020604051808303816000875af1158015610993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b79190611254565b610a035760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204255524e5f4641494c45446044820152606401610340565b603354603554604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610a8e9391169160c4016112bc565b600060405180830381600087803b158015610aa857600080fd5b505af1158015610abc573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316826001600160a01b03167fa0923f060a16fc784558d43de424ffde7b01643de5e5d335851b9df94c76bb273386604051610b0f92919061123b565b60405180910390a450505050565b6000808080610b2e858701876112e8565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610b715760405162461bcd60e51b8152600401610340906111e2565b806001600160a01b03163b600003610b8b57610b8b611225565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bef91906111c5565b9050856001600160a01b0316816001600160a01b031614610c1257610c12611225565b6001600160a01b038116610c2857610c28611225565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9491906111c5565b6001600160a01b031614610caa57610caa611225565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610cd8908790879060040161123b565b6020604051808303816000875af1158015610cf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1b9190611254565b610d675760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204d494e545f4641494c45446044820152606401610340565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fdf34f3a3ed8bedc14a4b284ebaee5374d55b64bac6a84c270dabe8fd6b4cdafd8887604051610db692919061123b565b60405180910390a45050505050505050565b6000808080610dd9858701876113dc565b92975090955093509150506001600160a01b038416610dfa57610dfa611225565b6001600160a01b038481166000908152603760205260409020541615610e2257610e22611225565b6036546040516bffffffffffffffffffffffff19606087901b166020820152600091610e72916001600160a01b039091169060340160405160208183030381529060405280519060200120610f3d565b6001600160a01b038681166000908152603760205260409081902080546001600160a01b031916928416928317905551637b69774360e11b81529192509063f6d2ee8690610eca908890889088908890600401611469565b600060405180830381600087803b158015610ee457600080fd5b505af1158015610ef8573d6000803e3d6000fd5b50506040516001600160a01b038085169350881691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a350505050505050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116610fd45760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b6044820152606401610340565b92915050565b6001600160a01b0381168114610fef57600080fd5b50565b600080600080600060a0868803121561100a57600080fd5b853561101581610fda565b9450602086013561102581610fda565b9350604086013561103581610fda565b9250606086013561104581610fda565b9150608086013561105581610fda565b809150509295509295909350565b60006020828403121561107557600080fd5b813561108081610fda565b9392505050565b60008060006060848603121561109c57600080fd5b83356110a781610fda565b925060208401356110b781610fda565b929592945050506040919091013590565b600080600080606085870312156110de57600080fd5b8435935060208501356110f081610fda565b9250604085013567ffffffffffffffff8082111561110d57600080fd5b818701915087601f83011261112157600080fd5b81358181111561113057600080fd5b88602082850101111561114257600080fd5b95989497505060200194505050565b6000806040838503121561116457600080fd5b823561116f81610fda565b946020939093013593505050565b6000808585111561118d57600080fd5b8386111561119a57600080fd5b5050820193919092039150565b80356020831015610fd457600019602084900360031b1b1692915050565b6000602082840312156111d757600080fd5b815161108081610fda565b60208082526023908201527f4368696c6445524332305072656469636174653a20554e4d41505045445f544f60408201526225a2a760e91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b60006020828403121561126657600080fd5b8151801515811461108057600080fd5b6000815180845260005b8181101561129c57602081850181015186830182015201611280565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190526000906112e090830184611276565b949350505050565b600080600080608085870312156112fe57600080fd5b843561130981610fda565b9350602085013561131981610fda565b9250604085013561132981610fda565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261136057600080fd5b813567ffffffffffffffff8082111561137b5761137b611339565b604051601f8301601f19908116603f011681019082821181831017156113a3576113a3611339565b816040528381528660208588010111156113bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156113f457600080fd5b85359450602086013561140681610fda565b9350604086013567ffffffffffffffff8082111561142357600080fd5b61142f89838a0161134f565b9450606088013591508082111561144557600080fd5b506114528882890161134f565b925050608086013560ff8116811461105557600080fd5b6001600160a01b038516815260806020820181905260009061148d90830186611276565b828103604084015261149f8186611276565b91505060ff831660608301529594505050505056fea26469706673582212200a9bd04ce459c321a21b5d2d1e75f54fc0466e0ee822ecf79ffa26d25a1e1f2664736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101375760003560e01c80637efab4f5116100b8578063c3b35a7e1161007c578063c3b35a7e14610270578063d41f177114610283578063e0563ab1146102aa578063eeb49945146102b3578063f3fef3a3146102c6578063f6451255146102d957600080fd5b80637efab4f5146101fa578063947287cf1461022357806397e5230d1461022c578063b176806514610236578063b68ad1e41461025d57600080fd5b80633b878c22116100ff5780633b878c22146101ab57806351351d53146101b457806355b01e4d146101c25780635ea5df79146101d057806371cf93b7146101e757600080fd5b806305dc2e8f1461013c57806307b3e2521461016c5780631459457a1461017a5780631bc114ba1461018f578063284017f5146101a2575b600080fd5b60345461014f906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61014f6004600360981b0181565b61018d610188366004610ff2565b610300565b005b60335461014f906001600160a01b031681565b61014f61202081565b61014f61101081565b61014f6002600160a01b0381565b61014f6004600160991b0181565b6101d961138881565b604051908152602001610163565b60355461014f906001600160a01b031681565b61014f610208366004611063565b6037602052600090815260409020546001600160a01b031681565b6101d961520881565b6101d9620249f081565b6101d97f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60365461014f906001600160a01b031681565b61018d61027e366004611087565b610464565b6101d97f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61014f61203081565b61018d6102c13660046110c8565b610474565b61018d6102d4366004611151565b610648565b6101d97f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b336002600160a01b03146103495760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064015b60405180910390fd5b600054610100900460ff16158080156103695750600054600160ff909116105b806103835750303b158015610383575060005460ff166001145b6103e65760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610340565b6000805460ff191660011790558015610409576000805461ff0019166101001790555b6104168686868686610657565b801561045c576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b61046f8383836107a7565b505050565b6034546001600160a01b031633146104df5760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f53544154455f6044820152672922a1a2a4ab22a960c11b6064820152608401610340565b6035546001600160a01b0384811691161461054d5760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f524f4f545f50604482015267524544494341544560c01b6064820152608401610340565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82161057c60206000848661117d565b610585916111a7565b036105a45761059f61059a826020818661117d565b610b1d565b610642565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6105d360206000848661117d565b6105dc916111a7565b036105eb5761059f8282610dc8565b60405162461bcd60e51b815260206004820152602660248201527f4368696c6445524332305072656469636174653a20494e56414c49445f5349476044820152654e415455524560d01b6064820152608401610340565b50505050565b6106538233836107a7565b5050565b6001600160a01b0385161580159061067757506001600160a01b03841615155b801561068b57506001600160a01b03831615155b801561069f57506001600160a01b03821615155b6106fb5760405162461bcd60e51b815260206004820152602760248201527f4368696c6445524332305072656469636174653a204241445f494e495449414c60448201526624ad20aa24a7a760c91b6064820152608401610340565b603380546001600160a01b03199081166001600160a01b0388811691909117909255603480548216878416179055603580548216868416179055603680549091168483161790558116156107a0576001600160a01b03811660008181526037602052604080822080546001600160a01b03191661101090811790915590519092917f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d91a35b5050505050565b826001600160a01b03163b60000361080b5760405162461bcd60e51b815260206004820152602160248201527f4368696c6445524332305072656469636174653a204e4f545f434f4e545241436044820152601560fa1b6064820152608401610340565b6000836001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086f91906111c5565b6001600160a01b038181166000908152603760205260409020549192508581169116146108ae5760405162461bcd60e51b8152600401610340906111e2565b6001600160a01b0381166108c4576108c4611225565b306001600160a01b0316846001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561090c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093091906111c5565b6001600160a01b03161461094657610946611225565b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac90610974903390869060040161123b565b6020604051808303816000875af1158015610993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b79190611254565b610a035760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204255524e5f4641494c45446044820152606401610340565b603354603554604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610a8e9391169160c4016112bc565b600060405180830381600087803b158015610aa857600080fd5b505af1158015610abc573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316826001600160a01b03167fa0923f060a16fc784558d43de424ffde7b01643de5e5d335851b9df94c76bb273386604051610b0f92919061123b565b60405180910390a450505050565b6000808080610b2e858701876112e8565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610b715760405162461bcd60e51b8152600401610340906111e2565b806001600160a01b03163b600003610b8b57610b8b611225565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bef91906111c5565b9050856001600160a01b0316816001600160a01b031614610c1257610c12611225565b6001600160a01b038116610c2857610c28611225565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c9491906111c5565b6001600160a01b031614610caa57610caa611225565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610cd8908790879060040161123b565b6020604051808303816000875af1158015610cf7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d1b9190611254565b610d675760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204d494e545f4641494c45446044820152606401610340565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fdf34f3a3ed8bedc14a4b284ebaee5374d55b64bac6a84c270dabe8fd6b4cdafd8887604051610db692919061123b565b60405180910390a45050505050505050565b6000808080610dd9858701876113dc565b92975090955093509150506001600160a01b038416610dfa57610dfa611225565b6001600160a01b038481166000908152603760205260409020541615610e2257610e22611225565b6036546040516bffffffffffffffffffffffff19606087901b166020820152600091610e72916001600160a01b039091169060340160405160208183030381529060405280519060200120610f3d565b6001600160a01b038681166000908152603760205260409081902080546001600160a01b031916928416928317905551637b69774360e11b81529192509063f6d2ee8690610eca908890889088908890600401611469565b600060405180830381600087803b158015610ee457600080fd5b505af1158015610ef8573d6000803e3d6000fd5b50506040516001600160a01b038085169350881691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a350505050505050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116610fd45760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b6044820152606401610340565b92915050565b6001600160a01b0381168114610fef57600080fd5b50565b600080600080600060a0868803121561100a57600080fd5b853561101581610fda565b9450602086013561102581610fda565b9350604086013561103581610fda565b9250606086013561104581610fda565b9150608086013561105581610fda565b809150509295509295909350565b60006020828403121561107557600080fd5b813561108081610fda565b9392505050565b60008060006060848603121561109c57600080fd5b83356110a781610fda565b925060208401356110b781610fda565b929592945050506040919091013590565b600080600080606085870312156110de57600080fd5b8435935060208501356110f081610fda565b9250604085013567ffffffffffffffff8082111561110d57600080fd5b818701915087601f83011261112157600080fd5b81358181111561113057600080fd5b88602082850101111561114257600080fd5b95989497505060200194505050565b6000806040838503121561116457600080fd5b823561116f81610fda565b946020939093013593505050565b6000808585111561118d57600080fd5b8386111561119a57600080fd5b5050820193919092039150565b80356020831015610fd457600019602084900360031b1b1692915050565b6000602082840312156111d757600080fd5b815161108081610fda565b60208082526023908201527f4368696c6445524332305072656469636174653a20554e4d41505045445f544f60408201526225a2a760e91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b60006020828403121561126657600080fd5b8151801515811461108057600080fd5b6000815180845260005b8181101561129c57602081850181015186830182015201611280565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190526000906112e090830184611276565b949350505050565b600080600080608085870312156112fe57600080fd5b843561130981610fda565b9350602085013561131981610fda565b9250604085013561132981610fda565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261136057600080fd5b813567ffffffffffffffff8082111561137b5761137b611339565b604051601f8301601f19908116603f011681019082821181831017156113a3576113a3611339565b816040528381528660208588010111156113bc57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156113f457600080fd5b85359450602086013561140681610fda565b9350604086013567ffffffffffffffff8082111561142357600080fd5b61142f89838a0161134f565b9450606088013591508082111561144557600080fd5b506114528882890161134f565b925050608086013560ff8116811461105557600080fd5b6001600160a01b038516815260806020820181905260009061148d90830186611276565b828103604084015261149f8186611276565b91505060ff831660608301529594505050505056fea26469706673582212200a9bd04ce459c321a21b5d2d1e75f54fc0466e0ee822ecf79ffa26d25a1e1f2664736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC20PredicateACLArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC20PredicateAccessList\",\n \"sourceName\": \"contracts/child/ChildERC20PredicateAccessList.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"AllowListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"BlockListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC20Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC20Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newNativeTokenRootAddress\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newNativeTokenRootAddress\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setAllowList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setBlockList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611c8e806100206000396000f3fe608060405234801561001057600080fd5b506004361061018f5760003560e01c80638da5cb5b116100e4578063c5e4683a11610092578063c5e4683a14610323578063d41f177114610336578063e0563ab11461035d578063e30c397814610366578063eeb4994514610377578063f2fde38b1461038a578063f3fef3a31461039d578063f6451255146103b057600080fd5b80638da5cb5b1461029f578063947287cf146102b057806397e5230d146102b9578063b1768065146102c3578063b68ad1e4146102ea578063c1225a20146102fd578063c3b35a7e1461031057600080fd5b806354f8abad1161014157806354f8abad1461021a57806355b01e4d1461022d5780635ea5df791461023b578063715018a61461025257806371cf93b71461025a57806379ba50971461026d5780637efab4f51461027557600080fd5b806305dc2e8f1461019457806307b3e252146101c45780631459457a146101d25780631bc114ba146101e7578063284017f5146101fa5780633b878c221461020357806351351d531461020c575b600080fd5b60fd546101a7906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101a76004600360981b0181565b6101e56101e0366004611616565b6103d7565b005b60fc546101a7906001600160a01b031681565b6101a761202081565b6101a761101081565b6101a76002600160a01b0381565b6101e5610228366004611695565b6104db565b6101a76004600160991b0181565b61024461138881565b6040519081526020016101bb565b6101e56105fe565b60fe546101a7906001600160a01b031681565b6101e5610612565b6101a761028336600461173e565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b03166101a7565b61024461520881565b610244620249f081565b6102447f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff546101a7906001600160a01b031681565b6101e561030b366004611762565b61068c565b6101e561031e36600461177f565b6106db565b6101e5610331366004611762565b6106f3565b6102447f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101a761203081565b6065546001600160a01b03166101a7565b6101e56103853660046117c0565b61073a565b6101e561039836600461173e565b61090e565b6101e56103ab366004611849565b61097f565b6102447f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b336002600160a01b03146104075760405163973d02cb60e01b81526004016103fe90611875565b60405180910390fd5b600054610100900460ff16158080156104275750600054600160ff909116105b806104415750303b158015610441575060005460ff166001145b61045d5760405162461bcd60e51b81526004016103fe90611899565b6000805460ff191660011790558015610480576000805461ff0019166101001790555b61048d8686868686610996565b80156104d3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b336002600160a01b03146105025760405163973d02cb60e01b81526004016103fe90611875565b600054610100900460ff16158080156105225750600054600160ff909116105b8061053c5750303b15801561053c575060005460ff166001145b6105585760405162461bcd60e51b81526004016103fe90611899565b6000805460ff19166001179055801561057b576000805461ff0019166101001790555b6105888989898989610996565b60c9805461ffff191685151561ff00191617610100851515021790556105ad82610ae7565b80156105f3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b610606610b00565b6106106000610ae7565b565b60655433906001600160a01b031681146106805760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016103fe565b61068981610ae7565b50565b610694610b00565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b6106e3610b5a565b6106ee838383610b62565b505050565b6106fb610b00565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b60fd546001600160a01b031633146107a55760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f53544154455f6044820152672922a1a2a4ab22a960c11b60648201526084016103fe565b60fe546001600160a01b038481169116146108135760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f524f4f545f50604482015267524544494341544560c01b60648201526084016103fe565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216108426020600084866118e7565b61084b91611911565b0361086a5761086561086082602081866118e7565b610ed9565b610908565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6108996020600084866118e7565b6108a291611911565b036108b1576108658282611185565b60405162461bcd60e51b815260206004820152602660248201527f4368696c6445524332305072656469636174653a20494e56414c49445f5349476044820152654e415455524560d01b60648201526084016103fe565b50505050565b610916610b00565b606580546001600160a01b0383166001600160a01b031990911681179091556109476033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b610987610b5a565b610992823383610b62565b5050565b6001600160a01b038516158015906109b657506001600160a01b03841615155b80156109ca57506001600160a01b03831615155b80156109de57506001600160a01b03821615155b610a3a5760405162461bcd60e51b815260206004820152602760248201527f4368696c6445524332305072656469636174653a204241445f494e495449414c60448201526624ad20aa24a7a760c91b60648201526084016103fe565b60fc80546001600160a01b03199081166001600160a01b038881169190911790925560fd8054821687841617905560fe8054821686841617905560ff8054909116848316179055811615610ae0576001600160a01b0381166000818152610100602052604080822080546001600160a01b03191661101090811790915590519092917f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d91a35b5050505050565b606580546001600160a01b0319169055610689816112fc565b6033546001600160a01b031633146106105760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103fe565b61061061134e565b826001600160a01b03163b600003610bc65760405162461bcd60e51b815260206004820152602160248201527f4368696c6445524332305072656469636174653a204e4f545f434f4e545241436044820152601560fa1b60648201526084016103fe565b6000836001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2a919061192f565b6001600160a01b0381811660009081526101006020526040902054919250858116911614610c6a5760405162461bcd60e51b81526004016103fe9061194c565b6001600160a01b038116610c8057610c8061198f565b306001600160a01b0316846001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec919061192f565b6001600160a01b031614610d0257610d0261198f565b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac90610d3090339086906004016119a5565b6020604051808303816000875af1158015610d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7391906119be565b610dbf5760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204255524e5f4641494c454460448201526064016103fe565b60fc5460fe54604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610e4a9391169160c401611a2b565b600060405180830381600087803b158015610e6457600080fd5b505af1158015610e78573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316826001600160a01b03167fa0923f060a16fc784558d43de424ffde7b01643de5e5d335851b9df94c76bb273386604051610ecb9291906119a5565b60405180910390a450505050565b6000808080610eea85870187611a57565b6001600160a01b038085166000908152610100602052604090205494985092965090945092501680610f2e5760405162461bcd60e51b81526004016103fe9061194c565b806001600160a01b03163b600003610f4857610f4861198f565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fac919061192f565b9050856001600160a01b0316816001600160a01b031614610fcf57610fcf61198f565b6001600160a01b038116610fe557610fe561198f565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561102d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611051919061192f565b6001600160a01b0316146110675761106761198f565b6040516340c10f1960e01b81526001600160a01b038316906340c10f199061109590879087906004016119a5565b6020604051808303816000875af11580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d891906119be565b6111245760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204d494e545f4641494c454460448201526064016103fe565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fdf34f3a3ed8bedc14a4b284ebaee5374d55b64bac6a84c270dabe8fd6b4cdafd88876040516111739291906119a5565b60405180910390a45050505050505050565b600080808061119685870187611b4b565b92975090955093509150506001600160a01b0384166111b7576111b761198f565b6001600160a01b038481166000908152610100602052604090205416156111e0576111e061198f565b60ff546040516bffffffffffffffffffffffff19606087901b166020820152600091611230916001600160a01b039091169060340160405160208183030381529060405280519060200120611564565b6001600160a01b03868116600090815261010060205260409081902080546001600160a01b031916928416928317905551637b69774360e11b81529192509063f6d2ee8690611289908890889088908890600401611bd8565b600060405180830381600087803b1580156112a357600080fd5b505af11580156112b7573d6000803e3d6000fd5b50506040516001600160a01b038085169350881691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a350505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c95460ff161561145957604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b0191611388916113b09190611c23565b6000604051808303818686fa925050503d80600081146113ec576040519150601f19603f3d011682016040523d82523d6000602084013e6113f1565b606091505b509150915081801561141657506000818060200190518101906114149190611c3f565b115b6114565760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b60448201526064016103fe565b50505b60c954610100900460ff161561061057604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b0191611388916114c09190611c23565b6000604051808303818686fa925050503d80600081146114fc576040519150601f19603f3d011682016040523d82523d6000602084013e611501565b606091505b50915091508180156115275750808060200190518101906115229190611c3f565b600114155b6109925760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b60448201526064016103fe565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b0381166115fb5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016103fe565b92915050565b6001600160a01b038116811461068957600080fd5b600080600080600060a0868803121561162e57600080fd5b853561163981611601565b9450602086013561164981611601565b9350604086013561165981611601565b9250606086013561166981611601565b9150608086013561167981611601565b809150509295509295909350565b801515811461068957600080fd5b600080600080600080600080610100898b0312156116b257600080fd5b88356116bd81611601565b975060208901356116cd81611601565b965060408901356116dd81611601565b955060608901356116ed81611601565b945060808901356116fd81611601565b935060a089013561170d81611687565b925060c089013561171d81611687565b915060e089013561172d81611601565b809150509295985092959890939650565b60006020828403121561175057600080fd5b813561175b81611601565b9392505050565b60006020828403121561177457600080fd5b813561175b81611687565b60008060006060848603121561179457600080fd5b833561179f81611601565b925060208401356117af81611601565b929592945050506040919091013590565b600080600080606085870312156117d657600080fd5b8435935060208501356117e881611601565b9250604085013567ffffffffffffffff8082111561180557600080fd5b818701915087601f83011261181957600080fd5b81358181111561182857600080fd5b88602082850101111561183a57600080fd5b95989497505060200194505050565b6000806040838503121561185c57600080fd5b823561186781611601565b946020939093013593505050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b600080858511156118f757600080fd5b8386111561190457600080fd5b5050820193919092039150565b803560208310156115fb57600019602084900360031b1b1692915050565b60006020828403121561194157600080fd5b815161175b81611601565b60208082526023908201527f4368696c6445524332305072656469636174653a20554e4d41505045445f544f60408201526225a2a760e91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b6000602082840312156119d057600080fd5b815161175b81611687565b60005b838110156119f65781810151838201526020016119de565b50506000910152565b60008151808452611a178160208601602086016119db565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090611a4f908301846119ff565b949350505050565b60008060008060808587031215611a6d57600080fd5b8435611a7881611601565b93506020850135611a8881611601565b92506040850135611a9881611601565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611acf57600080fd5b813567ffffffffffffffff80821115611aea57611aea611aa8565b604051601f8301601f19908116603f01168101908282118183101715611b1257611b12611aa8565b81604052838152866020858801011115611b2b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a08688031215611b6357600080fd5b853594506020860135611b7581611601565b9350604086013567ffffffffffffffff80821115611b9257600080fd5b611b9e89838a01611abe565b94506060880135915080821115611bb457600080fd5b50611bc188828901611abe565b925050608086013560ff8116811461167957600080fd5b6001600160a01b0385168152608060208201819052600090611bfc908301866119ff565b8281036040840152611c0e81866119ff565b91505060ff8316606083015295945050505050565b60008251611c358184602087016119db565b9190910192915050565b600060208284031215611c5157600080fd5b505191905056fea26469706673582212206cf96fe411dad9394c135358686b98cae9a19f7df3e05cbb3962783ddc9e15a964736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061018f5760003560e01c80638da5cb5b116100e4578063c5e4683a11610092578063c5e4683a14610323578063d41f177114610336578063e0563ab11461035d578063e30c397814610366578063eeb4994514610377578063f2fde38b1461038a578063f3fef3a31461039d578063f6451255146103b057600080fd5b80638da5cb5b1461029f578063947287cf146102b057806397e5230d146102b9578063b1768065146102c3578063b68ad1e4146102ea578063c1225a20146102fd578063c3b35a7e1461031057600080fd5b806354f8abad1161014157806354f8abad1461021a57806355b01e4d1461022d5780635ea5df791461023b578063715018a61461025257806371cf93b71461025a57806379ba50971461026d5780637efab4f51461027557600080fd5b806305dc2e8f1461019457806307b3e252146101c45780631459457a146101d25780631bc114ba146101e7578063284017f5146101fa5780633b878c221461020357806351351d531461020c575b600080fd5b60fd546101a7906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101a76004600360981b0181565b6101e56101e0366004611616565b6103d7565b005b60fc546101a7906001600160a01b031681565b6101a761202081565b6101a761101081565b6101a76002600160a01b0381565b6101e5610228366004611695565b6104db565b6101a76004600160991b0181565b61024461138881565b6040519081526020016101bb565b6101e56105fe565b60fe546101a7906001600160a01b031681565b6101e5610612565b6101a761028336600461173e565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b03166101a7565b61024461520881565b610244620249f081565b6102447f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff546101a7906001600160a01b031681565b6101e561030b366004611762565b61068c565b6101e561031e36600461177f565b6106db565b6101e5610331366004611762565b6106f3565b6102447f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101a761203081565b6065546001600160a01b03166101a7565b6101e56103853660046117c0565b61073a565b6101e561039836600461173e565b61090e565b6101e56103ab366004611849565b61097f565b6102447f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b336002600160a01b03146104075760405163973d02cb60e01b81526004016103fe90611875565b60405180910390fd5b600054610100900460ff16158080156104275750600054600160ff909116105b806104415750303b158015610441575060005460ff166001145b61045d5760405162461bcd60e51b81526004016103fe90611899565b6000805460ff191660011790558015610480576000805461ff0019166101001790555b61048d8686868686610996565b80156104d3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b336002600160a01b03146105025760405163973d02cb60e01b81526004016103fe90611875565b600054610100900460ff16158080156105225750600054600160ff909116105b8061053c5750303b15801561053c575060005460ff166001145b6105585760405162461bcd60e51b81526004016103fe90611899565b6000805460ff19166001179055801561057b576000805461ff0019166101001790555b6105888989898989610996565b60c9805461ffff191685151561ff00191617610100851515021790556105ad82610ae7565b80156105f3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050505050565b610606610b00565b6106106000610ae7565b565b60655433906001600160a01b031681146106805760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016103fe565b61068981610ae7565b50565b610694610b00565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b6106e3610b5a565b6106ee838383610b62565b505050565b6106fb610b00565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b60fd546001600160a01b031633146107a55760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f53544154455f6044820152672922a1a2a4ab22a960c11b60648201526084016103fe565b60fe546001600160a01b038481169116146108135760405162461bcd60e51b815260206004820152602860248201527f4368696c6445524332305072656469636174653a204f4e4c595f524f4f545f50604482015267524544494341544560c01b60648201526084016103fe565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216108426020600084866118e7565b61084b91611911565b0361086a5761086561086082602081866118e7565b610ed9565b610908565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6108996020600084866118e7565b6108a291611911565b036108b1576108658282611185565b60405162461bcd60e51b815260206004820152602660248201527f4368696c6445524332305072656469636174653a20494e56414c49445f5349476044820152654e415455524560d01b60648201526084016103fe565b50505050565b610916610b00565b606580546001600160a01b0383166001600160a01b031990911681179091556109476033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b610987610b5a565b610992823383610b62565b5050565b6001600160a01b038516158015906109b657506001600160a01b03841615155b80156109ca57506001600160a01b03831615155b80156109de57506001600160a01b03821615155b610a3a5760405162461bcd60e51b815260206004820152602760248201527f4368696c6445524332305072656469636174653a204241445f494e495449414c60448201526624ad20aa24a7a760c91b60648201526084016103fe565b60fc80546001600160a01b03199081166001600160a01b038881169190911790925560fd8054821687841617905560fe8054821686841617905560ff8054909116848316179055811615610ae0576001600160a01b0381166000818152610100602052604080822080546001600160a01b03191661101090811790915590519092917f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d91a35b5050505050565b606580546001600160a01b0319169055610689816112fc565b6033546001600160a01b031633146106105760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103fe565b61061061134e565b826001600160a01b03163b600003610bc65760405162461bcd60e51b815260206004820152602160248201527f4368696c6445524332305072656469636174653a204e4f545f434f4e545241436044820152601560fa1b60648201526084016103fe565b6000836001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2a919061192f565b6001600160a01b0381811660009081526101006020526040902054919250858116911614610c6a5760405162461bcd60e51b81526004016103fe9061194c565b6001600160a01b038116610c8057610c8061198f565b306001600160a01b0316846001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cec919061192f565b6001600160a01b031614610d0257610d0261198f565b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac90610d3090339086906004016119a5565b6020604051808303816000875af1158015610d4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7391906119be565b610dbf5760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204255524e5f4641494c454460448201526064016103fe565b60fc5460fe54604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610e4a9391169160c401611a2b565b600060405180830381600087803b158015610e6457600080fd5b505af1158015610e78573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316826001600160a01b03167fa0923f060a16fc784558d43de424ffde7b01643de5e5d335851b9df94c76bb273386604051610ecb9291906119a5565b60405180910390a450505050565b6000808080610eea85870187611a57565b6001600160a01b038085166000908152610100602052604090205494985092965090945092501680610f2e5760405162461bcd60e51b81526004016103fe9061194c565b806001600160a01b03163b600003610f4857610f4861198f565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fac919061192f565b9050856001600160a01b0316816001600160a01b031614610fcf57610fcf61198f565b6001600160a01b038116610fe557610fe561198f565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561102d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611051919061192f565b6001600160a01b0316146110675761106761198f565b6040516340c10f1960e01b81526001600160a01b038316906340c10f199061109590879087906004016119a5565b6020604051808303816000875af11580156110b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d891906119be565b6111245760405162461bcd60e51b815260206004820181905260248201527f4368696c6445524332305072656469636174653a204d494e545f4641494c454460448201526064016103fe565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fdf34f3a3ed8bedc14a4b284ebaee5374d55b64bac6a84c270dabe8fd6b4cdafd88876040516111739291906119a5565b60405180910390a45050505050505050565b600080808061119685870187611b4b565b92975090955093509150506001600160a01b0384166111b7576111b761198f565b6001600160a01b038481166000908152610100602052604090205416156111e0576111e061198f565b60ff546040516bffffffffffffffffffffffff19606087901b166020820152600091611230916001600160a01b039091169060340160405160208183030381529060405280519060200120611564565b6001600160a01b03868116600090815261010060205260409081902080546001600160a01b031916928416928317905551637b69774360e11b81529192509063f6d2ee8690611289908890889088908890600401611bd8565b600060405180830381600087803b1580156112a357600080fd5b505af11580156112b7573d6000803e3d6000fd5b50506040516001600160a01b038085169350881691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a350505050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c95460ff161561145957604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b0191611388916113b09190611c23565b6000604051808303818686fa925050503d80600081146113ec576040519150601f19603f3d011682016040523d82523d6000602084013e6113f1565b606091505b509150915081801561141657506000818060200190518101906114149190611c3f565b115b6114565760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b60448201526064016103fe565b50505b60c954610100900460ff161561061057604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b0191611388916114c09190611c23565b6000604051808303818686fa925050503d80600081146114fc576040519150601f19603f3d011682016040523d82523d6000602084013e611501565b606091505b50915091508180156115275750808060200190518101906115229190611c3f565b600114155b6109925760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b60448201526064016103fe565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b0381166115fb5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016103fe565b92915050565b6001600160a01b038116811461068957600080fd5b600080600080600060a0868803121561162e57600080fd5b853561163981611601565b9450602086013561164981611601565b9350604086013561165981611601565b9250606086013561166981611601565b9150608086013561167981611601565b809150509295509295909350565b801515811461068957600080fd5b600080600080600080600080610100898b0312156116b257600080fd5b88356116bd81611601565b975060208901356116cd81611601565b965060408901356116dd81611601565b955060608901356116ed81611601565b945060808901356116fd81611601565b935060a089013561170d81611687565b925060c089013561171d81611687565b915060e089013561172d81611601565b809150509295985092959890939650565b60006020828403121561175057600080fd5b813561175b81611601565b9392505050565b60006020828403121561177457600080fd5b813561175b81611687565b60008060006060848603121561179457600080fd5b833561179f81611601565b925060208401356117af81611601565b929592945050506040919091013590565b600080600080606085870312156117d657600080fd5b8435935060208501356117e881611601565b9250604085013567ffffffffffffffff8082111561180557600080fd5b818701915087601f83011261181957600080fd5b81358181111561182857600080fd5b88602082850101111561183a57600080fd5b95989497505060200194505050565b6000806040838503121561185c57600080fd5b823561186781611601565b946020939093013593505050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b600080858511156118f757600080fd5b8386111561190457600080fd5b5050820193919092039150565b803560208310156115fb57600019602084900360031b1b1692915050565b60006020828403121561194157600080fd5b815161175b81611601565b60208082526023908201527f4368696c6445524332305072656469636174653a20554e4d41505045445f544f60408201526225a2a760e91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b6000602082840312156119d057600080fd5b815161175b81611687565b60005b838110156119f65781810151838201526020016119de565b50506000910152565b60008151808452611a178160208601602086016119db565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090611a4f908301846119ff565b949350505050565b60008060008060808587031215611a6d57600080fd5b8435611a7881611601565b93506020850135611a8881611601565b92506040850135611a9881611601565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112611acf57600080fd5b813567ffffffffffffffff80821115611aea57611aea611aa8565b604051601f8301601f19908116603f01168101908282118183101715611b1257611b12611aa8565b81604052838152866020858801011115611b2b57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a08688031215611b6357600080fd5b853594506020860135611b7581611601565b9350604086013567ffffffffffffffff80821115611b9257600080fd5b611b9e89838a01611abe565b94506060880135915080821115611bb457600080fd5b50611bc188828901611abe565b925050608086013560ff8116811461167957600080fd5b6001600160a01b0385168152608060208201819052600090611bfc908301866119ff565b8281036040840152611c0e81866119ff565b91505060ff8316606083015295945050505050565b60008251611c358184602087016119db565b9190910192915050565b600060208284031215611c5157600080fd5b505191905056fea26469706673582212206cf96fe411dad9394c135358686b98cae9a19f7df3e05cbb3962783ddc9e15a964736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}" +var RootMintableERC20PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootMintableERC20Predicate\",\n \"sourceName\": \"contracts/child/RootMintableERC20Predicate.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC20Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC20Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b5061149f806100206000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806397e5230d116100b8578063e0563ab11161007c578063e0563ab1146102a2578063eeb49945146102ab578063f213159c146102be578063f4a120f7146102d1578063f6451255146102e4578063f8c8765e1461030b57600080fd5b806397e5230d14610224578063b17680651461022e578063b68ad1e414610255578063d41f177114610268578063d57184e41461028f57600080fd5b806347e7ef241161010a57806347e7ef24146101aa57806351351d53146101bf57806355b01e4d146101cd5780635ea5df79146101db5780637efab4f5146101f2578063947287cf1461021b57600080fd5b806305dc2e8f1461014757806307b3e252146101775780631bc114ba14610185578063284017f5146101985780633b878c22146101a1575b600080fd5b60345461015a906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61015a6004600360981b0181565b60335461015a906001600160a01b031681565b61015a61202081565b61015a61101081565b6101bd6101b8366004611038565b61031e565b005b61015a6002600160a01b0381565b61015a6004600160991b0181565b6101e461138881565b60405190815260200161016e565b61015a610200366004611064565b6037602052600090815260409020546001600160a01b031681565b6101e461520881565b6101e4620249f081565b6101e47f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60365461015a906001600160a01b031681565b6101e47f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b60355461015a906001600160a01b031681565b61015a61203081565b6101bd6102b9366004611088565b61032d565b6101bd6102cc366004611111565b6104d5565b61015a6102df366004611064565b6104e5565b6101e47f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b6101bd610319366004611152565b6108b1565b610329823383610a0e565b5050565b6034546001600160a01b031633146103a45760405162461bcd60e51b815260206004820152602f60248201527f526f6f744d696e7461626c6545524332305072656469636174653a204f4e4c5960448201526e2fa9aa20aa22afa922a1a2a4ab22a960891b60648201526084015b60405180910390fd5b6035546001600160a01b0384811691161461041a5760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c6545524332305072656469636174653a204f4e4c5960448201526f5f4348494c445f50524544494341544560801b606482015260840161039b565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696104496020600084866111ae565b610452916111d8565b036104715761046c61046782602081866111ae565b610b7e565b6104cf565b60405162461bcd60e51b815260206004820152602d60248201527f526f6f744d696e7461626c6545524332305072656469636174653a20494e564160448201526c4c49445f5349474e415455524560981b606482015260840161039b565b50505050565b6104e0838383610a0e565b505050565b60006001600160a01b03821661054f5760405162461bcd60e51b815260206004820152602960248201527f526f6f744d696e7461626c6545524332305072656469636174653a20494e56416044820152682624a22faa27a5a2a760b91b606482015260840161039b565b6001600160a01b0382811660009081526037602052604090205416156105ca5760405162461bcd60e51b815260206004820152602a60248201527f526f6f744d696e7461626c6545524332305072656469636174653a20414c524560448201526910511657d3505414115160b21b606482015260840161039b565b6035546036546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b039283169260009261067892911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b0385811660008181526037602052604080822080546001600160a01b03191686861617905560335481516306fdde0360e01b81529151959650909316936316f198319387937f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad938b9391926306fdde0392600480830193928290030181865afa158015610710573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107389190810190611231565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610776573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261079e9190810190611231565b8a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080091906112d3565b604051602001610814959493929190611322565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610840929190611374565b600060405180830381600087803b15801561085a57600080fd5b505af115801561086e573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a39392505050565b336002600160a01b03146108f55760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b604482015260640161039b565b600054610100900460ff16158080156109155750600054600160ff909116105b8061092f5750303b15801561092f575060005460ff166001145b6109925760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161039b565b6000805460ff1916600117905580156109b5576000805461ff0019166101001790555b6109c185858585610c36565b8015610a07576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b038084166000908152603760205260409020541680610a3a57610a37846104e5565b90505b6001600160a01b038116610a5057610a50611398565b610a656001600160a01b038516333085610d31565b603354603554604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b0388811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610af09391169160c401611374565b600060405180830381600087803b158015610b0a57600080fd5b505af1158015610b1e573d6000803e3d6000fd5b50505050826001600160a01b0316816001600160a01b0316856001600160a01b03167f1666a3f7b8a7494f2ebcebe646a5187ae55b1db3a068097377d90cd64a258ce93386604051610b719291906113ae565b60405180910390a46104cf565b6000808080610b8f858701876113c7565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610bc257610bc2611398565b610bd66001600160a01b0386168484610d9c565b826001600160a01b0316816001600160a01b0316866001600160a01b03167fb9f935478aae5b1da868de596dafe0a2b41eeb61311fdd60c6dbbe46a1debee88786604051610c259291906113ae565b60405180910390a450505050505050565b6001600160a01b03841615801590610c5657506001600160a01b03831615155b8015610c6a57506001600160a01b03821615155b8015610c7e57506001600160a01b03811615155b610ce15760405162461bcd60e51b815260206004820152602e60248201527f526f6f744d696e7461626c6545524332305072656469636174653a204241445f60448201526d24a724aa24a0a624ad20aa24a7a760911b606482015260840161039b565b603380546001600160a01b039586166001600160a01b0319918216179091556034805494861694821694909417909355603580549285169284169290921790915560368054919093169116179055565b6040516001600160a01b03808516602483015283166044820152606481018290526104cf9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610dbb565b6104e08363a9059cbb60e01b8484604051602401610d659291906113ae565b6000610e10826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610e909092919063ffffffff16565b9050805160001480610e31575080806020019051810190610e319190611418565b6104e05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161039b565b6060610e9f8484600085610ea7565b949350505050565b606082471015610f085760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161039b565b600080866001600160a01b03168587604051610f24919061143a565b60006040518083038185875af1925050503d8060008114610f61576040519150601f19603f3d011682016040523d82523d6000602084013e610f66565b606091505b5091509150610f7787838387610f82565b979650505050505050565b60608315610ff1578251600003610fea576001600160a01b0385163b610fea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161039b565b5081610e9f565b610e9f83838151156110065781518083602001fd5b8060405162461bcd60e51b815260040161039b9190611456565b6001600160a01b038116811461103557600080fd5b50565b6000806040838503121561104b57600080fd5b823561105681611020565b946020939093013593505050565b60006020828403121561107657600080fd5b813561108181611020565b9392505050565b6000806000806060858703121561109e57600080fd5b8435935060208501356110b081611020565b9250604085013567ffffffffffffffff808211156110cd57600080fd5b818701915087601f8301126110e157600080fd5b8135818111156110f057600080fd5b88602082850101111561110257600080fd5b95989497505060200194505050565b60008060006060848603121561112657600080fd5b833561113181611020565b9250602084013561114181611020565b929592945050506040919091013590565b6000806000806080858703121561116857600080fd5b843561117381611020565b9350602085013561118381611020565b9250604085013561119381611020565b915060608501356111a381611020565b939692955090935050565b600080858511156111be57600080fd5b838611156111cb57600080fd5b5050820193919092039150565b803560208310156111f157600019602084900360031b1b165b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015611228578181015183820152602001611210565b50506000910152565b60006020828403121561124357600080fd5b815167ffffffffffffffff8082111561125b57600080fd5b818401915084601f83011261126f57600080fd5b815181811115611281576112816111f7565b604051601f8201601f19908116603f011681019083821181831017156112a9576112a96111f7565b816040528281528760208487010111156112c257600080fd5b610f7783602083016020880161120d565b6000602082840312156112e557600080fd5b815160ff8116811461108157600080fd5b6000815180845261130e81602086016020860161120d565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260a06040820181905260009061134c908301866112f6565b828103606084015261135e81866112f6565b91505060ff831660808301529695505050505050565b6001600160a01b0383168152604060208201819052600090610e9f908301846112f6565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b600080600080608085870312156113dd57600080fd5b84356113e881611020565b935060208501356113f881611020565b9250604085013561140881611020565b9396929550929360600135925050565b60006020828403121561142a57600080fd5b8151801515811461108157600080fd5b6000825161144c81846020870161120d565b9190910192915050565b60208152600061108160208301846112f656fea26469706673582212208702e16b20ba9010d9192a951f06043b831a88e90ebd7657e3470c54f66e57f064736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101425760003560e01c806397e5230d116100b8578063e0563ab11161007c578063e0563ab1146102a2578063eeb49945146102ab578063f213159c146102be578063f4a120f7146102d1578063f6451255146102e4578063f8c8765e1461030b57600080fd5b806397e5230d14610224578063b17680651461022e578063b68ad1e414610255578063d41f177114610268578063d57184e41461028f57600080fd5b806347e7ef241161010a57806347e7ef24146101aa57806351351d53146101bf57806355b01e4d146101cd5780635ea5df79146101db5780637efab4f5146101f2578063947287cf1461021b57600080fd5b806305dc2e8f1461014757806307b3e252146101775780631bc114ba14610185578063284017f5146101985780633b878c22146101a1575b600080fd5b60345461015a906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61015a6004600360981b0181565b60335461015a906001600160a01b031681565b61015a61202081565b61015a61101081565b6101bd6101b8366004611038565b61031e565b005b61015a6002600160a01b0381565b61015a6004600160991b0181565b6101e461138881565b60405190815260200161016e565b61015a610200366004611064565b6037602052600090815260409020546001600160a01b031681565b6101e461520881565b6101e4620249f081565b6101e47f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60365461015a906001600160a01b031681565b6101e47f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b60355461015a906001600160a01b031681565b61015a61203081565b6101bd6102b9366004611088565b61032d565b6101bd6102cc366004611111565b6104d5565b61015a6102df366004611064565b6104e5565b6101e47f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b6101bd610319366004611152565b6108b1565b610329823383610a0e565b5050565b6034546001600160a01b031633146103a45760405162461bcd60e51b815260206004820152602f60248201527f526f6f744d696e7461626c6545524332305072656469636174653a204f4e4c5960448201526e2fa9aa20aa22afa922a1a2a4ab22a960891b60648201526084015b60405180910390fd5b6035546001600160a01b0384811691161461041a5760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c6545524332305072656469636174653a204f4e4c5960448201526f5f4348494c445f50524544494341544560801b606482015260840161039b565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696104496020600084866111ae565b610452916111d8565b036104715761046c61046782602081866111ae565b610b7e565b6104cf565b60405162461bcd60e51b815260206004820152602d60248201527f526f6f744d696e7461626c6545524332305072656469636174653a20494e564160448201526c4c49445f5349474e415455524560981b606482015260840161039b565b50505050565b6104e0838383610a0e565b505050565b60006001600160a01b03821661054f5760405162461bcd60e51b815260206004820152602960248201527f526f6f744d696e7461626c6545524332305072656469636174653a20494e56416044820152682624a22faa27a5a2a760b91b606482015260840161039b565b6001600160a01b0382811660009081526037602052604090205416156105ca5760405162461bcd60e51b815260206004820152602a60248201527f526f6f744d696e7461626c6545524332305072656469636174653a20414c524560448201526910511657d3505414115160b21b606482015260840161039b565b6035546036546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b039283169260009261067892911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b0385811660008181526037602052604080822080546001600160a01b03191686861617905560335481516306fdde0360e01b81529151959650909316936316f198319387937f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad938b9391926306fdde0392600480830193928290030181865afa158015610710573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107389190810190611231565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610776573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261079e9190810190611231565b8a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080091906112d3565b604051602001610814959493929190611322565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610840929190611374565b600060405180830381600087803b15801561085a57600080fd5b505af115801561086e573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a39392505050565b336002600160a01b03146108f55760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b604482015260640161039b565b600054610100900460ff16158080156109155750600054600160ff909116105b8061092f5750303b15801561092f575060005460ff166001145b6109925760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161039b565b6000805460ff1916600117905580156109b5576000805461ff0019166101001790555b6109c185858585610c36565b8015610a07576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6001600160a01b038084166000908152603760205260409020541680610a3a57610a37846104e5565b90505b6001600160a01b038116610a5057610a50611398565b610a656001600160a01b038516333085610d31565b603354603554604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b0388811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610af09391169160c401611374565b600060405180830381600087803b158015610b0a57600080fd5b505af1158015610b1e573d6000803e3d6000fd5b50505050826001600160a01b0316816001600160a01b0316856001600160a01b03167f1666a3f7b8a7494f2ebcebe646a5187ae55b1db3a068097377d90cd64a258ce93386604051610b719291906113ae565b60405180910390a46104cf565b6000808080610b8f858701876113c7565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610bc257610bc2611398565b610bd66001600160a01b0386168484610d9c565b826001600160a01b0316816001600160a01b0316866001600160a01b03167fb9f935478aae5b1da868de596dafe0a2b41eeb61311fdd60c6dbbe46a1debee88786604051610c259291906113ae565b60405180910390a450505050505050565b6001600160a01b03841615801590610c5657506001600160a01b03831615155b8015610c6a57506001600160a01b03821615155b8015610c7e57506001600160a01b03811615155b610ce15760405162461bcd60e51b815260206004820152602e60248201527f526f6f744d696e7461626c6545524332305072656469636174653a204241445f60448201526d24a724aa24a0a624ad20aa24a7a760911b606482015260840161039b565b603380546001600160a01b039586166001600160a01b0319918216179091556034805494861694821694909417909355603580549285169284169290921790915560368054919093169116179055565b6040516001600160a01b03808516602483015283166044820152606481018290526104cf9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610dbb565b6104e08363a9059cbb60e01b8484604051602401610d659291906113ae565b6000610e10826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610e909092919063ffffffff16565b9050805160001480610e31575080806020019051810190610e319190611418565b6104e05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161039b565b6060610e9f8484600085610ea7565b949350505050565b606082471015610f085760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161039b565b600080866001600160a01b03168587604051610f24919061143a565b60006040518083038185875af1925050503d8060008114610f61576040519150601f19603f3d011682016040523d82523d6000602084013e610f66565b606091505b5091509150610f7787838387610f82565b979650505050505050565b60608315610ff1578251600003610fea576001600160a01b0385163b610fea5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161039b565b5081610e9f565b610e9f83838151156110065781518083602001fd5b8060405162461bcd60e51b815260040161039b9190611456565b6001600160a01b038116811461103557600080fd5b50565b6000806040838503121561104b57600080fd5b823561105681611020565b946020939093013593505050565b60006020828403121561107657600080fd5b813561108181611020565b9392505050565b6000806000806060858703121561109e57600080fd5b8435935060208501356110b081611020565b9250604085013567ffffffffffffffff808211156110cd57600080fd5b818701915087601f8301126110e157600080fd5b8135818111156110f057600080fd5b88602082850101111561110257600080fd5b95989497505060200194505050565b60008060006060848603121561112657600080fd5b833561113181611020565b9250602084013561114181611020565b929592945050506040919091013590565b6000806000806080858703121561116857600080fd5b843561117381611020565b9350602085013561118381611020565b9250604085013561119381611020565b915060608501356111a381611020565b939692955090935050565b600080858511156111be57600080fd5b838611156111cb57600080fd5b5050820193919092039150565b803560208310156111f157600019602084900360031b1b165b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015611228578181015183820152602001611210565b50506000910152565b60006020828403121561124357600080fd5b815167ffffffffffffffff8082111561125b57600080fd5b818401915084601f83011261126f57600080fd5b815181811115611281576112816111f7565b604051601f8201601f19908116603f011681019083821181831017156112a9576112a96111f7565b816040528281528760208487010111156112c257600080fd5b610f7783602083016020880161120d565b6000602082840312156112e557600080fd5b815160ff8116811461108157600080fd5b6000815180845261130e81602086016020860161120d565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260a06040820181905260009061134c908301866112f6565b828103606084015261135e81866112f6565b91505060ff831660808301529695505050505050565b6001600160a01b0383168152604060208201819052600090610e9f908301846112f6565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b600080600080608085870312156113dd57600080fd5b84356113e881611020565b935060208501356113f881611020565b9250604085013561140881611020565b9396929550929360600135925050565b60006020828403121561142a57600080fd5b8151801515811461108157600080fd5b6000825161144c81846020870161120d565b9190910192915050565b60208152600061108160208301846112f656fea26469706673582212208702e16b20ba9010d9192a951f06043b831a88e90ebd7657e3470c54f66e57f064736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RootMintableERC20PredicateACLArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootMintableERC20PredicateAccessList\",\n \"sourceName\": \"contracts/child/RootMintableERC20PredicateAccessList.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"AllowListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"BlockListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC20Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC20Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setAllowList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setBlockList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611bfb806100206000396000f3fe608060405234801561001057600080fd5b506004361061019a5760003560e01c8063b1768065116100e4578063e0563ab111610092578063e0563ab114610355578063e30c39781461035e578063eeb499451461036f578063f213159c14610382578063f2fde38b14610395578063f4a120f7146103a8578063f6451255146103bb578063f8c8765e146103e257600080fd5b8063b1768065146102a8578063b68ad1e4146102cf578063c1225a20146102e2578063c5e4683a146102f5578063d41f177114610308578063d57184e41461032f578063d8dd17731461034257600080fd5b806355b01e4d1161014c57806355b01e4d146102255780635ea5df7914610233578063715018a61461024a57806379ba5097146102525780637efab4f51461025a5780638da5cb5b14610284578063947287cf1461029557806397e5230d1461029e57600080fd5b806305dc2e8f1461019f57806307b3e252146101cf5780631bc114ba146101dd578063284017f5146101f05780633b878c22146101f957806347e7ef241461020257806351351d5314610217575b600080fd5b60fd546101b2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101b26004600360981b0181565b60fc546101b2906001600160a01b031681565b6101b261202081565b6101b261101081565b61021561021036600461164d565b6103f5565b005b6101b26002600160a01b0381565b6101b26004600160991b0181565b61023c61138881565b6040519081526020016101c6565b610215610404565b610215610418565b6101b2610268366004611679565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b03166101b2565b61023c61520881565b61023c620249f081565b61023c7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff546101b2906001600160a01b031681565b6102156102f03660046116ab565b610497565b6102156103033660046116ab565b6104e6565b61023c7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b60fe546101b2906001600160a01b031681565b6102156103503660046116c8565b61052d565b6101b261203081565b6065546001600160a01b03166101b2565b61021561037d36600461175e565b61064e565b6102156103903660046117e7565b6107f1565b6102156103a3366004611679565b610801565b6101b26103b6366004611679565b610872565b61023c7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b6102156103f0366004611828565b610c40565b610400823383610d39565b5050565b61040c610eb2565b6104166000610f0c565b565b60655433906001600160a01b0316811461048b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61049481610f0c565b50565b61049f610eb2565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b6104ee610eb2565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b03146105545760405163973d02cb60e01b815260040161048290611884565b600054610100900460ff16158080156105745750600054600160ff909116105b8061058e5750303b15801561058e575060005460ff166001145b6105aa5760405162461bcd60e51b8152600401610482906118a8565b6000805460ff1916600117905580156105cd576000805461ff0019166101001790555b6105d988888888610f25565b60c9805461ffff191685151561ff00191617610100851515021790556105fe82610f0c565b8015610644576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146106c05760405162461bcd60e51b815260206004820152602f60248201527f526f6f744d696e7461626c6545524332305072656469636174653a204f4e4c5960448201526e2fa9aa20aa22afa922a1a2a4ab22a960891b6064820152608401610482565b60fe546001600160a01b038481169116146107365760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c6545524332305072656469636174653a204f4e4c5960448201526f5f4348494c445f50524544494341544560801b6064820152608401610482565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696107656020600084866118f6565b61076e91611920565b0361078d5761078861078382602081866118f6565b611020565b6107eb565b60405162461bcd60e51b815260206004820152602d60248201527f526f6f744d696e7461626c6545524332305072656469636174653a20494e564160448201526c4c49445f5349474e415455524560981b6064820152608401610482565b50505050565b6107fc838383610d39565b505050565b610809610eb2565b606580546001600160a01b0383166001600160a01b0319909116811790915561083a6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60006001600160a01b0382166108dc5760405162461bcd60e51b815260206004820152602960248201527f526f6f744d696e7461626c6545524332305072656469636174653a20494e56416044820152682624a22faa27a5a2a760b91b6064820152608401610482565b6001600160a01b038281166000908152610100602052604090205416156109585760405162461bcd60e51b815260206004820152602a60248201527f526f6f744d696e7461626c6545524332305072656469636174653a20414c524560448201526910511657d3505414115160b21b6064820152608401610482565b60fe5460ff546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b0392831692600092610a0692911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b038581166000818152610100602052604080822080546001600160a01b03191686861617905560fc5481516306fdde0360e01b81529151959650909316936316f198319387937f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad938b9391926306fdde0392600480830193928290030181865afa158015610a9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ac79190810190611979565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610b05573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b2d9190810190611979565b8a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8f9190611a1b565b604051602001610ba3959493929190611a6a565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610bcf929190611abc565b600060405180830381600087803b158015610be957600080fd5b505af1158015610bfd573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a39392505050565b336002600160a01b0314610c675760405163973d02cb60e01b815260040161048290611884565b600054610100900460ff1615808015610c875750600054600160ff909116105b80610ca15750303b158015610ca1575060005460ff166001145b610cbd5760405162461bcd60e51b8152600401610482906118a8565b6000805460ff191660011790558015610ce0576000805461ff0019166101001790555b610cec85858585610f25565b8015610d32576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b610d416110d9565b6001600160a01b03808416600090815261010060205260409020541680610d6e57610d6b84610872565b90505b6001600160a01b038116610d8457610d84611ae0565b610d996001600160a01b0385163330856110e1565b60fc5460fe54604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b0388811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610e249391169160c401611abc565b600060405180830381600087803b158015610e3e57600080fd5b505af1158015610e52573d6000803e3d6000fd5b50505050826001600160a01b0316816001600160a01b0316856001600160a01b03167f1666a3f7b8a7494f2ebcebe646a5187ae55b1db3a068097377d90cd64a258ce93386604051610ea5929190611af6565b60405180910390a46107eb565b6033546001600160a01b031633146104165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610482565b606580546001600160a01b03191690556104948161114c565b6001600160a01b03841615801590610f4557506001600160a01b03831615155b8015610f5957506001600160a01b03821615155b8015610f6d57506001600160a01b03811615155b610fd05760405162461bcd60e51b815260206004820152602e60248201527f526f6f744d696e7461626c6545524332305072656469636174653a204241445f60448201526d24a724aa24a0a624ad20aa24a7a760911b6064820152608401610482565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b600080808061103185870187611b0f565b6001600160a01b03808516600090815261010060205260409020549498509296509094509250168061106557611065611ae0565b6110796001600160a01b038616848461119e565b826001600160a01b0316816001600160a01b0316866001600160a01b03167fb9f935478aae5b1da868de596dafe0a2b41eeb61311fdd60c6dbbe46a1debee887866040516110c8929190611af6565b60405180910390a450505050505050565b6104166111bd565b6040516001600160a01b03808516602483015283166044820152606481018290526107eb9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526113d3565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6107fc8363a9059cbb60e01b8484604051602401611115929190611af6565b60c95460ff16156112c857604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161121f9190611b60565b6000604051808303818686fa925050503d806000811461125b576040519150601f19603f3d011682016040523d82523d6000602084013e611260565b606091505b509150915081801561128557506000818060200190518101906112839190611b7c565b115b6112c55760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b6044820152606401610482565b50505b60c954610100900460ff161561041657604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b01916113889161132f9190611b60565b6000604051808303818686fa925050503d806000811461136b576040519150601f19603f3d011682016040523d82523d6000602084013e611370565b606091505b50915091508180156113965750808060200190518101906113919190611b7c565b600114155b6104005760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b6044820152606401610482565b6000611428826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166114a89092919063ffffffff16565b90508051600014806114495750808060200190518101906114499190611b95565b6107fc5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610482565b60606114b784846000856114bf565b949350505050565b6060824710156115205760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610482565b600080866001600160a01b0316858760405161153c9190611b60565b60006040518083038185875af1925050503d8060008114611579576040519150601f19603f3d011682016040523d82523d6000602084013e61157e565b606091505b509150915061158f8783838761159a565b979650505050505050565b60608315611609578251600003611602576001600160a01b0385163b6116025760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610482565b50816114b7565b6114b7838381511561161e5781518083602001fd5b8060405162461bcd60e51b81526004016104829190611bb2565b6001600160a01b038116811461049457600080fd5b6000806040838503121561166057600080fd5b823561166b81611638565b946020939093013593505050565b60006020828403121561168b57600080fd5b813561169681611638565b9392505050565b801515811461049457600080fd5b6000602082840312156116bd57600080fd5b81356116968161169d565b600080600080600080600060e0888a0312156116e357600080fd5b87356116ee81611638565b965060208801356116fe81611638565b9550604088013561170e81611638565b9450606088013561171e81611638565b9350608088013561172e8161169d565b925060a088013561173e8161169d565b915060c088013561174e81611638565b8091505092959891949750929550565b6000806000806060858703121561177457600080fd5b84359350602085013561178681611638565b9250604085013567ffffffffffffffff808211156117a357600080fd5b818701915087601f8301126117b757600080fd5b8135818111156117c657600080fd5b8860208285010111156117d857600080fd5b95989497505060200194505050565b6000806000606084860312156117fc57600080fd5b833561180781611638565b9250602084013561181781611638565b929592945050506040919091013590565b6000806000806080858703121561183e57600080fd5b843561184981611638565b9350602085013561185981611638565b9250604085013561186981611638565b9150606085013561187981611638565b939692955090935050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000808585111561190657600080fd5b8386111561191357600080fd5b5050820193919092039150565b8035602083101561193957600019602084900360031b1b165b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015611970578181015183820152602001611958565b50506000910152565b60006020828403121561198b57600080fd5b815167ffffffffffffffff808211156119a357600080fd5b818401915084601f8301126119b757600080fd5b8151818111156119c9576119c961193f565b604051601f8201601f19908116603f011681019083821181831017156119f1576119f161193f565b81604052828152876020848701011115611a0a57600080fd5b61158f836020830160208801611955565b600060208284031215611a2d57600080fd5b815160ff8116811461169657600080fd5b60008151808452611a56816020860160208601611955565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260a060408201819052600090611a9490830186611a3e565b8281036060840152611aa68186611a3e565b91505060ff831660808301529695505050505050565b6001600160a01b03831681526040602082018190526000906114b790830184611a3e565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b60008060008060808587031215611b2557600080fd5b8435611b3081611638565b93506020850135611b4081611638565b92506040850135611b5081611638565b9396929550929360600135925050565b60008251611b72818460208701611955565b9190910192915050565b600060208284031215611b8e57600080fd5b5051919050565b600060208284031215611ba757600080fd5b81516116968161169d565b6020815260006116966020830184611a3e56fea264697066735822122046fe624d67d8c63ac14f4e051a861c827d5567a4754eee6b34a8b0d710c884d664736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061019a5760003560e01c8063b1768065116100e4578063e0563ab111610092578063e0563ab114610355578063e30c39781461035e578063eeb499451461036f578063f213159c14610382578063f2fde38b14610395578063f4a120f7146103a8578063f6451255146103bb578063f8c8765e146103e257600080fd5b8063b1768065146102a8578063b68ad1e4146102cf578063c1225a20146102e2578063c5e4683a146102f5578063d41f177114610308578063d57184e41461032f578063d8dd17731461034257600080fd5b806355b01e4d1161014c57806355b01e4d146102255780635ea5df7914610233578063715018a61461024a57806379ba5097146102525780637efab4f51461025a5780638da5cb5b14610284578063947287cf1461029557806397e5230d1461029e57600080fd5b806305dc2e8f1461019f57806307b3e252146101cf5780631bc114ba146101dd578063284017f5146101f05780633b878c22146101f957806347e7ef241461020257806351351d5314610217575b600080fd5b60fd546101b2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101b26004600360981b0181565b60fc546101b2906001600160a01b031681565b6101b261202081565b6101b261101081565b61021561021036600461164d565b6103f5565b005b6101b26002600160a01b0381565b6101b26004600160991b0181565b61023c61138881565b6040519081526020016101c6565b610215610404565b610215610418565b6101b2610268366004611679565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b03166101b2565b61023c61520881565b61023c620249f081565b61023c7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff546101b2906001600160a01b031681565b6102156102f03660046116ab565b610497565b6102156103033660046116ab565b6104e6565b61023c7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b60fe546101b2906001600160a01b031681565b6102156103503660046116c8565b61052d565b6101b261203081565b6065546001600160a01b03166101b2565b61021561037d36600461175e565b61064e565b6102156103903660046117e7565b6107f1565b6102156103a3366004611679565b610801565b6101b26103b6366004611679565b610872565b61023c7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b6102156103f0366004611828565b610c40565b610400823383610d39565b5050565b61040c610eb2565b6104166000610f0c565b565b60655433906001600160a01b0316811461048b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61049481610f0c565b50565b61049f610eb2565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b6104ee610eb2565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b03146105545760405163973d02cb60e01b815260040161048290611884565b600054610100900460ff16158080156105745750600054600160ff909116105b8061058e5750303b15801561058e575060005460ff166001145b6105aa5760405162461bcd60e51b8152600401610482906118a8565b6000805460ff1916600117905580156105cd576000805461ff0019166101001790555b6105d988888888610f25565b60c9805461ffff191685151561ff00191617610100851515021790556105fe82610f0c565b8015610644576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146106c05760405162461bcd60e51b815260206004820152602f60248201527f526f6f744d696e7461626c6545524332305072656469636174653a204f4e4c5960448201526e2fa9aa20aa22afa922a1a2a4ab22a960891b6064820152608401610482565b60fe546001600160a01b038481169116146107365760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c6545524332305072656469636174653a204f4e4c5960448201526f5f4348494c445f50524544494341544560801b6064820152608401610482565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696107656020600084866118f6565b61076e91611920565b0361078d5761078861078382602081866118f6565b611020565b6107eb565b60405162461bcd60e51b815260206004820152602d60248201527f526f6f744d696e7461626c6545524332305072656469636174653a20494e564160448201526c4c49445f5349474e415455524560981b6064820152608401610482565b50505050565b6107fc838383610d39565b505050565b610809610eb2565b606580546001600160a01b0383166001600160a01b0319909116811790915561083a6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60006001600160a01b0382166108dc5760405162461bcd60e51b815260206004820152602960248201527f526f6f744d696e7461626c6545524332305072656469636174653a20494e56416044820152682624a22faa27a5a2a760b91b6064820152608401610482565b6001600160a01b038281166000908152610100602052604090205416156109585760405162461bcd60e51b815260206004820152602a60248201527f526f6f744d696e7461626c6545524332305072656469636174653a20414c524560448201526910511657d3505414115160b21b6064820152608401610482565b60fe5460ff546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b0392831692600092610a0692911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b038581166000818152610100602052604080822080546001600160a01b03191686861617905560fc5481516306fdde0360e01b81529151959650909316936316f198319387937f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad938b9391926306fdde0392600480830193928290030181865afa158015610a9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ac79190810190611979565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610b05573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610b2d9190810190611979565b8a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8f9190611a1b565b604051602001610ba3959493929190611a6a565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610bcf929190611abc565b600060405180830381600087803b158015610be957600080fd5b505af1158015610bfd573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a39392505050565b336002600160a01b0314610c675760405163973d02cb60e01b815260040161048290611884565b600054610100900460ff1615808015610c875750600054600160ff909116105b80610ca15750303b158015610ca1575060005460ff166001145b610cbd5760405162461bcd60e51b8152600401610482906118a8565b6000805460ff191660011790558015610ce0576000805461ff0019166101001790555b610cec85858585610f25565b8015610d32576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b610d416110d9565b6001600160a01b03808416600090815261010060205260409020541680610d6e57610d6b84610872565b90505b6001600160a01b038116610d8457610d84611ae0565b610d996001600160a01b0385163330856110e1565b60fc5460fe54604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b0388811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610e249391169160c401611abc565b600060405180830381600087803b158015610e3e57600080fd5b505af1158015610e52573d6000803e3d6000fd5b50505050826001600160a01b0316816001600160a01b0316856001600160a01b03167f1666a3f7b8a7494f2ebcebe646a5187ae55b1db3a068097377d90cd64a258ce93386604051610ea5929190611af6565b60405180910390a46107eb565b6033546001600160a01b031633146104165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610482565b606580546001600160a01b03191690556104948161114c565b6001600160a01b03841615801590610f4557506001600160a01b03831615155b8015610f5957506001600160a01b03821615155b8015610f6d57506001600160a01b03811615155b610fd05760405162461bcd60e51b815260206004820152602e60248201527f526f6f744d696e7461626c6545524332305072656469636174653a204241445f60448201526d24a724aa24a0a624ad20aa24a7a760911b6064820152608401610482565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b600080808061103185870187611b0f565b6001600160a01b03808516600090815261010060205260409020549498509296509094509250168061106557611065611ae0565b6110796001600160a01b038616848461119e565b826001600160a01b0316816001600160a01b0316866001600160a01b03167fb9f935478aae5b1da868de596dafe0a2b41eeb61311fdd60c6dbbe46a1debee887866040516110c8929190611af6565b60405180910390a450505050505050565b6104166111bd565b6040516001600160a01b03808516602483015283166044820152606481018290526107eb9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526113d3565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6107fc8363a9059cbb60e01b8484604051602401611115929190611af6565b60c95460ff16156112c857604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161121f9190611b60565b6000604051808303818686fa925050503d806000811461125b576040519150601f19603f3d011682016040523d82523d6000602084013e611260565b606091505b509150915081801561128557506000818060200190518101906112839190611b7c565b115b6112c55760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b6044820152606401610482565b50505b60c954610100900460ff161561041657604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b01916113889161132f9190611b60565b6000604051808303818686fa925050503d806000811461136b576040519150601f19603f3d011682016040523d82523d6000602084013e611370565b606091505b50915091508180156113965750808060200190518101906113919190611b7c565b600114155b6104005760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b6044820152606401610482565b6000611428826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166114a89092919063ffffffff16565b90508051600014806114495750808060200190518101906114499190611b95565b6107fc5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610482565b60606114b784846000856114bf565b949350505050565b6060824710156115205760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610482565b600080866001600160a01b0316858760405161153c9190611b60565b60006040518083038185875af1925050503d8060008114611579576040519150601f19603f3d011682016040523d82523d6000602084013e61157e565b606091505b509150915061158f8783838761159a565b979650505050505050565b60608315611609578251600003611602576001600160a01b0385163b6116025760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610482565b50816114b7565b6114b7838381511561161e5781518083602001fd5b8060405162461bcd60e51b81526004016104829190611bb2565b6001600160a01b038116811461049457600080fd5b6000806040838503121561166057600080fd5b823561166b81611638565b946020939093013593505050565b60006020828403121561168b57600080fd5b813561169681611638565b9392505050565b801515811461049457600080fd5b6000602082840312156116bd57600080fd5b81356116968161169d565b600080600080600080600060e0888a0312156116e357600080fd5b87356116ee81611638565b965060208801356116fe81611638565b9550604088013561170e81611638565b9450606088013561171e81611638565b9350608088013561172e8161169d565b925060a088013561173e8161169d565b915060c088013561174e81611638565b8091505092959891949750929550565b6000806000806060858703121561177457600080fd5b84359350602085013561178681611638565b9250604085013567ffffffffffffffff808211156117a357600080fd5b818701915087601f8301126117b757600080fd5b8135818111156117c657600080fd5b8860208285010111156117d857600080fd5b95989497505060200194505050565b6000806000606084860312156117fc57600080fd5b833561180781611638565b9250602084013561181781611638565b929592945050506040919091013590565b6000806000806080858703121561183e57600080fd5b843561184981611638565b9350602085013561185981611638565b9250604085013561186981611638565b9150606085013561187981611638565b939692955090935050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000808585111561190657600080fd5b8386111561191357600080fd5b5050820193919092039150565b8035602083101561193957600019602084900360031b1b165b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015611970578181015183820152602001611958565b50506000910152565b60006020828403121561198b57600080fd5b815167ffffffffffffffff808211156119a357600080fd5b818401915084601f8301126119b757600080fd5b8151818111156119c9576119c961193f565b604051601f8201601f19908116603f011681019083821181831017156119f1576119f161193f565b81604052828152876020848701011115611a0a57600080fd5b61158f836020830160208801611955565b600060208284031215611a2d57600080fd5b815160ff8116811461169657600080fd5b60008151808452611a56816020860160208601611955565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260a060408201819052600090611a9490830186611a3e565b8281036060840152611aa68186611a3e565b91505060ff831660808301529695505050505050565b6001600160a01b03831681526040602082018190526000906114b790830184611a3e565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b60008060008060808587031215611b2557600080fd5b8435611b3081611638565b93506020850135611b4081611638565b92506040850135611b5081611638565b9396929550929360600135925050565b60008251611b72818460208701611955565b9190910192915050565b600060208284031215611b8e57600080fd5b5051919050565b600060208284031215611ba757600080fd5b81516116968161169d565b6020815260006116966020830184611a3e56fea264697066735822122046fe624d67d8c63ac14f4e051a861c827d5567a4754eee6b34a8b0d710c884d664736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC721Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC721\",\n \"sourceName\": \"contracts/child/ChildERC721.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"approved\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bool\",\n \"name\": \"approved\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"ApprovalForAll\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"userAddress\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"relayerAddress\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"functionSignature\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"MetaTransactionExecuted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"burnBatch\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"userAddress\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"functionSignature\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"sigR\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"sigS\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"sigV\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"executeMetaTransaction\",\n \"outputs\": [\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getApproved\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"user\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"getNonce\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"nonce\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"rootToken_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"name_\",\n \"type\": \"string\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"symbol_\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"offset\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"invalidateNext\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"isApprovedForAll\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"accounts\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"mintBatch\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ownerOf\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"safeTransferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"safeTransferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"approved\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setApprovalForAll\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"tokenURI\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612488806100206000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c806370a08231116100c3578063a22cb4651161007c578063a22cb465146102de578063b2dc5dc3146102f1578063b88d4fde14610304578063c87b56dd14610317578063e61987051461032a578063e985e9c51461033c57600080fd5b806370a08231146102775780637c88e3d91461028a578063906571471461029d57806395d89b41146102b05780639b77ef11146102b85780639dc29fac146102cb57600080fd5b80631f2d0065116101155780631f2d0065146101e257806323b872dd146101f45780632d0335ab1461020757806340c10f191461023e57806342842e0e146102515780636352211e1461026457600080fd5b806301ffc9a71461015257806306fdde031461017a578063081812fc1461018f578063095ea7b3146101ba5780630c53c51c146101cf575b600080fd5b610165610160366004611a73565b61034f565b60405190151581526020015b60405180910390f35b6101826103a1565b6040516101719190611ae0565b6101a261019d366004611af3565b610433565b6040516001600160a01b039091168152602001610171565b6101cd6101c8366004611b28565b61045a565b005b6101826101dd366004611b9a565b610586565b610103546001600160a01b03166101a2565b6101cd610202366004611c19565b610864565b610230610215366004611c55565b6001600160a01b031660009081526038602052604090205490565b604051908152602001610171565b61016561024c366004611b28565b61089c565b6101cd61025f366004611c19565b6108dd565b6101a2610272366004611af3565b6108f8565b610230610285366004611c55565b61092d565b610165610298366004611cb4565b6109b3565b6101cd6102ab366004611d1f565b610a9b565b610182610d0b565b6101cd6102c6366004611af3565b610d1a565b6101656102d9366004611b28565b610d41565b6101cd6102ec366004611d9f565b610db1565b6101656102ff366004611ddb565b610dc7565b6101cd610312366004611e43565b610e75565b610182610325366004611af3565b610eb4565b610102546001600160a01b03166101a2565b61016561034a366004611f1e565b610f28565b60006001600160e01b031982166380ac58cd60e01b148061038057506001600160e01b03198216635b5e139f60e01b145b8061039b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060d080546103b090611f51565b80601f01602080910402602001604051908101604052809291908181526020018280546103dc90611f51565b80156104295780601f106103fe57610100808354040283529160200191610429565b820191906000526020600020905b81548152906001019060200180831161040c57829003601f168201915b5050505050905090565b600061043e82610f56565b50600090815260d460205260409020546001600160a01b031690565b6000610465826108f8565b9050806001600160a01b0316836001600160a01b0316036104d75760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b806001600160a01b03166104e9610f7e565b6001600160a01b0316148061050557506105058161034a610f7e565b6105775760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c00000060648201526084016104ce565b6105818383610f8d565b505050565b606060006105c987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ffb92505050565b90506001600160e01b031960003581169082160361064f5760405162461bcd60e51b815260206004820152603d60248201527f66756e6374696f6e5369676e61747572652063616e206e6f74206265206f662060448201527f657865637574654d6574615472616e73616374696f6e206d6574686f6400000060648201526084016104ce565b604080516060810182526001600160a01b038a16600081815260386020908152848220548452808401929092528351601f8b0183900483028101830185528a815290938301918b908b9081908401838280828437600092019190915250505091525090506106c08982888888611016565b6107165760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b60648201526084016104ce565b603860008a6001600160a01b03166001600160a01b031681526020019081526020016000206000815460010191905081905550600080306001600160a01b03168a8a8d60405160200161076b93929190611f8b565b60408051601f198184030181529082905261078591611fb1565b6000604051808303816000865af19150503d80600081146107c2576040519150601f19603f3d011682016040523d82523d6000602084013e6107c7565b606091505b5091509150816108195760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c0000000060448201526064016104ce565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b8b338c8c60405161084e9493929190611fcd565b60405180910390a19a9950505050505050505050565b61087561086f610f7e565b826110f2565b6108915760405162461bcd60e51b81526004016104ce90612019565b610581838383611150565b610102546000906001600160a01b031633146108ca5760405162461bcd60e51b81526004016104ce90612066565b6108d483836112a2565b50600192915050565b61058183838360405180602001604052806000815250610e75565b600081815260d260205260408120546001600160a01b03168061039b5760405162461bcd60e51b81526004016104ce906120aa565b60006001600160a01b0382166109975760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016104ce565b506001600160a01b0316600090815260d3602052604090205490565b610102546000906001600160a01b031633146109e15760405162461bcd60e51b81526004016104ce90612066565b83828114610a315760405162461bcd60e51b815260206004820152601f60248201527f4368696c644552433732313a204172726179206c656e206d69736d617463680060448201526064016104ce565b60005b81811015610a8c57610a84878783818110610a5157610a516120dc565b9050602002016020810190610a669190611c55565b868684818110610a7857610a786120dc565b905060200201356112a2565b600101610a34565b5060019150505b949350505050565b606b54610100900460ff1615808015610abb5750606b54600160ff909116105b80610ad55750303b158015610ad55750606b5460ff166001145b610b385760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016104ce565b606b805460ff191660011790558015610b5b57606b805461ff0019166101001790555b6001600160a01b03861615801590610b7257508315155b8015610b7d57508115155b610bc95760405162461bcd60e51b815260206004820152601f60248201527f4368696c644552433732313a2042616420696e697469616c697a6174696f6e0060448201526064016104ce565b61010380546001600160a01b0388166001600160a01b031991821617909155610102805490911633179055604080516020601f8701819004810282018101909252858152610c6591879087908190840183828082843760009201919091525050604080516020601f890181900481028201810190925287815292508791508690819084018382808284376000920191909152506112bc92505050565b610cbd85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b602082015291506112ed9050565b8015610d0357606b805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b606060d180546103b090611f51565b3360009081526038602052604081208054839290610d399084906120f2565b909155505050565b610102546000906001600160a01b03163314610d6f5760405162461bcd60e51b81526004016104ce90612066565b610d78826108f8565b6001600160a01b0316836001600160a01b031614610da85760405162461bcd60e51b81526004016104ce90612113565b6108d482611359565b610dc3610dbc610f7e565b83836113dc565b5050565b610102546000906001600160a01b03163314610df55760405162461bcd60e51b81526004016104ce90612066565b8160005b81811015610e69576000858583818110610e1557610e156120dc565b905060200201359050610e27816108f8565b6001600160a01b0316876001600160a01b031614610e575760405162461bcd60e51b81526004016104ce90612113565b610e6081611359565b50600101610df9565b50600195945050505050565b610e86610e80610f7e565b836110f2565b610ea25760405162461bcd60e51b81526004016104ce90612019565b610eae848484846114a6565b50505050565b6060610ebf82610f56565b6000610ed660408051602081019091526000815290565b90506000815111610ef65760405180602001604052806000815250610f21565b80610f00846114d9565b604051602001610f11929190612148565b6040516020818303038152906040525b9392505050565b6001600160a01b03918216600090815260d56020908152604080832093909416825291909152205460ff1690565b610f5f8161156b565b610f7b5760405162461bcd60e51b81526004016104ce906120aa565b50565b6000610f88611588565b905090565b600081815260d46020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610fc2826108f8565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000815160000361100e57506000919050565b506020015190565b600080600161102c611027886115e4565b611661565b6040805160008152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa15801561107a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166110d15760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b60448201526064016104ce565b866001600160a01b0316816001600160a01b03161491505095945050505050565b6000806110fe836108f8565b9050806001600160a01b0316846001600160a01b0316148061112557506111258185610f28565b80610a935750836001600160a01b031661113e84610433565b6001600160a01b031614949350505050565b826001600160a01b0316611163826108f8565b6001600160a01b0316146111895760405162461bcd60e51b81526004016104ce90612177565b6001600160a01b0382166111eb5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016104ce565b826001600160a01b03166111fe826108f8565b6001600160a01b0316146112245760405162461bcd60e51b81526004016104ce90612177565b600081815260d46020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260d3855283862080546000190190559087168086528386208054600101905586865260d2909452828520805490921684179091559051849360008051602061243383398151915291a4505050565b610dc382826040518060200160405280600081525061168e565b606b54610100900460ff166112e35760405162461bcd60e51b81526004016104ce906121bc565b610dc382826116c1565b815160208084019190912082519183019190912060038290556004819055466001557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61133b818484611701565b600055600280546001600160a01b0319163017905560055550505050565b6000611364826108f8565b905061136f826108f8565b600083815260d46020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260d38452828520805460001901905587855260d290935281842080549091169055519293508492600080516020612433833981519152908390a45050565b816001600160a01b0316836001600160a01b0316036114395760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b60448201526064016104ce565b6001600160a01b03838116600081815260d56020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6114b1848484611150565b6114bd8484848461174a565b610eae5760405162461bcd60e51b81526004016104ce90612207565b606060006114e68361184f565b60010190506000816001600160401b0381111561150557611505611e2d565b6040519080825280601f01601f19166020018201604052801561152f576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461153957509392505050565b600090815260d260205260409020546001600160a01b0316151590565b60003033036115de57600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506115e19050565b50335b90565b60006040518060800160405280604381526020016123f06043913980516020918201208351848301516040808701518051908601209051611644950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061039b61166e611927565b8360405161190160f01b8152600281019290925260228201526042902090565b6116988383611962565b6116a5600084848461174a565b6105815760405162461bcd60e51b81526004016104ce90612207565b606b54610100900460ff166116e85760405162461bcd60e51b81526004016104ce906121bc565b60d06116f4838261229f565b5060d1610581828261229f565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b60006001600160a01b0384163b1561184757836001600160a01b031663150b7a02611773610f7e565b8786866040518563ffffffff1660e01b8152600401611795949392919061235e565b6020604051808303816000875af19250505080156117d0575060408051601f3d908101601f191682019092526117cd9181019061239b565b60015b61182d573d8080156117fe576040519150601f19603f3d011682016040523d82523d6000602084013e611803565b606091505b5080516000036118255760405162461bcd60e51b81526004016104ce90612207565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610a93565b506001610a93565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061188e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106118ba576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106118d857662386f26fc10000830492506010015b6305f5e10083106118f0576305f5e100830492506008015b612710831061190457612710830492506004015b60648310611916576064830492506002015b600a831061039b5760010192915050565b6002546000906001600160a01b031630148015611945575060015446145b15611951575060005490565b610f88600554600354600454611701565b6001600160a01b0382166119b85760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016104ce565b6119c18161156b565b156119de5760405162461bcd60e51b81526004016104ce906123b8565b6119e78161156b565b15611a045760405162461bcd60e51b81526004016104ce906123b8565b6001600160a01b038216600081815260d3602090815260408083208054600101905584835260d290915280822080546001600160a01b031916841790555183929190600080516020612433833981519152908290a45050565b6001600160e01b031981168114610f7b57600080fd5b600060208284031215611a8557600080fd5b8135610f2181611a5d565b60005b83811015611aab578181015183820152602001611a93565b50506000910152565b60008151808452611acc816020860160208601611a90565b601f01601f19169290920160200192915050565b602081526000610f216020830184611ab4565b600060208284031215611b0557600080fd5b5035919050565b80356001600160a01b0381168114611b2357600080fd5b919050565b60008060408385031215611b3b57600080fd5b611b4483611b0c565b946020939093013593505050565b60008083601f840112611b6457600080fd5b5081356001600160401b03811115611b7b57600080fd5b602083019150836020828501011115611b9357600080fd5b9250929050565b60008060008060008060a08789031215611bb357600080fd5b611bbc87611b0c565b955060208701356001600160401b03811115611bd757600080fd5b611be389828a01611b52565b9096509450506040870135925060608701359150608087013560ff81168114611c0b57600080fd5b809150509295509295509295565b600080600060608486031215611c2e57600080fd5b611c3784611b0c565b9250611c4560208501611b0c565b9150604084013590509250925092565b600060208284031215611c6757600080fd5b610f2182611b0c565b60008083601f840112611c8257600080fd5b5081356001600160401b03811115611c9957600080fd5b6020830191508360208260051b8501011115611b9357600080fd5b60008060008060408587031215611cca57600080fd5b84356001600160401b0380821115611ce157600080fd5b611ced88838901611c70565b90965094506020870135915080821115611d0657600080fd5b50611d1387828801611c70565b95989497509550505050565b600080600080600060608688031215611d3757600080fd5b611d4086611b0c565b945060208601356001600160401b0380821115611d5c57600080fd5b611d6889838a01611b52565b90965094506040880135915080821115611d8157600080fd5b50611d8e88828901611b52565b969995985093965092949392505050565b60008060408385031215611db257600080fd5b611dbb83611b0c565b915060208301358015158114611dd057600080fd5b809150509250929050565b600080600060408486031215611df057600080fd5b611df984611b0c565b925060208401356001600160401b03811115611e1457600080fd5b611e2086828701611c70565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611e5957600080fd5b611e6285611b0c565b9350611e7060208601611b0c565b92506040850135915060608501356001600160401b0380821115611e9357600080fd5b818701915087601f830112611ea757600080fd5b813581811115611eb957611eb9611e2d565b604051601f8201601f19908116603f01168101908382118183101715611ee157611ee1611e2d565b816040528281528a6020848701011115611efa57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060408385031215611f3157600080fd5b611f3a83611b0c565b9150611f4860208401611b0c565b90509250929050565b600181811c90821680611f6557607f821691505b602082108103611f8557634e487b7160e01b600052602260045260246000fd5b50919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251611fc3818460208701611a90565b9190910192915050565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b60208082526024908201527f4368696c644552433732313a204f6e6c79207072656469636174652063616e2060408201526318d85b1b60e21b606082015260800190565b602080825260189082015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b8082018082111561039b57634e487b7160e01b600052601160045260246000fd5b6020808252818101527f4368696c644552433732313a204f6e6c79206f776e65722063616e206275726e604082015260600190565b6000835161215a818460208801611a90565b83519083019061216e818360208801611a90565b01949350505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b601f82111561058157600081815260208120601f850160051c810160208610156122805750805b601f850160051c820191505b81811015610d035782815560010161228c565b81516001600160401b038111156122b8576122b8611e2d565b6122cc816122c68454611f51565b84612259565b602080601f83116001811461230157600084156122e95750858301515b600019600386901b1c1916600185901b178555610d03565b600085815260208120601f198616915b8281101561233057888601518255948401946001909101908401612311565b508582101561234e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061239190830184611ab4565b9695505050505050565b6000602082840312156123ad57600080fd5b8151610f2181611a5d565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060408201526060019056fe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220f91f642808324bd8531abbaf91281f9e3d4bf524dfff70328f58ead32897596764736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061014d5760003560e01c806370a08231116100c3578063a22cb4651161007c578063a22cb465146102de578063b2dc5dc3146102f1578063b88d4fde14610304578063c87b56dd14610317578063e61987051461032a578063e985e9c51461033c57600080fd5b806370a08231146102775780637c88e3d91461028a578063906571471461029d57806395d89b41146102b05780639b77ef11146102b85780639dc29fac146102cb57600080fd5b80631f2d0065116101155780631f2d0065146101e257806323b872dd146101f45780632d0335ab1461020757806340c10f191461023e57806342842e0e146102515780636352211e1461026457600080fd5b806301ffc9a71461015257806306fdde031461017a578063081812fc1461018f578063095ea7b3146101ba5780630c53c51c146101cf575b600080fd5b610165610160366004611a73565b61034f565b60405190151581526020015b60405180910390f35b6101826103a1565b6040516101719190611ae0565b6101a261019d366004611af3565b610433565b6040516001600160a01b039091168152602001610171565b6101cd6101c8366004611b28565b61045a565b005b6101826101dd366004611b9a565b610586565b610103546001600160a01b03166101a2565b6101cd610202366004611c19565b610864565b610230610215366004611c55565b6001600160a01b031660009081526038602052604090205490565b604051908152602001610171565b61016561024c366004611b28565b61089c565b6101cd61025f366004611c19565b6108dd565b6101a2610272366004611af3565b6108f8565b610230610285366004611c55565b61092d565b610165610298366004611cb4565b6109b3565b6101cd6102ab366004611d1f565b610a9b565b610182610d0b565b6101cd6102c6366004611af3565b610d1a565b6101656102d9366004611b28565b610d41565b6101cd6102ec366004611d9f565b610db1565b6101656102ff366004611ddb565b610dc7565b6101cd610312366004611e43565b610e75565b610182610325366004611af3565b610eb4565b610102546001600160a01b03166101a2565b61016561034a366004611f1e565b610f28565b60006001600160e01b031982166380ac58cd60e01b148061038057506001600160e01b03198216635b5e139f60e01b145b8061039b57506301ffc9a760e01b6001600160e01b03198316145b92915050565b606060d080546103b090611f51565b80601f01602080910402602001604051908101604052809291908181526020018280546103dc90611f51565b80156104295780601f106103fe57610100808354040283529160200191610429565b820191906000526020600020905b81548152906001019060200180831161040c57829003601f168201915b5050505050905090565b600061043e82610f56565b50600090815260d460205260409020546001600160a01b031690565b6000610465826108f8565b9050806001600160a01b0316836001600160a01b0316036104d75760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b806001600160a01b03166104e9610f7e565b6001600160a01b0316148061050557506105058161034a610f7e565b6105775760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c00000060648201526084016104ce565b6105818383610f8d565b505050565b606060006105c987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ffb92505050565b90506001600160e01b031960003581169082160361064f5760405162461bcd60e51b815260206004820152603d60248201527f66756e6374696f6e5369676e61747572652063616e206e6f74206265206f662060448201527f657865637574654d6574615472616e73616374696f6e206d6574686f6400000060648201526084016104ce565b604080516060810182526001600160a01b038a16600081815260386020908152848220548452808401929092528351601f8b0183900483028101830185528a815290938301918b908b9081908401838280828437600092019190915250505091525090506106c08982888888611016565b6107165760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b60648201526084016104ce565b603860008a6001600160a01b03166001600160a01b031681526020019081526020016000206000815460010191905081905550600080306001600160a01b03168a8a8d60405160200161076b93929190611f8b565b60408051601f198184030181529082905261078591611fb1565b6000604051808303816000865af19150503d80600081146107c2576040519150601f19603f3d011682016040523d82523d6000602084013e6107c7565b606091505b5091509150816108195760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c0000000060448201526064016104ce565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b8b338c8c60405161084e9493929190611fcd565b60405180910390a19a9950505050505050505050565b61087561086f610f7e565b826110f2565b6108915760405162461bcd60e51b81526004016104ce90612019565b610581838383611150565b610102546000906001600160a01b031633146108ca5760405162461bcd60e51b81526004016104ce90612066565b6108d483836112a2565b50600192915050565b61058183838360405180602001604052806000815250610e75565b600081815260d260205260408120546001600160a01b03168061039b5760405162461bcd60e51b81526004016104ce906120aa565b60006001600160a01b0382166109975760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016104ce565b506001600160a01b0316600090815260d3602052604090205490565b610102546000906001600160a01b031633146109e15760405162461bcd60e51b81526004016104ce90612066565b83828114610a315760405162461bcd60e51b815260206004820152601f60248201527f4368696c644552433732313a204172726179206c656e206d69736d617463680060448201526064016104ce565b60005b81811015610a8c57610a84878783818110610a5157610a516120dc565b9050602002016020810190610a669190611c55565b868684818110610a7857610a786120dc565b905060200201356112a2565b600101610a34565b5060019150505b949350505050565b606b54610100900460ff1615808015610abb5750606b54600160ff909116105b80610ad55750303b158015610ad55750606b5460ff166001145b610b385760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016104ce565b606b805460ff191660011790558015610b5b57606b805461ff0019166101001790555b6001600160a01b03861615801590610b7257508315155b8015610b7d57508115155b610bc95760405162461bcd60e51b815260206004820152601f60248201527f4368696c644552433732313a2042616420696e697469616c697a6174696f6e0060448201526064016104ce565b61010380546001600160a01b0388166001600160a01b031991821617909155610102805490911633179055604080516020601f8701819004810282018101909252858152610c6591879087908190840183828082843760009201919091525050604080516020601f890181900481028201810190925287815292508791508690819084018382808284376000920191909152506112bc92505050565b610cbd85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260018152603160f81b602082015291506112ed9050565b8015610d0357606b805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b606060d180546103b090611f51565b3360009081526038602052604081208054839290610d399084906120f2565b909155505050565b610102546000906001600160a01b03163314610d6f5760405162461bcd60e51b81526004016104ce90612066565b610d78826108f8565b6001600160a01b0316836001600160a01b031614610da85760405162461bcd60e51b81526004016104ce90612113565b6108d482611359565b610dc3610dbc610f7e565b83836113dc565b5050565b610102546000906001600160a01b03163314610df55760405162461bcd60e51b81526004016104ce90612066565b8160005b81811015610e69576000858583818110610e1557610e156120dc565b905060200201359050610e27816108f8565b6001600160a01b0316876001600160a01b031614610e575760405162461bcd60e51b81526004016104ce90612113565b610e6081611359565b50600101610df9565b50600195945050505050565b610e86610e80610f7e565b836110f2565b610ea25760405162461bcd60e51b81526004016104ce90612019565b610eae848484846114a6565b50505050565b6060610ebf82610f56565b6000610ed660408051602081019091526000815290565b90506000815111610ef65760405180602001604052806000815250610f21565b80610f00846114d9565b604051602001610f11929190612148565b6040516020818303038152906040525b9392505050565b6001600160a01b03918216600090815260d56020908152604080832093909416825291909152205460ff1690565b610f5f8161156b565b610f7b5760405162461bcd60e51b81526004016104ce906120aa565b50565b6000610f88611588565b905090565b600081815260d46020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610fc2826108f8565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000815160000361100e57506000919050565b506020015190565b600080600161102c611027886115e4565b611661565b6040805160008152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa15801561107a573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166110d15760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b60448201526064016104ce565b866001600160a01b0316816001600160a01b03161491505095945050505050565b6000806110fe836108f8565b9050806001600160a01b0316846001600160a01b0316148061112557506111258185610f28565b80610a935750836001600160a01b031661113e84610433565b6001600160a01b031614949350505050565b826001600160a01b0316611163826108f8565b6001600160a01b0316146111895760405162461bcd60e51b81526004016104ce90612177565b6001600160a01b0382166111eb5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016104ce565b826001600160a01b03166111fe826108f8565b6001600160a01b0316146112245760405162461bcd60e51b81526004016104ce90612177565b600081815260d46020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260d3855283862080546000190190559087168086528386208054600101905586865260d2909452828520805490921684179091559051849360008051602061243383398151915291a4505050565b610dc382826040518060200160405280600081525061168e565b606b54610100900460ff166112e35760405162461bcd60e51b81526004016104ce906121bc565b610dc382826116c1565b815160208084019190912082519183019190912060038290556004819055466001557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61133b818484611701565b600055600280546001600160a01b0319163017905560055550505050565b6000611364826108f8565b905061136f826108f8565b600083815260d46020908152604080832080546001600160a01b03199081169091556001600160a01b03851680855260d38452828520805460001901905587855260d290935281842080549091169055519293508492600080516020612433833981519152908390a45050565b816001600160a01b0316836001600160a01b0316036114395760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b60448201526064016104ce565b6001600160a01b03838116600081815260d56020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6114b1848484611150565b6114bd8484848461174a565b610eae5760405162461bcd60e51b81526004016104ce90612207565b606060006114e68361184f565b60010190506000816001600160401b0381111561150557611505611e2d565b6040519080825280601f01601f19166020018201604052801561152f576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461153957509392505050565b600090815260d260205260409020546001600160a01b0316151590565b60003033036115de57600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506115e19050565b50335b90565b60006040518060800160405280604381526020016123f06043913980516020918201208351848301516040808701518051908601209051611644950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061039b61166e611927565b8360405161190160f01b8152600281019290925260228201526042902090565b6116988383611962565b6116a5600084848461174a565b6105815760405162461bcd60e51b81526004016104ce90612207565b606b54610100900460ff166116e85760405162461bcd60e51b81526004016104ce906121bc565b60d06116f4838261229f565b5060d1610581828261229f565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b60006001600160a01b0384163b1561184757836001600160a01b031663150b7a02611773610f7e565b8786866040518563ffffffff1660e01b8152600401611795949392919061235e565b6020604051808303816000875af19250505080156117d0575060408051601f3d908101601f191682019092526117cd9181019061239b565b60015b61182d573d8080156117fe576040519150601f19603f3d011682016040523d82523d6000602084013e611803565b606091505b5080516000036118255760405162461bcd60e51b81526004016104ce90612207565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610a93565b506001610a93565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061188e5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106118ba576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106118d857662386f26fc10000830492506010015b6305f5e10083106118f0576305f5e100830492506008015b612710831061190457612710830492506004015b60648310611916576064830492506002015b600a831061039b5760010192915050565b6002546000906001600160a01b031630148015611945575060015446145b15611951575060005490565b610f88600554600354600454611701565b6001600160a01b0382166119b85760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016104ce565b6119c18161156b565b156119de5760405162461bcd60e51b81526004016104ce906123b8565b6119e78161156b565b15611a045760405162461bcd60e51b81526004016104ce906123b8565b6001600160a01b038216600081815260d3602090815260408083208054600101905584835260d290915280822080546001600160a01b031916841790555183929190600080516020612433833981519152908290a45050565b6001600160e01b031981168114610f7b57600080fd5b600060208284031215611a8557600080fd5b8135610f2181611a5d565b60005b83811015611aab578181015183820152602001611a93565b50506000910152565b60008151808452611acc816020860160208601611a90565b601f01601f19169290920160200192915050565b602081526000610f216020830184611ab4565b600060208284031215611b0557600080fd5b5035919050565b80356001600160a01b0381168114611b2357600080fd5b919050565b60008060408385031215611b3b57600080fd5b611b4483611b0c565b946020939093013593505050565b60008083601f840112611b6457600080fd5b5081356001600160401b03811115611b7b57600080fd5b602083019150836020828501011115611b9357600080fd5b9250929050565b60008060008060008060a08789031215611bb357600080fd5b611bbc87611b0c565b955060208701356001600160401b03811115611bd757600080fd5b611be389828a01611b52565b9096509450506040870135925060608701359150608087013560ff81168114611c0b57600080fd5b809150509295509295509295565b600080600060608486031215611c2e57600080fd5b611c3784611b0c565b9250611c4560208501611b0c565b9150604084013590509250925092565b600060208284031215611c6757600080fd5b610f2182611b0c565b60008083601f840112611c8257600080fd5b5081356001600160401b03811115611c9957600080fd5b6020830191508360208260051b8501011115611b9357600080fd5b60008060008060408587031215611cca57600080fd5b84356001600160401b0380821115611ce157600080fd5b611ced88838901611c70565b90965094506020870135915080821115611d0657600080fd5b50611d1387828801611c70565b95989497509550505050565b600080600080600060608688031215611d3757600080fd5b611d4086611b0c565b945060208601356001600160401b0380821115611d5c57600080fd5b611d6889838a01611b52565b90965094506040880135915080821115611d8157600080fd5b50611d8e88828901611b52565b969995985093965092949392505050565b60008060408385031215611db257600080fd5b611dbb83611b0c565b915060208301358015158114611dd057600080fd5b809150509250929050565b600080600060408486031215611df057600080fd5b611df984611b0c565b925060208401356001600160401b03811115611e1457600080fd5b611e2086828701611c70565b9497909650939450505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611e5957600080fd5b611e6285611b0c565b9350611e7060208601611b0c565b92506040850135915060608501356001600160401b0380821115611e9357600080fd5b818701915087601f830112611ea757600080fd5b813581811115611eb957611eb9611e2d565b604051601f8201601f19908116603f01168101908382118183101715611ee157611ee1611e2d565b816040528281528a6020848701011115611efa57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060408385031215611f3157600080fd5b611f3a83611b0c565b9150611f4860208401611b0c565b90509250929050565b600181811c90821680611f6557607f821691505b602082108103611f8557634e487b7160e01b600052602260045260246000fd5b50919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251611fc3818460208701611a90565b9190910192915050565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b60208082526024908201527f4368696c644552433732313a204f6e6c79207072656469636174652063616e2060408201526318d85b1b60e21b606082015260800190565b602080825260189082015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b8082018082111561039b57634e487b7160e01b600052601160045260246000fd5b6020808252818101527f4368696c644552433732313a204f6e6c79206f776e65722063616e206275726e604082015260600190565b6000835161215a818460208801611a90565b83519083019061216e818360208801611a90565b01949350505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b601f82111561058157600081815260208120601f850160051c810160208610156122805750805b601f850160051c820191505b81811015610d035782815560010161228c565b81516001600160401b038111156122b8576122b8611e2d565b6122cc816122c68454611f51565b84612259565b602080601f83116001811461230157600084156122e95750858301515b600019600386901b1c1916600185901b178555610d03565b600085815260208120601f198616915b8281101561233057888601518255948401946001909101908401612311565b508582101561234e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061239190830184611ab4565b9695505050505050565b6000602082840312156123ad57600080fd5b8151610f2181611a5d565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060408201526060019056fe4d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220f91f642808324bd8531abbaf91281f9e3d4bf524dfff70328f58ead32897596764736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC721PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC721Predicate\",\n \"sourceName\": \"contracts/child/ChildERC721Predicate.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC721Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2ERC721DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC721Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2ERC721WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC721Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC721Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"withdrawBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611fc4806100206000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c8063b1768065116100c3578063e0563ab11161007c578063e0563ab114610306578063eeb499451461030f578063f3fef3a314610322578063f645125514610335578063f691325c1461035c578063f8c8765e1461036f57600080fd5b8063b176806514610244578063b68ad1e41461026b578063c3b35a7e1461027e578063c5ac2b1c14610291578063d41f1771146102b8578063d7c9e3ec146102df57600080fd5b806355b01e4d1161011557806355b01e4d146101ce5780635ea5df79146101dc5780636f33e695146101f35780637efab4f514610208578063947287cf1461023157806397e5230d1461023a57600080fd5b806305dc2e8f1461015d57806307b3e2521461018d5780631bc114ba1461019b578063284017f5146101ae5780633b878c22146101b757806351351d53146101c0575b600080fd5b603454610170906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101706004600360981b0181565b603354610170906001600160a01b031681565b61017061202081565b61017061101081565b6101706002600160a01b0381565b6101706004600160991b0181565b6101e561138881565b604051908152602001610184565b61020661020136600461166f565b610382565b005b6101706102163660046116f1565b6037602052600090815260409020546001600160a01b031681565b6101e561520881565b6101e5620249f081565b6101e57f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b603654610170906001600160a01b031681565b61020661028c366004611715565b610396565b6101e57faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6101e57f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101e57f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61017061203081565b61020661031d366004611756565b6103a6565b6102066103303660046117de565b6105c9565b6101e57f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b603554610170906001600160a01b031681565b61020661037d36600461180a565b6105d8565b61038f8585858585610734565b5050505050565b6103a1838383610a98565b505050565b6034546001600160a01b031633146104175760405162461bcd60e51b815260206004820152602960248201527f4368696c644552433732315072656469636174653a204f4e4c595f53544154456044820152682fa922a1a2a4ab22a960b91b60648201526084015b60405180910390fd5b6035546001600160a01b038481169116146104865760405162461bcd60e51b815260206004820152602960248201527f4368696c644552433732315072656469636174653a204f4e4c595f524f4f545f60448201526850524544494341544560b81b606482015260840161040e565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216104b5602060008486611866565b6104be91611890565b036104dd576104d86104d38260208186611866565b610da1565b6105c3565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1861050c602060008486611866565b61051591611890565b03610524576104d88282611017565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad610553602060008486611866565b61055c91611890565b0361056b576104d8828261127d565b60405162461bcd60e51b815260206004820152602760248201527f4368696c644552433732315072656469636174653a20494e56414c49445f5349604482015266474e415455524560c81b606482015260840161040e565b50505050565b6105d4823383610a98565b5050565b336002600160a01b031461061c5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b604482015260640161040e565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106b95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161040e565b6000805460ff1916600117905580156106dc576000805461ff0019166101001790555b6106e8858585856113eb565b801561038f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b8461073e816114e0565b61075a5760405162461bcd60e51b815260040161040e906118ae565b6000866001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561079a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107be91906118f0565b6001600160a01b038181166000908152603760205260409020549192508881169116146107fd5760405162461bcd60e51b815260040161040e9061190d565b6001600160a01b03811661081357610813611951565b306001600160a01b0316876001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561085b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087f91906118f0565b6001600160a01b03161461089557610895611951565b8483146108f05760405162461bcd60e51b8152602060048201526024808201527f4368696c644552433732315072656469636174653a20494e56414c49445f4c4560448201526309c8ea8960e31b606482015260840161040e565b60405163b2dc5dc360e01b81526001600160a01b0388169063b2dc5dc39061092090339088908890600401611999565b6020604051808303816000875af115801561093f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096391906119c7565b61097f5760405162461bcd60e51b815260040161040e906119e9565b6033546035546040516001600160a01b03928316926316f198319216906109d6907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908d908d908d908d90602001611a73565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610a02929190611b0d565b600060405180830381600087803b158015610a1c57600080fd5b505af1158015610a30573d6000803e3d6000fd5b50505050336001600160a01b0316876001600160a01b0316826001600160a01b03167fa80bc76d6e1849a9088a9c00a2aeaa54eeb78f15565a18da3e8873438976f52289898989604051610a879493929190611b39565b60405180910390a450505050505050565b82610aa2816114e0565b610abe5760405162461bcd60e51b815260040161040e906118ae565b6000846001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2291906118f0565b6001600160a01b03818116600090815260376020526040902054919250868116911614610b615760405162461bcd60e51b815260040161040e9061190d565b6001600160a01b038116610b7757610b77611951565b306001600160a01b0316856001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be391906118f0565b6001600160a01b031614610bf957610bf9611951565b604051632770a7eb60e21b81526001600160a01b03861690639dc29fac90610c279033908790600401611b6b565b6020604051808303816000875af1158015610c46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6a91906119c7565b610c865760405162461bcd60e51b815260040161040e906119e9565b603354603554604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152888116608083015260a08083018990528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610d119391169160c401611b0d565b600060405180830381600087803b158015610d2b57600080fd5b505af1158015610d3f573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b0316826001600160a01b03167f1e0ef6131232b1090efc3ec1cf7b53aa17f4b7cd8a4f9e033b49ee237379b0133387604051610d92929190611b6b565b60405180910390a45050505050565b6000808080610db285870187611b84565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610df55760405162461bcd60e51b815260040161040e9061190d565b610dfe816114e0565b610e0a57610e0a611951565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6e91906118f0565b9050856001600160a01b0316816001600160a01b031614610e9157610e91611951565b6001600160a01b038116610ea757610ea7611951565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1391906118f0565b6001600160a01b031614610f2957610f29611951565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610f579087908790600401611b6b565b6020604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9a91906119c7565b610fb65760405162461bcd60e51b815260040161040e90611bd5565b836001600160a01b0316826001600160a01b0316876001600160a01b03167f37589fd8c906c19ea68eeb7e6b3e03efc06ff8aa4b1830588eba75f4375b16118887604051611005929190611b6b565b60405180910390a45050505050505050565b600080808061102885870187611cea565b6001600160a01b0380851660009081526037602052604090205494995092975090955093501690508061106d5760405162461bcd60e51b815260040161040e9061190d565b611076816114e0565b61108257611082611951565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e691906118f0565b9050856001600160a01b0316816001600160a01b03161461110957611109611951565b6001600160a01b03811661111f5761111f611951565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015611167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118b91906118f0565b6001600160a01b0316146111a1576111a1611951565b604051637c88e3d960e01b81526001600160a01b03831690637c88e3d9906111cf9087908790600401611ddc565b6020604051808303816000875af11580156111ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121291906119c7565b61122e5760405162461bcd60e51b815260040161040e90611bd5565b846001600160a01b0316826001600160a01b0316876001600160a01b03167fc1b1a5c1b97cc8e5ac82b47496f5ebdadf9c7d119b30a116e2bdafd56f6ed4758787604051611005929190611ddc565b6000808061128d84860186611ecf565b91955093509150506001600160a01b0383166112ab576112ab611951565b6001600160a01b0383811660009081526037602052604090205416156112d3576112d3611951565b6036546040516bffffffffffffffffffffffff19606086901b166020820152600091611323916001600160a01b039091169060340160405160208183030381529060405280519060200120611575565b6001600160a01b038581166000908152603760205260409081902080546001600160a01b031916928416928317905551639065714760e01b81529192509063906571479061137990879087908790600401611f4e565b600060405180830381600087803b15801561139357600080fd5b505af11580156113a7573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a3505050505050565b6001600160a01b0384161580159061140b57506001600160a01b03831615155b801561141f57506001600160a01b03821615155b801561143357506001600160a01b03811615155b6114905760405162461bcd60e51b815260206004820152602860248201527f4368696c644552433732315072656469636174653a204241445f494e495449416044820152672624ad20aa24a7a760c11b606482015260840161040e565b603380546001600160a01b039586166001600160a01b0319918216179091556034805494861694821694909417909355603580549285169284169290921790915560368054919093169116179055565b6000816001600160a01b03163b6000036114fc57506000919050565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611563575060408051601f3d908101601f19168201909252611560918101906119c7565b60015b61156f57506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b03811661156f5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b604482015260640161040e565b6001600160a01b038116811461162157600080fd5b50565b60008083601f84011261163657600080fd5b5081356001600160401b0381111561164d57600080fd5b6020830191508360208260051b850101111561166857600080fd5b9250929050565b60008060008060006060868803121561168757600080fd5b85356116928161160c565b945060208601356001600160401b03808211156116ae57600080fd5b6116ba89838a01611624565b909650945060408801359150808211156116d357600080fd5b506116e088828901611624565b969995985093965092949392505050565b60006020828403121561170357600080fd5b813561170e8161160c565b9392505050565b60008060006060848603121561172a57600080fd5b83356117358161160c565b925060208401356117458161160c565b929592945050506040919091013590565b6000806000806060858703121561176c57600080fd5b84359350602085013561177e8161160c565b925060408501356001600160401b038082111561179a57600080fd5b818701915087601f8301126117ae57600080fd5b8135818111156117bd57600080fd5b8860208285010111156117cf57600080fd5b95989497505060200194505050565b600080604083850312156117f157600080fd5b82356117fc8161160c565b946020939093013593505050565b6000806000806080858703121561182057600080fd5b843561182b8161160c565b9350602085013561183b8161160c565b9250604085013561184b8161160c565b9150606085013561185b8161160c565b939692955090935050565b6000808585111561187657600080fd5b8386111561188357600080fd5b5050820193919092039150565b8035602083101561156f57600019602084900360031b1b1692915050565b60208082526022908201527f4368696c644552433732315072656469636174653a204e4f545f434f4e54524160408201526110d560f21b606082015260800190565b60006020828403121561190257600080fd5b815161170e8161160c565b60208082526024908201527f4368696c644552433732315072656469636174653a20554e4d41505045445f5460408201526327a5a2a760e11b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b0383111561198057600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b03841681526040602082018190526000906119be9083018486611967565b95945050505050565b6000602082840312156119d957600080fd5b8151801515811461170e57600080fd5b60208082526021908201527f4368696c644552433732315072656469636174653a204255524e5f4641494c456040820152601160fa1b606082015260800190565b8183526000602080850194508260005b85811015611a68578135611a4d8161160c565b6001600160a01b031687529582019590820190600101611a3a565b509495945050505050565b8781526001600160a01b0387811660208301528616604082015260a060608201819052600090611aa69083018688611a2a565b8281036080840152611ab9818587611967565b9a9950505050505050505050565b6000815180845260005b81811015611aed57602081850181015186830182015201611ad1565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611b3190830184611ac7565b949350505050565b604081526000611b4d604083018688611a2a565b8281036020840152611b60818587611967565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b60008060008060808587031215611b9a57600080fd5b8435611ba58161160c565b93506020850135611bb58161160c565b92506040850135611bc58161160c565b9396929550929360600135925050565b60208082526021908201527f4368696c644552433732315072656469636174653a204d494e545f4641494c456040820152601160fa1b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611c5457611c54611c16565b604052919050565b60006001600160401b03821115611c7557611c75611c16565b5060051b60200190565b600082601f830112611c9057600080fd5b81356020611ca5611ca083611c5c565b611c2c565b82815260059290921b84018101918181019086841115611cc457600080fd5b8286015b84811015611cdf5780358352918301918301611cc8565b509695505050505050565b600080600080600060a08688031215611d0257600080fd5b85359450602080870135611d158161160c565b94506040870135611d258161160c565b935060608701356001600160401b0380821115611d4157600080fd5b818901915089601f830112611d5557600080fd5b8135611d63611ca082611c5c565b81815260059190911b8301840190848101908c831115611d8257600080fd5b938501935b82851015611da9578435611d9a8161160c565b82529385019390850190611d87565b965050506080890135925080831115611dc157600080fd5b5050611dcf88828901611c7f565b9150509295509295909350565b604080825283519082018190526000906020906060840190828701845b82811015611e1e5781516001600160a01b031684529284019290840190600101611df9565b5050508381038285015284518082528583019183019060005b81811015611e5357835183529284019291840191600101611e37565b5090979650505050505050565b600082601f830112611e7157600080fd5b81356001600160401b03811115611e8a57611e8a611c16565b611e9d601f8201601f1916602001611c2c565b818152846020838601011115611eb257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611ee557600080fd5b843593506020850135611ef78161160c565b925060408501356001600160401b0380821115611f1357600080fd5b611f1f88838901611e60565b93506060870135915080821115611f3557600080fd5b50611f4287828801611e60565b91505092959194509250565b6001600160a01b0384168152606060208201819052600090611f7290830185611ac7565b8281036040840152611f848185611ac7565b969550505050505056fea264697066735822122033c05283a28fb22a3fea46c8e88f9a833d7c53490442d56ec5e0108de332c5a964736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101585760003560e01c8063b1768065116100c3578063e0563ab11161007c578063e0563ab114610306578063eeb499451461030f578063f3fef3a314610322578063f645125514610335578063f691325c1461035c578063f8c8765e1461036f57600080fd5b8063b176806514610244578063b68ad1e41461026b578063c3b35a7e1461027e578063c5ac2b1c14610291578063d41f1771146102b8578063d7c9e3ec146102df57600080fd5b806355b01e4d1161011557806355b01e4d146101ce5780635ea5df79146101dc5780636f33e695146101f35780637efab4f514610208578063947287cf1461023157806397e5230d1461023a57600080fd5b806305dc2e8f1461015d57806307b3e2521461018d5780631bc114ba1461019b578063284017f5146101ae5780633b878c22146101b757806351351d53146101c0575b600080fd5b603454610170906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101706004600360981b0181565b603354610170906001600160a01b031681565b61017061202081565b61017061101081565b6101706002600160a01b0381565b6101706004600160991b0181565b6101e561138881565b604051908152602001610184565b61020661020136600461166f565b610382565b005b6101706102163660046116f1565b6037602052600090815260409020546001600160a01b031681565b6101e561520881565b6101e5620249f081565b6101e57f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b603654610170906001600160a01b031681565b61020661028c366004611715565b610396565b6101e57faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6101e57f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101e57f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61017061203081565b61020661031d366004611756565b6103a6565b6102066103303660046117de565b6105c9565b6101e57f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b603554610170906001600160a01b031681565b61020661037d36600461180a565b6105d8565b61038f8585858585610734565b5050505050565b6103a1838383610a98565b505050565b6034546001600160a01b031633146104175760405162461bcd60e51b815260206004820152602960248201527f4368696c644552433732315072656469636174653a204f4e4c595f53544154456044820152682fa922a1a2a4ab22a960b91b60648201526084015b60405180910390fd5b6035546001600160a01b038481169116146104865760405162461bcd60e51b815260206004820152602960248201527f4368696c644552433732315072656469636174653a204f4e4c595f524f4f545f60448201526850524544494341544560b81b606482015260840161040e565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216104b5602060008486611866565b6104be91611890565b036104dd576104d86104d38260208186611866565b610da1565b6105c3565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1861050c602060008486611866565b61051591611890565b03610524576104d88282611017565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad610553602060008486611866565b61055c91611890565b0361056b576104d8828261127d565b60405162461bcd60e51b815260206004820152602760248201527f4368696c644552433732315072656469636174653a20494e56414c49445f5349604482015266474e415455524560c81b606482015260840161040e565b50505050565b6105d4823383610a98565b5050565b336002600160a01b031461061c5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b604482015260640161040e565b600054610100900460ff161580801561063c5750600054600160ff909116105b806106565750303b158015610656575060005460ff166001145b6106b95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161040e565b6000805460ff1916600117905580156106dc576000805461ff0019166101001790555b6106e8858585856113eb565b801561038f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b8461073e816114e0565b61075a5760405162461bcd60e51b815260040161040e906118ae565b6000866001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561079a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107be91906118f0565b6001600160a01b038181166000908152603760205260409020549192508881169116146107fd5760405162461bcd60e51b815260040161040e9061190d565b6001600160a01b03811661081357610813611951565b306001600160a01b0316876001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561085b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087f91906118f0565b6001600160a01b03161461089557610895611951565b8483146108f05760405162461bcd60e51b8152602060048201526024808201527f4368696c644552433732315072656469636174653a20494e56414c49445f4c4560448201526309c8ea8960e31b606482015260840161040e565b60405163b2dc5dc360e01b81526001600160a01b0388169063b2dc5dc39061092090339088908890600401611999565b6020604051808303816000875af115801561093f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096391906119c7565b61097f5760405162461bcd60e51b815260040161040e906119e9565b6033546035546040516001600160a01b03928316926316f198319216906109d6907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908d908d908d908d90602001611a73565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610a02929190611b0d565b600060405180830381600087803b158015610a1c57600080fd5b505af1158015610a30573d6000803e3d6000fd5b50505050336001600160a01b0316876001600160a01b0316826001600160a01b03167fa80bc76d6e1849a9088a9c00a2aeaa54eeb78f15565a18da3e8873438976f52289898989604051610a879493929190611b39565b60405180910390a450505050505050565b82610aa2816114e0565b610abe5760405162461bcd60e51b815260040161040e906118ae565b6000846001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2291906118f0565b6001600160a01b03818116600090815260376020526040902054919250868116911614610b615760405162461bcd60e51b815260040161040e9061190d565b6001600160a01b038116610b7757610b77611951565b306001600160a01b0316856001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be391906118f0565b6001600160a01b031614610bf957610bf9611951565b604051632770a7eb60e21b81526001600160a01b03861690639dc29fac90610c279033908790600401611b6b565b6020604051808303816000875af1158015610c46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6a91906119c7565b610c865760405162461bcd60e51b815260040161040e906119e9565b603354603554604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152888116608083015260a08083018990528351808403909101815260c08301938490526316f1983160e01b909352938416936316f1983193610d119391169160c401611b0d565b600060405180830381600087803b158015610d2b57600080fd5b505af1158015610d3f573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b0316826001600160a01b03167f1e0ef6131232b1090efc3ec1cf7b53aa17f4b7cd8a4f9e033b49ee237379b0133387604051610d92929190611b6b565b60405180910390a45050505050565b6000808080610db285870187611b84565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610df55760405162461bcd60e51b815260040161040e9061190d565b610dfe816114e0565b610e0a57610e0a611951565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6e91906118f0565b9050856001600160a01b0316816001600160a01b031614610e9157610e91611951565b6001600160a01b038116610ea757610ea7611951565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f1391906118f0565b6001600160a01b031614610f2957610f29611951565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610f579087908790600401611b6b565b6020604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9a91906119c7565b610fb65760405162461bcd60e51b815260040161040e90611bd5565b836001600160a01b0316826001600160a01b0316876001600160a01b03167f37589fd8c906c19ea68eeb7e6b3e03efc06ff8aa4b1830588eba75f4375b16118887604051611005929190611b6b565b60405180910390a45050505050505050565b600080808061102885870187611cea565b6001600160a01b0380851660009081526037602052604090205494995092975090955093501690508061106d5760405162461bcd60e51b815260040161040e9061190d565b611076816114e0565b61108257611082611951565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110e691906118f0565b9050856001600160a01b0316816001600160a01b03161461110957611109611951565b6001600160a01b03811661111f5761111f611951565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015611167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118b91906118f0565b6001600160a01b0316146111a1576111a1611951565b604051637c88e3d960e01b81526001600160a01b03831690637c88e3d9906111cf9087908790600401611ddc565b6020604051808303816000875af11580156111ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121291906119c7565b61122e5760405162461bcd60e51b815260040161040e90611bd5565b846001600160a01b0316826001600160a01b0316876001600160a01b03167fc1b1a5c1b97cc8e5ac82b47496f5ebdadf9c7d119b30a116e2bdafd56f6ed4758787604051611005929190611ddc565b6000808061128d84860186611ecf565b91955093509150506001600160a01b0383166112ab576112ab611951565b6001600160a01b0383811660009081526037602052604090205416156112d3576112d3611951565b6036546040516bffffffffffffffffffffffff19606086901b166020820152600091611323916001600160a01b039091169060340160405160208183030381529060405280519060200120611575565b6001600160a01b038581166000908152603760205260409081902080546001600160a01b031916928416928317905551639065714760e01b81529192509063906571479061137990879087908790600401611f4e565b600060405180830381600087803b15801561139357600080fd5b505af11580156113a7573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a3505050505050565b6001600160a01b0384161580159061140b57506001600160a01b03831615155b801561141f57506001600160a01b03821615155b801561143357506001600160a01b03811615155b6114905760405162461bcd60e51b815260206004820152602860248201527f4368696c644552433732315072656469636174653a204241445f494e495449416044820152672624ad20aa24a7a760c11b606482015260840161040e565b603380546001600160a01b039586166001600160a01b0319918216179091556034805494861694821694909417909355603580549285169284169290921790915560368054919093169116179055565b6000816001600160a01b03163b6000036114fc57506000919050565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611563575060408051601f3d908101601f19168201909252611560918101906119c7565b60015b61156f57506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b03811661156f5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b604482015260640161040e565b6001600160a01b038116811461162157600080fd5b50565b60008083601f84011261163657600080fd5b5081356001600160401b0381111561164d57600080fd5b6020830191508360208260051b850101111561166857600080fd5b9250929050565b60008060008060006060868803121561168757600080fd5b85356116928161160c565b945060208601356001600160401b03808211156116ae57600080fd5b6116ba89838a01611624565b909650945060408801359150808211156116d357600080fd5b506116e088828901611624565b969995985093965092949392505050565b60006020828403121561170357600080fd5b813561170e8161160c565b9392505050565b60008060006060848603121561172a57600080fd5b83356117358161160c565b925060208401356117458161160c565b929592945050506040919091013590565b6000806000806060858703121561176c57600080fd5b84359350602085013561177e8161160c565b925060408501356001600160401b038082111561179a57600080fd5b818701915087601f8301126117ae57600080fd5b8135818111156117bd57600080fd5b8860208285010111156117cf57600080fd5b95989497505060200194505050565b600080604083850312156117f157600080fd5b82356117fc8161160c565b946020939093013593505050565b6000806000806080858703121561182057600080fd5b843561182b8161160c565b9350602085013561183b8161160c565b9250604085013561184b8161160c565b9150606085013561185b8161160c565b939692955090935050565b6000808585111561187657600080fd5b8386111561188357600080fd5b5050820193919092039150565b8035602083101561156f57600019602084900360031b1b1692915050565b60208082526022908201527f4368696c644552433732315072656469636174653a204e4f545f434f4e54524160408201526110d560f21b606082015260800190565b60006020828403121561190257600080fd5b815161170e8161160c565b60208082526024908201527f4368696c644552433732315072656469636174653a20554e4d41505045445f5460408201526327a5a2a760e11b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b0383111561198057600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b03841681526040602082018190526000906119be9083018486611967565b95945050505050565b6000602082840312156119d957600080fd5b8151801515811461170e57600080fd5b60208082526021908201527f4368696c644552433732315072656469636174653a204255524e5f4641494c456040820152601160fa1b606082015260800190565b8183526000602080850194508260005b85811015611a68578135611a4d8161160c565b6001600160a01b031687529582019590820190600101611a3a565b509495945050505050565b8781526001600160a01b0387811660208301528616604082015260a060608201819052600090611aa69083018688611a2a565b8281036080840152611ab9818587611967565b9a9950505050505050505050565b6000815180845260005b81811015611aed57602081850181015186830182015201611ad1565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611b3190830184611ac7565b949350505050565b604081526000611b4d604083018688611a2a565b8281036020840152611b60818587611967565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b60008060008060808587031215611b9a57600080fd5b8435611ba58161160c565b93506020850135611bb58161160c565b92506040850135611bc58161160c565b9396929550929360600135925050565b60208082526021908201527f4368696c644552433732315072656469636174653a204d494e545f4641494c456040820152601160fa1b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611c5457611c54611c16565b604052919050565b60006001600160401b03821115611c7557611c75611c16565b5060051b60200190565b600082601f830112611c9057600080fd5b81356020611ca5611ca083611c5c565b611c2c565b82815260059290921b84018101918181019086841115611cc457600080fd5b8286015b84811015611cdf5780358352918301918301611cc8565b509695505050505050565b600080600080600060a08688031215611d0257600080fd5b85359450602080870135611d158161160c565b94506040870135611d258161160c565b935060608701356001600160401b0380821115611d4157600080fd5b818901915089601f830112611d5557600080fd5b8135611d63611ca082611c5c565b81815260059190911b8301840190848101908c831115611d8257600080fd5b938501935b82851015611da9578435611d9a8161160c565b82529385019390850190611d87565b965050506080890135925080831115611dc157600080fd5b5050611dcf88828901611c7f565b9150509295509295909350565b604080825283519082018190526000906020906060840190828701845b82811015611e1e5781516001600160a01b031684529284019290840190600101611df9565b5050508381038285015284518082528583019183019060005b81811015611e5357835183529284019291840191600101611e37565b5090979650505050505050565b600082601f830112611e7157600080fd5b81356001600160401b03811115611e8a57611e8a611c16565b611e9d601f8201601f1916602001611c2c565b818152846020838601011115611eb257600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611ee557600080fd5b843593506020850135611ef78161160c565b925060408501356001600160401b0380821115611f1357600080fd5b611f1f88838901611e60565b93506060870135915080821115611f3557600080fd5b50611f4287828801611e60565b91505092959194509250565b6001600160a01b0384168152606060208201819052600090611f7290830185611ac7565b8281036040840152611f848185611ac7565b969550505050505056fea264697066735822122033c05283a28fb22a3fea46c8e88f9a833d7c53490442d56ec5e0108de332c5a964736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC721PredicateACLArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC721PredicateAccessList\",\n \"sourceName\": \"contracts/child/ChildERC721PredicateAccessList.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"AllowListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"BlockListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC721Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2ERC721DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC721Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2ERC721WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC721Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC721Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC721Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setAllowList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setBlockList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"withdrawBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612758806100206000396000f3fe608060405234801561001057600080fd5b50600436106101b05760003560e01c8063b68ad1e4116100ef578063e0563ab111610092578063e0563ab1146103b9578063e30c3978146103c2578063eeb49945146103d3578063f2fde38b146103e6578063f3fef3a3146103f9578063f64512551461040c578063f691325c14610433578063f8c8765e1461044657600080fd5b8063b68ad1e4146102e5578063c1225a20146102f8578063c3b35a7e1461030b578063c5ac2b1c1461031e578063c5e4683a14610345578063d41f177114610358578063d7c9e3ec1461037f578063d8dd1773146103a657600080fd5b80636f33e695116101575780636f33e6951461024b578063715018a61461026057806379ba5097146102685780637efab4f5146102705780638da5cb5b1461029a578063947287cf146102ab57806397e5230d146102b4578063b1768065146102be57600080fd5b806305dc2e8f146101b557806307b3e252146101e55780631bc114ba146101f3578063284017f5146102065780633b878c221461020f57806351351d531461021857806355b01e4d146102265780635ea5df7914610234575b600080fd5b60fd546101c8906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101c86004600360981b0181565b60fc546101c8906001600160a01b031681565b6101c861202081565b6101c861101081565b6101c86002600160a01b0381565b6101c86004600160991b0181565b61023d61138881565b6040519081526020016101dc565b61025e610259366004611c96565b610459565b005b61025e610475565b61025e610489565b6101c861027e366004611d18565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b03166101c8565b61023d61520881565b61023d620249f081565b61023d7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff546101c8906001600160a01b031681565b61025e610306366004611d4a565b610508565b61025e610319366004611d67565b610557565b61023d7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b61025e610353366004611d4a565b61056f565b61023d7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61023d7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61025e6103b4366004611da8565b6105b6565b6101c861203081565b6065546001600160a01b03166101c8565b61025e6103e1366004611e3e565b6106d7565b61025e6103f4366004611d18565b6108f5565b61025e610407366004611ec6565b610966565b61023d7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b60fe546101c8906001600160a01b031681565b61025e610454366004611ef2565b61097d565b610461610a75565b61046e8585858585610a7d565b5050505050565b61047d610de2565b6104876000610e3c565b565b60655433906001600160a01b031681146104fc5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61050581610e3c565b50565b610510610de2565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b61055f610a75565b61056a838383610e55565b505050565b610577610de2565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b03146105dd5760405163973d02cb60e01b81526004016104f390611f4e565b600054610100900460ff16158080156105fd5750600054600160ff909116105b806106175750303b158015610617575060005460ff166001145b6106335760405162461bcd60e51b81526004016104f390611f72565b6000805460ff191660011790558015610656576000805461ff0019166101001790555b6106628888888861115f565b60c9805461ffff191685151561ff001916176101008515150217905561068782610e3c565b80156106cd576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146107435760405162461bcd60e51b815260206004820152602960248201527f4368696c644552433732315072656469636174653a204f4e4c595f53544154456044820152682fa922a1a2a4ab22a960b91b60648201526084016104f3565b60fe546001600160a01b038481169116146107b25760405162461bcd60e51b815260206004820152602960248201527f4368696c644552433732315072656469636174653a204f4e4c595f524f4f545f60448201526850524544494341544560b81b60648201526084016104f3565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216107e1602060008486611fc0565b6107ea91611fea565b03610809576108046107ff8260208186611fc0565b611254565b6108ef565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18610838602060008486611fc0565b61084191611fea565b036108505761080482826114cb565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad61087f602060008486611fc0565b61088891611fea565b03610897576108048282611732565b60405162461bcd60e51b815260206004820152602760248201527f4368696c644552433732315072656469636174653a20494e56414c49445f5349604482015266474e415455524560c81b60648201526084016104f3565b50505050565b6108fd610de2565b606580546001600160a01b0383166001600160a01b0319909116811790915561092e6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61096e610a75565b610979823383610e55565b5050565b336002600160a01b03146109a45760405163973d02cb60e01b81526004016104f390611f4e565b600054610100900460ff16158080156109c45750600054600160ff909116105b806109de5750303b1580156109de575060005460ff166001145b6109fa5760405162461bcd60e51b81526004016104f390611f72565b6000805460ff191660011790558015610a1d576000805461ff0019166101001790555b610a298585858561115f565b801561046e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6104876118a2565b84610a8781611ab8565b610aa35760405162461bcd60e51b81526004016104f390612008565b6000866001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b07919061204a565b6001600160a01b0381811660009081526101006020526040902054919250888116911614610b475760405162461bcd60e51b81526004016104f390612067565b6001600160a01b038116610b5d57610b5d6120ab565b306001600160a01b0316876001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ba5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc9919061204a565b6001600160a01b031614610bdf57610bdf6120ab565b848314610c3a5760405162461bcd60e51b8152602060048201526024808201527f4368696c644552433732315072656469636174653a20494e56414c49445f4c4560448201526309c8ea8960e31b60648201526084016104f3565b60405163b2dc5dc360e01b81526001600160a01b0388169063b2dc5dc390610c6a903390889088906004016120f3565b6020604051808303816000875af1158015610c89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cad9190612121565b610cc95760405162461bcd60e51b81526004016104f39061213e565b60fc5460fe546040516001600160a01b03928316926316f19831921690610d20907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908d908d908d908d906020016121c8565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610d4c92919061226c565b600060405180830381600087803b158015610d6657600080fd5b505af1158015610d7a573d6000803e3d6000fd5b50505050336001600160a01b0316876001600160a01b0316826001600160a01b03167fa80bc76d6e1849a9088a9c00a2aeaa54eeb78f15565a18da3e8873438976f52289898989604051610dd19493929190612298565b60405180910390a450505050505050565b6033546001600160a01b031633146104875760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b606580546001600160a01b031916905561050581611b4d565b82610e5f81611ab8565b610e7b5760405162461bcd60e51b81526004016104f390612008565b6000846001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edf919061204a565b6001600160a01b0381811660009081526101006020526040902054919250868116911614610f1f5760405162461bcd60e51b81526004016104f390612067565b6001600160a01b038116610f3557610f356120ab565b306001600160a01b0316856001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa1919061204a565b6001600160a01b031614610fb757610fb76120ab565b604051632770a7eb60e21b81526001600160a01b03861690639dc29fac90610fe590339087906004016122ca565b6020604051808303816000875af1158015611004573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110289190612121565b6110445760405162461bcd60e51b81526004016104f39061213e565b60fc5460fe54604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152888116608083015260a08083018990528351808403909101815260c08301938490526316f1983160e01b909352938416936316f19831936110cf9391169160c40161226c565b600060405180830381600087803b1580156110e957600080fd5b505af11580156110fd573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b0316826001600160a01b03167f1e0ef6131232b1090efc3ec1cf7b53aa17f4b7cd8a4f9e033b49ee237379b01333876040516111509291906122ca565b60405180910390a45050505050565b6001600160a01b0384161580159061117f57506001600160a01b03831615155b801561119357506001600160a01b03821615155b80156111a757506001600160a01b03811615155b6112045760405162461bcd60e51b815260206004820152602860248201527f4368696c644552433732315072656469636174653a204241445f494e495449416044820152672624ad20aa24a7a760c11b60648201526084016104f3565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b6000808080611265858701876122e3565b6001600160a01b0380851660009081526101006020526040902054949850929650909450925016806112a95760405162461bcd60e51b81526004016104f390612067565b6112b281611ab8565b6112be576112be6120ab565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611322919061204a565b9050856001600160a01b0316816001600160a01b031614611345576113456120ab565b6001600160a01b03811661135b5761135b6120ab565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c7919061204a565b6001600160a01b0316146113dd576113dd6120ab565b6040516340c10f1960e01b81526001600160a01b038316906340c10f199061140b90879087906004016122ca565b6020604051808303816000875af115801561142a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144e9190612121565b61146a5760405162461bcd60e51b81526004016104f390612334565b836001600160a01b0316826001600160a01b0316876001600160a01b03167f37589fd8c906c19ea68eeb7e6b3e03efc06ff8aa4b1830588eba75f4375b161188876040516114b99291906122ca565b60405180910390a45050505050505050565b60008080806114dc85870187612449565b6001600160a01b03808516600090815261010060205260409020549499509297509095509350169050806115225760405162461bcd60e51b81526004016104f390612067565b61152b81611ab8565b611537576115376120ab565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015611577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159b919061204a565b9050856001600160a01b0316816001600160a01b0316146115be576115be6120ab565b6001600160a01b0381166115d4576115d46120ab565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561161c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611640919061204a565b6001600160a01b031614611656576116566120ab565b604051637c88e3d960e01b81526001600160a01b03831690637c88e3d990611684908790879060040161253b565b6020604051808303816000875af11580156116a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116c79190612121565b6116e35760405162461bcd60e51b81526004016104f390612334565b846001600160a01b0316826001600160a01b0316876001600160a01b03167fc1b1a5c1b97cc8e5ac82b47496f5ebdadf9c7d119b30a116e2bdafd56f6ed47587876040516114b992919061253b565b600080806117428486018661262e565b91955093509150506001600160a01b038316611760576117606120ab565b6001600160a01b03838116600090815261010060205260409020541615611789576117896120ab565b60ff546040516bffffffffffffffffffffffff19606086901b1660208201526000916117d9916001600160a01b039091169060340160405160208183030381529060405280519060200120611b9f565b6001600160a01b03858116600090815261010060205260409081902080546001600160a01b031916928416928317905551639065714760e01b815291925090639065714790611830908790879087906004016126ad565b600060405180830381600087803b15801561184a57600080fd5b505af115801561185e573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a3505050505050565b60c95460ff16156119ad57604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161190491906126ed565b6000604051808303818686fa925050503d8060008114611940576040519150601f19603f3d011682016040523d82523d6000602084013e611945565b606091505b509150915081801561196a57506000818060200190518101906119689190612709565b115b6119aa5760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b60448201526064016104f3565b50505b60c954610100900460ff161561048757604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b019161138891611a1491906126ed565b6000604051808303818686fa925050503d8060008114611a50576040519150601f19603f3d011682016040523d82523d6000602084013e611a55565b606091505b5091509150818015611a7b575080806020019051810190611a769190612709565b600114155b6109795760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b60448201526064016104f3565b6000816001600160a01b03163b600003611ad457506000919050565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611b3b575060408051601f3d908101601f19168201909252611b3891810190612121565b60015b611b4757506000919050565b92915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116611b475760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016104f3565b6001600160a01b038116811461050557600080fd5b60008083601f840112611c5d57600080fd5b5081356001600160401b03811115611c7457600080fd5b6020830191508360208260051b8501011115611c8f57600080fd5b9250929050565b600080600080600060608688031215611cae57600080fd5b8535611cb981611c36565b945060208601356001600160401b0380821115611cd557600080fd5b611ce189838a01611c4b565b90965094506040880135915080821115611cfa57600080fd5b50611d0788828901611c4b565b969995985093965092949392505050565b600060208284031215611d2a57600080fd5b8135611d3581611c36565b9392505050565b801515811461050557600080fd5b600060208284031215611d5c57600080fd5b8135611d3581611d3c565b600080600060608486031215611d7c57600080fd5b8335611d8781611c36565b92506020840135611d9781611c36565b929592945050506040919091013590565b600080600080600080600060e0888a031215611dc357600080fd5b8735611dce81611c36565b96506020880135611dde81611c36565b95506040880135611dee81611c36565b94506060880135611dfe81611c36565b93506080880135611e0e81611d3c565b925060a0880135611e1e81611d3c565b915060c0880135611e2e81611c36565b8091505092959891949750929550565b60008060008060608587031215611e5457600080fd5b843593506020850135611e6681611c36565b925060408501356001600160401b0380821115611e8257600080fd5b818701915087601f830112611e9657600080fd5b813581811115611ea557600080fd5b886020828501011115611eb757600080fd5b95989497505060200194505050565b60008060408385031215611ed957600080fd5b8235611ee481611c36565b946020939093013593505050565b60008060008060808587031215611f0857600080fd5b8435611f1381611c36565b93506020850135611f2381611c36565b92506040850135611f3381611c36565b91506060850135611f4381611c36565b939692955090935050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008085851115611fd057600080fd5b83861115611fdd57600080fd5b5050820193919092039150565b80356020831015611b4757600019602084900360031b1b1692915050565b60208082526022908201527f4368696c644552433732315072656469636174653a204e4f545f434f4e54524160408201526110d560f21b606082015260800190565b60006020828403121561205c57600080fd5b8151611d3581611c36565b60208082526024908201527f4368696c644552433732315072656469636174653a20554e4d41505045445f5460408201526327a5a2a760e11b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b038311156120da57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038416815260406020820181905260009061211890830184866120c1565b95945050505050565b60006020828403121561213357600080fd5b8151611d3581611d3c565b60208082526021908201527f4368696c644552433732315072656469636174653a204255524e5f4641494c456040820152601160fa1b606082015260800190565b8183526000602080850194508260005b858110156121bd5781356121a281611c36565b6001600160a01b03168752958201959082019060010161218f565b509495945050505050565b8781526001600160a01b0387811660208301528616604082015260a0606082018190526000906121fb908301868861217f565b828103608084015261220e8185876120c1565b9a9950505050505050505050565b60005b8381101561223757818101518382015260200161221f565b50506000910152565b6000815180845261225881602086016020860161221c565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061229090830184612240565b949350505050565b6040815260006122ac60408301868861217f565b82810360208401526122bf8185876120c1565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b600080600080608085870312156122f957600080fd5b843561230481611c36565b9350602085013561231481611c36565b9250604085013561232481611c36565b9396929550929360600135925050565b60208082526021908201527f4368696c644552433732315072656469636174653a204d494e545f4641494c456040820152601160fa1b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156123b3576123b3612375565b604052919050565b60006001600160401b038211156123d4576123d4612375565b5060051b60200190565b600082601f8301126123ef57600080fd5b813560206124046123ff836123bb565b61238b565b82815260059290921b8401810191818101908684111561242357600080fd5b8286015b8481101561243e5780358352918301918301612427565b509695505050505050565b600080600080600060a0868803121561246157600080fd5b8535945060208087013561247481611c36565b9450604087013561248481611c36565b935060608701356001600160401b03808211156124a057600080fd5b818901915089601f8301126124b457600080fd5b81356124c26123ff826123bb565b81815260059190911b8301840190848101908c8311156124e157600080fd5b938501935b828510156125085784356124f981611c36565b825293850193908501906124e6565b96505050608089013592508083111561252057600080fd5b505061252e888289016123de565b9150509295509295909350565b604080825283519082018190526000906020906060840190828701845b8281101561257d5781516001600160a01b031684529284019290840190600101612558565b5050508381038285015284518082528583019183019060005b818110156125b257835183529284019291840191600101612596565b5090979650505050505050565b600082601f8301126125d057600080fd5b81356001600160401b038111156125e9576125e9612375565b6125fc601f8201601f191660200161238b565b81815284602083860101111561261157600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561264457600080fd5b84359350602085013561265681611c36565b925060408501356001600160401b038082111561267257600080fd5b61267e888389016125bf565b9350606087013591508082111561269457600080fd5b506126a1878288016125bf565b91505092959194509250565b6001600160a01b03841681526060602082018190526000906126d190830185612240565b82810360408401526126e38185612240565b9695505050505050565b600082516126ff81846020870161221c565b9190910192915050565b60006020828403121561271b57600080fd5b505191905056fea2646970667358221220f432dec92e2b851cf09a10edc80bb08d14c91bd93d7311308f4149c24ce2c61d64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101b05760003560e01c8063b68ad1e4116100ef578063e0563ab111610092578063e0563ab1146103b9578063e30c3978146103c2578063eeb49945146103d3578063f2fde38b146103e6578063f3fef3a3146103f9578063f64512551461040c578063f691325c14610433578063f8c8765e1461044657600080fd5b8063b68ad1e4146102e5578063c1225a20146102f8578063c3b35a7e1461030b578063c5ac2b1c1461031e578063c5e4683a14610345578063d41f177114610358578063d7c9e3ec1461037f578063d8dd1773146103a657600080fd5b80636f33e695116101575780636f33e6951461024b578063715018a61461026057806379ba5097146102685780637efab4f5146102705780638da5cb5b1461029a578063947287cf146102ab57806397e5230d146102b4578063b1768065146102be57600080fd5b806305dc2e8f146101b557806307b3e252146101e55780631bc114ba146101f3578063284017f5146102065780633b878c221461020f57806351351d531461021857806355b01e4d146102265780635ea5df7914610234575b600080fd5b60fd546101c8906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101c86004600360981b0181565b60fc546101c8906001600160a01b031681565b6101c861202081565b6101c861101081565b6101c86002600160a01b0381565b6101c86004600160991b0181565b61023d61138881565b6040519081526020016101dc565b61025e610259366004611c96565b610459565b005b61025e610475565b61025e610489565b6101c861027e366004611d18565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b03166101c8565b61023d61520881565b61023d620249f081565b61023d7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff546101c8906001600160a01b031681565b61025e610306366004611d4a565b610508565b61025e610319366004611d67565b610557565b61023d7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b61025e610353366004611d4a565b61056f565b61023d7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61023d7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61025e6103b4366004611da8565b6105b6565b6101c861203081565b6065546001600160a01b03166101c8565b61025e6103e1366004611e3e565b6106d7565b61025e6103f4366004611d18565b6108f5565b61025e610407366004611ec6565b610966565b61023d7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b60fe546101c8906001600160a01b031681565b61025e610454366004611ef2565b61097d565b610461610a75565b61046e8585858585610a7d565b5050505050565b61047d610de2565b6104876000610e3c565b565b60655433906001600160a01b031681146104fc5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61050581610e3c565b50565b610510610de2565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b61055f610a75565b61056a838383610e55565b505050565b610577610de2565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b03146105dd5760405163973d02cb60e01b81526004016104f390611f4e565b600054610100900460ff16158080156105fd5750600054600160ff909116105b806106175750303b158015610617575060005460ff166001145b6106335760405162461bcd60e51b81526004016104f390611f72565b6000805460ff191660011790558015610656576000805461ff0019166101001790555b6106628888888861115f565b60c9805461ffff191685151561ff001916176101008515150217905561068782610e3c565b80156106cd576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146107435760405162461bcd60e51b815260206004820152602960248201527f4368696c644552433732315072656469636174653a204f4e4c595f53544154456044820152682fa922a1a2a4ab22a960b91b60648201526084016104f3565b60fe546001600160a01b038481169116146107b25760405162461bcd60e51b815260206004820152602960248201527f4368696c644552433732315072656469636174653a204f4e4c595f524f4f545f60448201526850524544494341544560b81b60648201526084016104f3565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216107e1602060008486611fc0565b6107ea91611fea565b03610809576108046107ff8260208186611fc0565b611254565b6108ef565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18610838602060008486611fc0565b61084191611fea565b036108505761080482826114cb565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad61087f602060008486611fc0565b61088891611fea565b03610897576108048282611732565b60405162461bcd60e51b815260206004820152602760248201527f4368696c644552433732315072656469636174653a20494e56414c49445f5349604482015266474e415455524560c81b60648201526084016104f3565b50505050565b6108fd610de2565b606580546001600160a01b0383166001600160a01b0319909116811790915561092e6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b61096e610a75565b610979823383610e55565b5050565b336002600160a01b03146109a45760405163973d02cb60e01b81526004016104f390611f4e565b600054610100900460ff16158080156109c45750600054600160ff909116105b806109de5750303b1580156109de575060005460ff166001145b6109fa5760405162461bcd60e51b81526004016104f390611f72565b6000805460ff191660011790558015610a1d576000805461ff0019166101001790555b610a298585858561115f565b801561046e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b6104876118a2565b84610a8781611ab8565b610aa35760405162461bcd60e51b81526004016104f390612008565b6000866001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b07919061204a565b6001600160a01b0381811660009081526101006020526040902054919250888116911614610b475760405162461bcd60e51b81526004016104f390612067565b6001600160a01b038116610b5d57610b5d6120ab565b306001600160a01b0316876001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ba5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bc9919061204a565b6001600160a01b031614610bdf57610bdf6120ab565b848314610c3a5760405162461bcd60e51b8152602060048201526024808201527f4368696c644552433732315072656469636174653a20494e56414c49445f4c4560448201526309c8ea8960e31b60648201526084016104f3565b60405163b2dc5dc360e01b81526001600160a01b0388169063b2dc5dc390610c6a903390889088906004016120f3565b6020604051808303816000875af1158015610c89573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cad9190612121565b610cc95760405162461bcd60e51b81526004016104f39061213e565b60fc5460fe546040516001600160a01b03928316926316f19831921690610d20907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908d908d908d908d906020016121c8565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610d4c92919061226c565b600060405180830381600087803b158015610d6657600080fd5b505af1158015610d7a573d6000803e3d6000fd5b50505050336001600160a01b0316876001600160a01b0316826001600160a01b03167fa80bc76d6e1849a9088a9c00a2aeaa54eeb78f15565a18da3e8873438976f52289898989604051610dd19493929190612298565b60405180910390a450505050505050565b6033546001600160a01b031633146104875760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104f3565b606580546001600160a01b031916905561050581611b4d565b82610e5f81611ab8565b610e7b5760405162461bcd60e51b81526004016104f390612008565b6000846001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610edf919061204a565b6001600160a01b0381811660009081526101006020526040902054919250868116911614610f1f5760405162461bcd60e51b81526004016104f390612067565b6001600160a01b038116610f3557610f356120ab565b306001600160a01b0316856001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa1919061204a565b6001600160a01b031614610fb757610fb76120ab565b604051632770a7eb60e21b81526001600160a01b03861690639dc29fac90610fe590339087906004016122ca565b6020604051808303816000875af1158015611004573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110289190612121565b6110445760405162461bcd60e51b81526004016104f39061213e565b60fc5460fe54604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152888116608083015260a08083018990528351808403909101815260c08301938490526316f1983160e01b909352938416936316f19831936110cf9391169160c40161226c565b600060405180830381600087803b1580156110e957600080fd5b505af11580156110fd573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b0316826001600160a01b03167f1e0ef6131232b1090efc3ec1cf7b53aa17f4b7cd8a4f9e033b49ee237379b01333876040516111509291906122ca565b60405180910390a45050505050565b6001600160a01b0384161580159061117f57506001600160a01b03831615155b801561119357506001600160a01b03821615155b80156111a757506001600160a01b03811615155b6112045760405162461bcd60e51b815260206004820152602860248201527f4368696c644552433732315072656469636174653a204241445f494e495449416044820152672624ad20aa24a7a760c11b60648201526084016104f3565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b6000808080611265858701876122e3565b6001600160a01b0380851660009081526101006020526040902054949850929650909450925016806112a95760405162461bcd60e51b81526004016104f390612067565b6112b281611ab8565b6112be576112be6120ab565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611322919061204a565b9050856001600160a01b0316816001600160a01b031614611345576113456120ab565b6001600160a01b03811661135b5761135b6120ab565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c7919061204a565b6001600160a01b0316146113dd576113dd6120ab565b6040516340c10f1960e01b81526001600160a01b038316906340c10f199061140b90879087906004016122ca565b6020604051808303816000875af115801561142a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061144e9190612121565b61146a5760405162461bcd60e51b81526004016104f390612334565b836001600160a01b0316826001600160a01b0316876001600160a01b03167f37589fd8c906c19ea68eeb7e6b3e03efc06ff8aa4b1830588eba75f4375b161188876040516114b99291906122ca565b60405180910390a45050505050505050565b60008080806114dc85870187612449565b6001600160a01b03808516600090815261010060205260409020549499509297509095509350169050806115225760405162461bcd60e51b81526004016104f390612067565b61152b81611ab8565b611537576115376120ab565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015611577573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159b919061204a565b9050856001600160a01b0316816001600160a01b0316146115be576115be6120ab565b6001600160a01b0381166115d4576115d46120ab565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561161c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611640919061204a565b6001600160a01b031614611656576116566120ab565b604051637c88e3d960e01b81526001600160a01b03831690637c88e3d990611684908790879060040161253b565b6020604051808303816000875af11580156116a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116c79190612121565b6116e35760405162461bcd60e51b81526004016104f390612334565b846001600160a01b0316826001600160a01b0316876001600160a01b03167fc1b1a5c1b97cc8e5ac82b47496f5ebdadf9c7d119b30a116e2bdafd56f6ed47587876040516114b992919061253b565b600080806117428486018661262e565b91955093509150506001600160a01b038316611760576117606120ab565b6001600160a01b03838116600090815261010060205260409020541615611789576117896120ab565b60ff546040516bffffffffffffffffffffffff19606086901b1660208201526000916117d9916001600160a01b039091169060340160405160208183030381529060405280519060200120611b9f565b6001600160a01b03858116600090815261010060205260409081902080546001600160a01b031916928416928317905551639065714760e01b815291925090639065714790611830908790879087906004016126ad565b600060405180830381600087803b15801561184a57600080fd5b505af115801561185e573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a3505050505050565b60c95460ff16156119ad57604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161190491906126ed565b6000604051808303818686fa925050503d8060008114611940576040519150601f19603f3d011682016040523d82523d6000602084013e611945565b606091505b509150915081801561196a57506000818060200190518101906119689190612709565b115b6119aa5760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b60448201526064016104f3565b50505b60c954610100900460ff161561048757604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b019161138891611a1491906126ed565b6000604051808303818686fa925050503d8060008114611a50576040519150601f19603f3d011682016040523d82523d6000602084013e611a55565b606091505b5091509150818015611a7b575080806020019051810190611a769190612709565b600114155b6109795760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b60448201526064016104f3565b6000816001600160a01b03163b600003611ad457506000919050565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611b3b575060408051601f3d908101601f19168201909252611b3891810190612121565b60015b611b4757506000919050565b92915050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116611b475760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016104f3565b6001600160a01b038116811461050557600080fd5b60008083601f840112611c5d57600080fd5b5081356001600160401b03811115611c7457600080fd5b6020830191508360208260051b8501011115611c8f57600080fd5b9250929050565b600080600080600060608688031215611cae57600080fd5b8535611cb981611c36565b945060208601356001600160401b0380821115611cd557600080fd5b611ce189838a01611c4b565b90965094506040880135915080821115611cfa57600080fd5b50611d0788828901611c4b565b969995985093965092949392505050565b600060208284031215611d2a57600080fd5b8135611d3581611c36565b9392505050565b801515811461050557600080fd5b600060208284031215611d5c57600080fd5b8135611d3581611d3c565b600080600060608486031215611d7c57600080fd5b8335611d8781611c36565b92506020840135611d9781611c36565b929592945050506040919091013590565b600080600080600080600060e0888a031215611dc357600080fd5b8735611dce81611c36565b96506020880135611dde81611c36565b95506040880135611dee81611c36565b94506060880135611dfe81611c36565b93506080880135611e0e81611d3c565b925060a0880135611e1e81611d3c565b915060c0880135611e2e81611c36565b8091505092959891949750929550565b60008060008060608587031215611e5457600080fd5b843593506020850135611e6681611c36565b925060408501356001600160401b0380821115611e8257600080fd5b818701915087601f830112611e9657600080fd5b813581811115611ea557600080fd5b886020828501011115611eb757600080fd5b95989497505060200194505050565b60008060408385031215611ed957600080fd5b8235611ee481611c36565b946020939093013593505050565b60008060008060808587031215611f0857600080fd5b8435611f1381611c36565b93506020850135611f2381611c36565b92506040850135611f3381611c36565b91506060850135611f4381611c36565b939692955090935050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008085851115611fd057600080fd5b83861115611fdd57600080fd5b5050820193919092039150565b80356020831015611b4757600019602084900360031b1b1692915050565b60208082526022908201527f4368696c644552433732315072656469636174653a204e4f545f434f4e54524160408201526110d560f21b606082015260800190565b60006020828403121561205c57600080fd5b8151611d3581611c36565b60208082526024908201527f4368696c644552433732315072656469636174653a20554e4d41505045445f5460408201526327a5a2a760e11b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b038311156120da57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038416815260406020820181905260009061211890830184866120c1565b95945050505050565b60006020828403121561213357600080fd5b8151611d3581611d3c565b60208082526021908201527f4368696c644552433732315072656469636174653a204255524e5f4641494c456040820152601160fa1b606082015260800190565b8183526000602080850194508260005b858110156121bd5781356121a281611c36565b6001600160a01b03168752958201959082019060010161218f565b509495945050505050565b8781526001600160a01b0387811660208301528616604082015260a0606082018190526000906121fb908301868861217f565b828103608084015261220e8185876120c1565b9a9950505050505050505050565b60005b8381101561223757818101518382015260200161221f565b50506000910152565b6000815180845261225881602086016020860161221c565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061229090830184612240565b949350505050565b6040815260006122ac60408301868861217f565b82810360208401526122bf8185876120c1565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b600080600080608085870312156122f957600080fd5b843561230481611c36565b9350602085013561231481611c36565b9250604085013561232481611c36565b9396929550929360600135925050565b60208082526021908201527f4368696c644552433732315072656469636174653a204d494e545f4641494c456040820152601160fa1b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156123b3576123b3612375565b604052919050565b60006001600160401b038211156123d4576123d4612375565b5060051b60200190565b600082601f8301126123ef57600080fd5b813560206124046123ff836123bb565b61238b565b82815260059290921b8401810191818101908684111561242357600080fd5b8286015b8481101561243e5780358352918301918301612427565b509695505050505050565b600080600080600060a0868803121561246157600080fd5b8535945060208087013561247481611c36565b9450604087013561248481611c36565b935060608701356001600160401b03808211156124a057600080fd5b818901915089601f8301126124b457600080fd5b81356124c26123ff826123bb565b81815260059190911b8301840190848101908c8311156124e157600080fd5b938501935b828510156125085784356124f981611c36565b825293850193908501906124e6565b96505050608089013592508083111561252057600080fd5b505061252e888289016123de565b9150509295509295909350565b604080825283519082018190526000906020906060840190828701845b8281101561257d5781516001600160a01b031684529284019290840190600101612558565b5050508381038285015284518082528583019183019060005b818110156125b257835183529284019291840191600101612596565b5090979650505050505050565b600082601f8301126125d057600080fd5b81356001600160401b038111156125e9576125e9612375565b6125fc601f8201601f191660200161238b565b81815284602083860101111561261157600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561264457600080fd5b84359350602085013561265681611c36565b925060408501356001600160401b038082111561267257600080fd5b61267e888389016125bf565b9350606087013591508082111561269457600080fd5b506126a1878288016125bf565b91505092959194509250565b6001600160a01b03841681526060602082018190526000906126d190830185612240565b82810360408401526126e38185612240565b9695505050505050565b600082516126ff81846020870161221c565b9190910192915050565b60006020828403121561271b57600080fd5b505191905056fea2646970667358221220f432dec92e2b851cf09a10edc80bb08d14c91bd93d7311308f4149c24ce2c61d64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RootMintableERC721PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootMintableERC721Predicate\",\n \"sourceName\": \"contracts/child/RootMintableERC721Predicate.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC721Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2MintableERC721DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC721Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2MintableERC721WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC721Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"depositBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC721Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC721Received\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611a8f806100206000396000f3fe608060405234801561001057600080fd5b506004361061016e5760003560e01c806397e5230d116100ce578063e0563ab111610087578063e0563ab114610353578063eeb499451461035c578063f213159c1461036f578063f4a120f714610382578063f645125514610395578063f8c8765e146103bc578063ff6f870c146103cf57600080fd5b806397e5230d1461029a578063b1768065146102a4578063b68ad1e4146102cb578063c5ac2b1c146102de578063d41f177114610305578063d7c9e3ec1461032c57600080fd5b806347e7ef241161012b57806347e7ef241461020d5780634fdca69d1461022257806351351d531461023557806355b01e4d146102435780635ea5df79146102515780637efab4f514610268578063947287cf1461029157600080fd5b806305dc2e8f1461017357806307b3e252146101a3578063150b7a02146101b15780631bc114ba146101e8578063284017f5146101fb5780633b878c2214610204575b600080fd5b603454610186906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101866004600360981b0181565b6101cf6101bf366004611231565b630a85bd0160e11b949350505050565b6040516001600160e01b0319909116815260200161019a565b603354610186906001600160a01b031681565b61018661202081565b61018661101081565b61022061021b3660046112df565b6103e2565b005b603554610186906001600160a01b031681565b6101866002600160a01b0381565b6101866004600160991b0181565b61025a61138881565b60405190815260200161019a565b61018661027636600461130b565b6037602052600090815260409020546001600160a01b031681565b61025a61520881565b61025a620249f081565b61025a7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b603654610186906001600160a01b031681565b61025a7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b61025a7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61025a7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61018661203081565b61022061036a36600461132f565b6103f1565b61022061037d3660046113b7565b6105d1565b61018661039036600461130b565b6105e1565b61025a7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b6102206103ca3660046113f8565b61093a565b6102206103dd36600461149f565b610a97565b6103ed823383610af5565b5050565b6034546001600160a01b031633146104695760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c654552433732315072656469636174653a204f4e4c60448201526f2cafa9aa20aa22afa922a1a2a4ab22a960811b60648201526084015b60405180910390fd5b6035546001600160a01b038481169116146104e05760405162461bcd60e51b815260206004820152603160248201527f526f6f744d696e7461626c654552433732315072656469636174653a204f4e4c604482015270595f4348494c445f50524544494341544560781b6064820152608401610460565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286961050f602060008486611521565b6105189161154b565b036105375761053261052d8260208186611521565b610c74565b6105cb565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed2610566602060008486611521565b61056f9161154b565b0361057e576105328282610d72565b60405162461bcd60e51b815260206004820152602e6024820152600080516020611a3a83398151915260448201526d414c49445f5349474e415455524560901b6064820152608401610460565b50505050565b6105dc838383610af5565b505050565b60006001600160a01b03821661063a5760405162461bcd60e51b815260206004820152602a6024820152600080516020611a3a83398151915260448201526920a624a22faa27a5a2a760b11b6064820152608401610460565b6001600160a01b0382811660009081526037602052604090205416156106b65760405162461bcd60e51b815260206004820152602b60248201527f526f6f744d696e7461626c654552433732315072656469636174653a20414c5260448201526a1150511657d3505414115160aa1b6064820152608401610460565b6035546036546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b039283169260009261076492911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b0385811660008181526037602052604080822080546001600160a01b03191686861617905560335481516306fdde0360e01b81529151959650909316936316f198319387937f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad938b9391926306fdde0392600480830193928290030181865afa1580156107fc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610824919081019061158e565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610862573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261088a919081019061158e565b60405160200161089d9493929190611630565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016108c9929190611677565b600060405180830381600087803b1580156108e357600080fd5b505af11580156108f7573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a39392505050565b336002600160a01b031461097e5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b6044820152606401610460565b600054610100900460ff161580801561099e5750600054600160ff909116105b806109b85750303b1580156109b8575060005460ff166001145b610a1b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610460565b6000805460ff191660011790558015610a3e576000805461ff0019166101001790555b610a4a85858585610eb3565b8015610a90576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b828114610ae85760405162461bcd60e51b815260206004820152602b6024820152600080516020611a3a83398151915260448201526a082989288be988a9c8ea8960ab1b6064820152608401610460565b610a908585858585610faf565b6000610b0084611165565b604051632142170760e11b81529091506001600160a01b038516906342842e0e90610b33903390309087906004016116a3565b600060405180830381600087803b158015610b4d57600080fd5b505af1158015610b61573d6000803e3d6000fd5b5050603354603554604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038a811682840152336060830152898116608083015260a08083018a90528351808403909101815260c08301938490526316f1983160e01b90935293841695506316f198319450610bf1939092169160c401611677565b600060405180830381600087803b158015610c0b57600080fd5b505af1158015610c1f573d6000803e3d6000fd5b505060408051338152602081018690526001600160a01b03808816945085811693508816917fe3abb9ec195b50242582cc6cb7abc990ac26439b9ed7635ed72f7bd720e7477a910160405180910390a46105cb565b6000808080610c85858701876116c7565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610cb857610cb8611718565b604051632142170760e11b81526001600160a01b038616906342842e0e90610ce8903090879087906004016116a3565b600060405180830381600087803b158015610d0257600080fd5b505af1158015610d16573d6000803e3d6000fd5b5050604080516001600160a01b03888116825260208201879052808816945085811693508916917f80afffd84aa825dd9b3c1ba262eb55eef58f78616634437a367a263f3c48fe3d91015b60405180910390a450505050505050565b6000808080610d83858701876117b7565b6001600160a01b03808516600090815260376020526040902054949950929750909550935016905080610db857610db8611718565b60005b8251811015610e6357856001600160a01b03166342842e0e30868481518110610de657610de66118a9565b6020026020010151868581518110610e0057610e006118a9565b60200260200101516040518463ffffffff1660e01b8152600401610e26939291906116a3565b600060405180830381600087803b158015610e4057600080fd5b505af1158015610e54573d6000803e3d6000fd5b50505050806001019050610dbb565b50836001600160a01b0316816001600160a01b0316866001600160a01b03167ff64537485d843fa8a1f4354cb9937954c64282de0828be9f096355006222186b8686604051610d619291906118bf565b6001600160a01b03841615801590610ed357506001600160a01b03831615155b8015610ee757506001600160a01b03821615155b8015610efb57506001600160a01b03811615155b610f5f5760405162461bcd60e51b815260206004820152602f60248201527f526f6f744d696e7461626c654552433732315072656469636174653a2042414460448201526e2fa4a724aa24a0a624ad20aa24a7a760891b6064820152608401610460565b603380546001600160a01b039586166001600160a01b0319918216179091556034805494861694821694909417909355603580549285169284169290921790915560368054919093169116179055565b6000610fba86611165565b905060005b8281101561104c57866001600160a01b03166342842e0e3330878786818110610fea57610fea6118a9565b905060200201356040518463ffffffff1660e01b815260040161100f939291906116a3565b600060405180830381600087803b15801561102957600080fd5b505af115801561103d573d6000803e3d6000fd5b50505050806001019050610fbf565b506033546035546040516001600160a01b03928316926316f198319216906110a4907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908b9033908c908c908c908c906020016119be565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016110d0929190611677565b600060405180830381600087803b1580156110ea57600080fd5b505af11580156110fe573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316876001600160a01b03167f0ca5d99e0f7e7651c00c76347baa68a333790cbc9fb039a10843d1bd61f578c5888888886040516111559493929190611a12565b60405180910390a4505050505050565b6001600160a01b0380821660009081526037602052604090205416806111915761118e826105e1565b90505b6001600160a01b0381166111a7576111a7611718565b919050565b6001600160a01b03811681146111c157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611202576112026111c4565b604052919050565b60006001600160401b03821115611223576112236111c4565b50601f01601f191660200190565b6000806000806080858703121561124757600080fd5b8435611252816111ac565b93506020850135611262816111ac565b92506040850135915060608501356001600160401b0381111561128457600080fd5b8501601f8101871361129557600080fd5b80356112a86112a38261120a565b6111da565b8181528860208385010111156112bd57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080604083850312156112f257600080fd5b82356112fd816111ac565b946020939093013593505050565b60006020828403121561131d57600080fd5b8135611328816111ac565b9392505050565b6000806000806060858703121561134557600080fd5b843593506020850135611357816111ac565b925060408501356001600160401b038082111561137357600080fd5b818701915087601f83011261138757600080fd5b81358181111561139657600080fd5b8860208285010111156113a857600080fd5b95989497505060200194505050565b6000806000606084860312156113cc57600080fd5b83356113d7816111ac565b925060208401356113e7816111ac565b929592945050506040919091013590565b6000806000806080858703121561140e57600080fd5b8435611419816111ac565b93506020850135611429816111ac565b92506040850135611439816111ac565b91506060850135611449816111ac565b939692955090935050565b60008083601f84011261146657600080fd5b5081356001600160401b0381111561147d57600080fd5b6020830191508360208260051b850101111561149857600080fd5b9250929050565b6000806000806000606086880312156114b757600080fd5b85356114c2816111ac565b945060208601356001600160401b03808211156114de57600080fd5b6114ea89838a01611454565b9096509450604088013591508082111561150357600080fd5b5061151088828901611454565b969995985093965092949392505050565b6000808585111561153157600080fd5b8386111561153e57600080fd5b5050820193919092039150565b8035602083101561156457600019602084900360031b1b165b92915050565b60005b8381101561158557818101518382015260200161156d565b50506000910152565b6000602082840312156115a057600080fd5b81516001600160401b038111156115b657600080fd5b8201601f810184136115c757600080fd5b80516115d56112a38261120a565b8181528560208385010111156115ea57600080fd5b6115fb82602083016020860161156a565b95945050505050565b6000815180845261161c81602086016020860161156a565b601f01601f19169290920160200192915050565b8481526001600160a01b038416602082015260806040820181905260009061165a90830185611604565b828103606084015261166c8185611604565b979650505050505050565b6001600160a01b038316815260406020820181905260009061169b90830184611604565b949350505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600080600080608085870312156116dd57600080fd5b84356116e8816111ac565b935060208501356116f8816111ac565b92506040850135611708816111ac565b9396929550929360600135925050565b634e487b7160e01b600052600160045260246000fd5b60006001600160401b03821115611747576117476111c4565b5060051b60200190565b600082601f83011261176257600080fd5b813560206117726112a38361172e565b82815260059290921b8401810191818101908684111561179157600080fd5b8286015b848110156117ac5780358352918301918301611795565b509695505050505050565b600080600080600060a086880312156117cf57600080fd5b853594506020808701356117e2816111ac565b945060408701356117f2816111ac565b935060608701356001600160401b038082111561180e57600080fd5b818901915089601f83011261182257600080fd5b81356118306112a38261172e565b81815260059190911b8301840190848101908c83111561184f57600080fd5b938501935b82851015611876578435611867816111ac565b82529385019390850190611854565b96505050608089013592508083111561188e57600080fd5b505061189c88828901611751565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b828110156119015781516001600160a01b0316845292840192908401906001016118dc565b5050508381038285015284518082528583019183019060005b818110156119365783518352928401929184019160010161191a565b5090979650505050505050565b8183526000602080850194508260005b85811015611981578135611966816111ac565b6001600160a01b031687529582019590820190600101611953565b509495945050505050565b81835260006001600160fb1b038311156119a557600080fd5b8260051b80836020870137939093016020019392505050565b8781526001600160a01b0387811660208301528616604082015260a0606082018190526000906119f19083018688611943565b8281036080840152611a0481858761198c565b9a9950505050505050505050565b604081526000611a26604083018688611943565b828103602084015261166c81858761198c56fe526f6f744d696e7461626c654552433732315072656469636174653a20494e56a2646970667358221220baff62909a0428581d96b1def4713f00df6c8f95df1a380d9a2e4487899aa7f464736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061016e5760003560e01c806397e5230d116100ce578063e0563ab111610087578063e0563ab114610353578063eeb499451461035c578063f213159c1461036f578063f4a120f714610382578063f645125514610395578063f8c8765e146103bc578063ff6f870c146103cf57600080fd5b806397e5230d1461029a578063b1768065146102a4578063b68ad1e4146102cb578063c5ac2b1c146102de578063d41f177114610305578063d7c9e3ec1461032c57600080fd5b806347e7ef241161012b57806347e7ef241461020d5780634fdca69d1461022257806351351d531461023557806355b01e4d146102435780635ea5df79146102515780637efab4f514610268578063947287cf1461029157600080fd5b806305dc2e8f1461017357806307b3e252146101a3578063150b7a02146101b15780631bc114ba146101e8578063284017f5146101fb5780633b878c2214610204575b600080fd5b603454610186906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101866004600360981b0181565b6101cf6101bf366004611231565b630a85bd0160e11b949350505050565b6040516001600160e01b0319909116815260200161019a565b603354610186906001600160a01b031681565b61018661202081565b61018661101081565b61022061021b3660046112df565b6103e2565b005b603554610186906001600160a01b031681565b6101866002600160a01b0381565b6101866004600160991b0181565b61025a61138881565b60405190815260200161019a565b61018661027636600461130b565b6037602052600090815260409020546001600160a01b031681565b61025a61520881565b61025a620249f081565b61025a7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b603654610186906001600160a01b031681565b61025a7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b61025a7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61025a7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61018661203081565b61022061036a36600461132f565b6103f1565b61022061037d3660046113b7565b6105d1565b61018661039036600461130b565b6105e1565b61025a7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b6102206103ca3660046113f8565b61093a565b6102206103dd36600461149f565b610a97565b6103ed823383610af5565b5050565b6034546001600160a01b031633146104695760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c654552433732315072656469636174653a204f4e4c60448201526f2cafa9aa20aa22afa922a1a2a4ab22a960811b60648201526084015b60405180910390fd5b6035546001600160a01b038481169116146104e05760405162461bcd60e51b815260206004820152603160248201527f526f6f744d696e7461626c654552433732315072656469636174653a204f4e4c604482015270595f4348494c445f50524544494341544560781b6064820152608401610460565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286961050f602060008486611521565b6105189161154b565b036105375761053261052d8260208186611521565b610c74565b6105cb565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed2610566602060008486611521565b61056f9161154b565b0361057e576105328282610d72565b60405162461bcd60e51b815260206004820152602e6024820152600080516020611a3a83398151915260448201526d414c49445f5349474e415455524560901b6064820152608401610460565b50505050565b6105dc838383610af5565b505050565b60006001600160a01b03821661063a5760405162461bcd60e51b815260206004820152602a6024820152600080516020611a3a83398151915260448201526920a624a22faa27a5a2a760b11b6064820152608401610460565b6001600160a01b0382811660009081526037602052604090205416156106b65760405162461bcd60e51b815260206004820152602b60248201527f526f6f744d696e7461626c654552433732315072656469636174653a20414c5260448201526a1150511657d3505414115160aa1b6064820152608401610460565b6035546036546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b039283169260009261076492911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b0385811660008181526037602052604080822080546001600160a01b03191686861617905560335481516306fdde0360e01b81529151959650909316936316f198319387937f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad938b9391926306fdde0392600480830193928290030181865afa1580156107fc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610824919081019061158e565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610862573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261088a919081019061158e565b60405160200161089d9493929190611630565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016108c9929190611677565b600060405180830381600087803b1580156108e357600080fd5b505af11580156108f7573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a39392505050565b336002600160a01b031461097e5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b6044820152606401610460565b600054610100900460ff161580801561099e5750600054600160ff909116105b806109b85750303b1580156109b8575060005460ff166001145b610a1b5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610460565b6000805460ff191660011790558015610a3e576000805461ff0019166101001790555b610a4a85858585610eb3565b8015610a90576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b828114610ae85760405162461bcd60e51b815260206004820152602b6024820152600080516020611a3a83398151915260448201526a082989288be988a9c8ea8960ab1b6064820152608401610460565b610a908585858585610faf565b6000610b0084611165565b604051632142170760e11b81529091506001600160a01b038516906342842e0e90610b33903390309087906004016116a3565b600060405180830381600087803b158015610b4d57600080fd5b505af1158015610b61573d6000803e3d6000fd5b5050603354603554604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038a811682840152336060830152898116608083015260a08083018a90528351808403909101815260c08301938490526316f1983160e01b90935293841695506316f198319450610bf1939092169160c401611677565b600060405180830381600087803b158015610c0b57600080fd5b505af1158015610c1f573d6000803e3d6000fd5b505060408051338152602081018690526001600160a01b03808816945085811693508816917fe3abb9ec195b50242582cc6cb7abc990ac26439b9ed7635ed72f7bd720e7477a910160405180910390a46105cb565b6000808080610c85858701876116c7565b6001600160a01b0380851660009081526037602052604090205494985092965090945092501680610cb857610cb8611718565b604051632142170760e11b81526001600160a01b038616906342842e0e90610ce8903090879087906004016116a3565b600060405180830381600087803b158015610d0257600080fd5b505af1158015610d16573d6000803e3d6000fd5b5050604080516001600160a01b03888116825260208201879052808816945085811693508916917f80afffd84aa825dd9b3c1ba262eb55eef58f78616634437a367a263f3c48fe3d91015b60405180910390a450505050505050565b6000808080610d83858701876117b7565b6001600160a01b03808516600090815260376020526040902054949950929750909550935016905080610db857610db8611718565b60005b8251811015610e6357856001600160a01b03166342842e0e30868481518110610de657610de66118a9565b6020026020010151868581518110610e0057610e006118a9565b60200260200101516040518463ffffffff1660e01b8152600401610e26939291906116a3565b600060405180830381600087803b158015610e4057600080fd5b505af1158015610e54573d6000803e3d6000fd5b50505050806001019050610dbb565b50836001600160a01b0316816001600160a01b0316866001600160a01b03167ff64537485d843fa8a1f4354cb9937954c64282de0828be9f096355006222186b8686604051610d619291906118bf565b6001600160a01b03841615801590610ed357506001600160a01b03831615155b8015610ee757506001600160a01b03821615155b8015610efb57506001600160a01b03811615155b610f5f5760405162461bcd60e51b815260206004820152602f60248201527f526f6f744d696e7461626c654552433732315072656469636174653a2042414460448201526e2fa4a724aa24a0a624ad20aa24a7a760891b6064820152608401610460565b603380546001600160a01b039586166001600160a01b0319918216179091556034805494861694821694909417909355603580549285169284169290921790915560368054919093169116179055565b6000610fba86611165565b905060005b8281101561104c57866001600160a01b03166342842e0e3330878786818110610fea57610fea6118a9565b905060200201356040518463ffffffff1660e01b815260040161100f939291906116a3565b600060405180830381600087803b15801561102957600080fd5b505af115801561103d573d6000803e3d6000fd5b50505050806001019050610fbf565b506033546035546040516001600160a01b03928316926316f198319216906110a4907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908b9033908c908c908c908c906020016119be565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016110d0929190611677565b600060405180830381600087803b1580156110ea57600080fd5b505af11580156110fe573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316876001600160a01b03167f0ca5d99e0f7e7651c00c76347baa68a333790cbc9fb039a10843d1bd61f578c5888888886040516111559493929190611a12565b60405180910390a4505050505050565b6001600160a01b0380821660009081526037602052604090205416806111915761118e826105e1565b90505b6001600160a01b0381166111a7576111a7611718565b919050565b6001600160a01b03811681146111c157600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611202576112026111c4565b604052919050565b60006001600160401b03821115611223576112236111c4565b50601f01601f191660200190565b6000806000806080858703121561124757600080fd5b8435611252816111ac565b93506020850135611262816111ac565b92506040850135915060608501356001600160401b0381111561128457600080fd5b8501601f8101871361129557600080fd5b80356112a86112a38261120a565b6111da565b8181528860208385010111156112bd57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080604083850312156112f257600080fd5b82356112fd816111ac565b946020939093013593505050565b60006020828403121561131d57600080fd5b8135611328816111ac565b9392505050565b6000806000806060858703121561134557600080fd5b843593506020850135611357816111ac565b925060408501356001600160401b038082111561137357600080fd5b818701915087601f83011261138757600080fd5b81358181111561139657600080fd5b8860208285010111156113a857600080fd5b95989497505060200194505050565b6000806000606084860312156113cc57600080fd5b83356113d7816111ac565b925060208401356113e7816111ac565b929592945050506040919091013590565b6000806000806080858703121561140e57600080fd5b8435611419816111ac565b93506020850135611429816111ac565b92506040850135611439816111ac565b91506060850135611449816111ac565b939692955090935050565b60008083601f84011261146657600080fd5b5081356001600160401b0381111561147d57600080fd5b6020830191508360208260051b850101111561149857600080fd5b9250929050565b6000806000806000606086880312156114b757600080fd5b85356114c2816111ac565b945060208601356001600160401b03808211156114de57600080fd5b6114ea89838a01611454565b9096509450604088013591508082111561150357600080fd5b5061151088828901611454565b969995985093965092949392505050565b6000808585111561153157600080fd5b8386111561153e57600080fd5b5050820193919092039150565b8035602083101561156457600019602084900360031b1b165b92915050565b60005b8381101561158557818101518382015260200161156d565b50506000910152565b6000602082840312156115a057600080fd5b81516001600160401b038111156115b657600080fd5b8201601f810184136115c757600080fd5b80516115d56112a38261120a565b8181528560208385010111156115ea57600080fd5b6115fb82602083016020860161156a565b95945050505050565b6000815180845261161c81602086016020860161156a565b601f01601f19169290920160200192915050565b8481526001600160a01b038416602082015260806040820181905260009061165a90830185611604565b828103606084015261166c8185611604565b979650505050505050565b6001600160a01b038316815260406020820181905260009061169b90830184611604565b949350505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600080600080608085870312156116dd57600080fd5b84356116e8816111ac565b935060208501356116f8816111ac565b92506040850135611708816111ac565b9396929550929360600135925050565b634e487b7160e01b600052600160045260246000fd5b60006001600160401b03821115611747576117476111c4565b5060051b60200190565b600082601f83011261176257600080fd5b813560206117726112a38361172e565b82815260059290921b8401810191818101908684111561179157600080fd5b8286015b848110156117ac5780358352918301918301611795565b509695505050505050565b600080600080600060a086880312156117cf57600080fd5b853594506020808701356117e2816111ac565b945060408701356117f2816111ac565b935060608701356001600160401b038082111561180e57600080fd5b818901915089601f83011261182257600080fd5b81356118306112a38261172e565b81815260059190911b8301840190848101908c83111561184f57600080fd5b938501935b82851015611876578435611867816111ac565b82529385019390850190611854565b96505050608089013592508083111561188e57600080fd5b505061189c88828901611751565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b828110156119015781516001600160a01b0316845292840192908401906001016118dc565b5050508381038285015284518082528583019183019060005b818110156119365783518352928401929184019160010161191a565b5090979650505050505050565b8183526000602080850194508260005b85811015611981578135611966816111ac565b6001600160a01b031687529582019590820190600101611953565b509495945050505050565b81835260006001600160fb1b038311156119a557600080fd5b8260051b80836020870137939093016020019392505050565b8781526001600160a01b0387811660208301528616604082015260a0606082018190526000906119f19083018688611943565b8281036080840152611a0481858761198c565b9a9950505050505050505050565b604081526000611a26604083018688611943565b828103602084015261166c81858761198c56fe526f6f744d696e7461626c654552433732315072656469636174653a20494e56a2646970667358221220baff62909a0428581d96b1def4713f00df6c8f95df1a380d9a2e4487899aa7f464736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RootMintableERC721PredicateACLArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootMintableERC721PredicateAccessList\",\n \"sourceName\": \"contracts/child/RootMintableERC721PredicateAccessList.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"AllowListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"BlockListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC721Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2MintableERC721DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC721Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2MintableERC721WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC721Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"depositBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC721Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC721Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC721Received\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setAllowList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setBlockList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612231806100206000396000f3fe608060405234801561001057600080fd5b50600436106101e65760003560e01c8063b17680651161010a578063e0563ab1116100ad578063f2fde38b1161007c578063f2fde38b14610466578063f4a120f714610479578063f64512551461048c578063f8c8765e146104b3578063ff6f870c146104c657600080fd5b8063e0563ab114610426578063e30c39781461042f578063eeb4994514610440578063f213159c1461045357600080fd5b8063b17680651461033e578063b68ad1e414610365578063c1225a2014610378578063c5ac2b1c1461038b578063c5e4683a146103b2578063d41f1771146103c5578063d7c9e3ec146103ec578063d8dd17731461041357600080fd5b806351351d531161018d57806379ba50971161015c57806379ba5097146102e85780637efab4f5146102f05780638da5cb5b1461031a578063947287cf1461032b57806397e5230d1461033457600080fd5b806351351d53146102ad57806355b01e4d146102bb5780635ea5df79146102c9578063715018a6146102e057600080fd5b806305dc2e8f146101eb57806307b3e2521461021b578063150b7a02146102295780631bc114ba14610260578063284017f5146102735780633b878c221461027c57806347e7ef24146102855780634fdca69d1461029a575b600080fd5b60fd546101fe906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101fe6004600360981b0181565b61024761023736600461186f565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610212565b60fc546101fe906001600160a01b031681565b6101fe61202081565b6101fe61101081565b61029861029336600461191d565b6104d9565b005b60fe546101fe906001600160a01b031681565b6101fe6002600160a01b0381565b6101fe6004600160991b0181565b6102d261138881565b604051908152602001610212565b6102986104e8565b6102986104fc565b6101fe6102fe366004611949565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b03166101fe565b6102d261520881565b6102d2620249f081565b6102d27f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff546101fe906001600160a01b031681565b61029861038636600461197d565b61057b565b6102d27faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6102986103c036600461197d565b6105ca565b6102d27f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102d27f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b610298610421366004611998565b610611565b6101fe61203081565b6065546001600160a01b03166101fe565b61029861044e366004611a2a565b610732565b610298610461366004611ab2565b61090d565b610298610474366004611949565b61091d565b6101fe610487366004611949565b61098e565b6102d27f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b6102986104c1366004611af3565b610ce9565b6102986104d4366004611b9a565b610de2565b6104e4823383610e40565b5050565b6104f0610fc7565b6104fa6000611021565b565b60655433906001600160a01b0316811461056f5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61057881611021565b50565b610583610fc7565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b6105d2610fc7565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b03146106385760405163973d02cb60e01b815260040161056690611c1c565b600054610100900460ff16158080156106585750600054600160ff909116105b806106725750303b158015610672575060005460ff166001145b61068e5760405162461bcd60e51b815260040161056690611c40565b6000805460ff1916600117905580156106b1576000805461ff0019166101001790555b6106bd8888888861103a565b60c9805461ffff191685151561ff00191617610100851515021790556106e282611021565b8015610728576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146107a55760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c654552433732315072656469636174653a204f4e4c60448201526f2cafa9aa20aa22afa922a1a2a4ab22a960811b6064820152608401610566565b60fe546001600160a01b0384811691161461081c5760405162461bcd60e51b815260206004820152603160248201527f526f6f744d696e7461626c654552433732315072656469636174653a204f4e4c604482015270595f4348494c445f50524544494341544560781b6064820152608401610566565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286961084b602060008486611c8e565b61085491611cb8565b036108735761086e6108698260208186611c8e565b611136565b610907565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed26108a2602060008486611c8e565b6108ab91611cb8565b036108ba5761086e8282611235565b60405162461bcd60e51b815260206004820152602e60248201526000805160206121dc83398151915260448201526d414c49445f5349474e415455524560901b6064820152608401610566565b50505050565b610918838383610e40565b505050565b610925610fc7565b606580546001600160a01b0383166001600160a01b031990911681179091556109566033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60006001600160a01b0382166109e75760405162461bcd60e51b815260206004820152602a60248201526000805160206121dc83398151915260448201526920a624a22faa27a5a2a760b11b6064820152608401610566565b6001600160a01b03828116600090815261010060205260409020541615610a645760405162461bcd60e51b815260206004820152602b60248201527f526f6f744d696e7461626c654552433732315072656469636174653a20414c5260448201526a1150511657d3505414115160aa1b6064820152608401610566565b60fe5460ff546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b0392831692600092610b1292911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b038581166000818152610100602052604080822080546001600160a01b03191686861617905560fc5481516306fdde0360e01b81529151959650909316936316f198319387937f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad938b9391926306fdde0392600480830193928290030181865afa158015610bab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bd39190810190611cfb565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c11573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c399190810190611cfb565b604051602001610c4c9493929190611d9d565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610c78929190611de4565b600060405180830381600087803b158015610c9257600080fd5b505af1158015610ca6573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a39392505050565b336002600160a01b0314610d105760405163973d02cb60e01b815260040161056690611c1c565b600054610100900460ff1615808015610d305750600054600160ff909116105b80610d4a5750303b158015610d4a575060005460ff166001145b610d665760405162461bcd60e51b815260040161056690611c40565b6000805460ff191660011790558015610d89576000805461ff0019166101001790555b610d958585858561103a565b8015610ddb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b828114610e335760405162461bcd60e51b815260206004820152602b60248201526000805160206121dc83398151915260448201526a082989288be988a9c8ea8960ab1b6064820152608401610566565b610ddb8585858585611377565b610e48611535565b6000610e538461153d565b604051632142170760e11b81529091506001600160a01b038516906342842e0e90610e8690339030908790600401611e10565b600060405180830381600087803b158015610ea057600080fd5b505af1158015610eb4573d6000803e3d6000fd5b505060fc5460fe54604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038a811682840152336060830152898116608083015260a08083018a90528351808403909101815260c08301938490526316f1983160e01b90935293841695506316f198319450610f44939092169160c401611de4565b600060405180830381600087803b158015610f5e57600080fd5b505af1158015610f72573d6000803e3d6000fd5b505060408051338152602081018690526001600160a01b03808816945085811693508816917fe3abb9ec195b50242582cc6cb7abc990ac26439b9ed7635ed72f7bd720e7477a910160405180910390a4610907565b6033546001600160a01b031633146104fa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610566565b606580546001600160a01b031916905561057881611585565b6001600160a01b0384161580159061105a57506001600160a01b03831615155b801561106e57506001600160a01b03821615155b801561108257506001600160a01b03811615155b6110e65760405162461bcd60e51b815260206004820152602f60248201527f526f6f744d696e7461626c654552433732315072656469636174653a2042414460448201526e2fa4a724aa24a0a624ad20aa24a7a760891b6064820152608401610566565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b600080808061114785870187611e34565b6001600160a01b03808516600090815261010060205260409020549498509296509094509250168061117b5761117b611e85565b604051632142170760e11b81526001600160a01b038616906342842e0e906111ab90309087908790600401611e10565b600060405180830381600087803b1580156111c557600080fd5b505af11580156111d9573d6000803e3d6000fd5b5050604080516001600160a01b03888116825260208201879052808816945085811693508916917f80afffd84aa825dd9b3c1ba262eb55eef58f78616634437a367a263f3c48fe3d91015b60405180910390a450505050505050565b600080808061124685870187611f24565b6001600160a01b038085166000908152610100602052604090205494995092975090955093501690508061127c5761127c611e85565b60005b825181101561132757856001600160a01b03166342842e0e308684815181106112aa576112aa612016565b60200260200101518685815181106112c4576112c4612016565b60200260200101516040518463ffffffff1660e01b81526004016112ea93929190611e10565b600060405180830381600087803b15801561130457600080fd5b505af1158015611318573d6000803e3d6000fd5b5050505080600101905061127f565b50836001600160a01b0316816001600160a01b0316866001600160a01b03167ff64537485d843fa8a1f4354cb9937954c64282de0828be9f096355006222186b868660405161122492919061202c565b61137f611535565b600061138a8661153d565b905060005b8281101561141c57866001600160a01b03166342842e0e33308787868181106113ba576113ba612016565b905060200201356040518463ffffffff1660e01b81526004016113df93929190611e10565b600060405180830381600087803b1580156113f957600080fd5b505af115801561140d573d6000803e3d6000fd5b5050505080600101905061138f565b5060fc5460fe546040516001600160a01b03928316926316f19831921690611474907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908b9033908c908c908c908c9060200161212b565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016114a0929190611de4565b600060405180830381600087803b1580156114ba57600080fd5b505af11580156114ce573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316876001600160a01b03167f0ca5d99e0f7e7651c00c76347baa68a333790cbc9fb039a10843d1bd61f578c588888888604051611525949392919061217f565b60405180910390a4505050505050565b6104fa6115d7565b6001600160a01b0380821660009081526101006020526040902054168061156a576115678261098e565b90505b6001600160a01b03811661158057611580611e85565b919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c95460ff16156116e257604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161163991906121a6565b6000604051808303818686fa925050503d8060008114611675576040519150601f19603f3d011682016040523d82523d6000602084013e61167a565b606091505b509150915081801561169f575060008180602001905181019061169d91906121c2565b115b6116df5760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b6044820152606401610566565b50505b60c954610100900460ff16156104fa57604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b01916113889161174991906121a6565b6000604051808303818686fa925050503d8060008114611785576040519150601f19603f3d011682016040523d82523d6000602084013e61178a565b606091505b50915091508180156117b05750808060200190518101906117ab91906121c2565b600114155b6104e45760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b6044820152606401610566565b6001600160a01b038116811461057857600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561184057611840611802565b604052919050565b60006001600160401b0382111561186157611861611802565b50601f01601f191660200190565b6000806000806080858703121561188557600080fd5b8435611890816117ed565b935060208501356118a0816117ed565b92506040850135915060608501356001600160401b038111156118c257600080fd5b8501601f810187136118d357600080fd5b80356118e66118e182611848565b611818565b8181528860208385010111156118fb57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561193057600080fd5b823561193b816117ed565b946020939093013593505050565b60006020828403121561195b57600080fd5b8135611966816117ed565b9392505050565b8035801515811461158057600080fd5b60006020828403121561198f57600080fd5b6119668261196d565b600080600080600080600060e0888a0312156119b357600080fd5b87356119be816117ed565b965060208801356119ce816117ed565b955060408801356119de816117ed565b945060608801356119ee816117ed565b93506119fc6080890161196d565b9250611a0a60a0890161196d565b915060c0880135611a1a816117ed565b8091505092959891949750929550565b60008060008060608587031215611a4057600080fd5b843593506020850135611a52816117ed565b925060408501356001600160401b0380821115611a6e57600080fd5b818701915087601f830112611a8257600080fd5b813581811115611a9157600080fd5b886020828501011115611aa357600080fd5b95989497505060200194505050565b600080600060608486031215611ac757600080fd5b8335611ad2816117ed565b92506020840135611ae2816117ed565b929592945050506040919091013590565b60008060008060808587031215611b0957600080fd5b8435611b14816117ed565b93506020850135611b24816117ed565b92506040850135611b34816117ed565b91506060850135611b44816117ed565b939692955090935050565b60008083601f840112611b6157600080fd5b5081356001600160401b03811115611b7857600080fd5b6020830191508360208260051b8501011115611b9357600080fd5b9250929050565b600080600080600060608688031215611bb257600080fd5b8535611bbd816117ed565b945060208601356001600160401b0380821115611bd957600080fd5b611be589838a01611b4f565b90965094506040880135915080821115611bfe57600080fd5b50611c0b88828901611b4f565b969995985093965092949392505050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008085851115611c9e57600080fd5b83861115611cab57600080fd5b5050820193919092039150565b80356020831015611cd157600019602084900360031b1b165b92915050565b60005b83811015611cf2578181015183820152602001611cda565b50506000910152565b600060208284031215611d0d57600080fd5b81516001600160401b03811115611d2357600080fd5b8201601f81018413611d3457600080fd5b8051611d426118e182611848565b818152856020838501011115611d5757600080fd5b611d68826020830160208601611cd7565b95945050505050565b60008151808452611d89816020860160208601611cd7565b601f01601f19169290920160200192915050565b8481526001600160a01b0384166020820152608060408201819052600090611dc790830185611d71565b8281036060840152611dd98185611d71565b979650505050505050565b6001600160a01b0383168152604060208201819052600090611e0890830184611d71565b949350505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60008060008060808587031215611e4a57600080fd5b8435611e55816117ed565b93506020850135611e65816117ed565b92506040850135611e75816117ed565b9396929550929360600135925050565b634e487b7160e01b600052600160045260246000fd5b60006001600160401b03821115611eb457611eb4611802565b5060051b60200190565b600082601f830112611ecf57600080fd5b81356020611edf6118e183611e9b565b82815260059290921b84018101918181019086841115611efe57600080fd5b8286015b84811015611f195780358352918301918301611f02565b509695505050505050565b600080600080600060a08688031215611f3c57600080fd5b85359450602080870135611f4f816117ed565b94506040870135611f5f816117ed565b935060608701356001600160401b0380821115611f7b57600080fd5b818901915089601f830112611f8f57600080fd5b8135611f9d6118e182611e9b565b81815260059190911b8301840190848101908c831115611fbc57600080fd5b938501935b82851015611fe3578435611fd4816117ed565b82529385019390850190611fc1565b965050506080890135925080831115611ffb57600080fd5b505061200988828901611ebe565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b8281101561206e5781516001600160a01b031684529284019290840190600101612049565b5050508381038285015284518082528583019183019060005b818110156120a357835183529284019291840191600101612087565b5090979650505050505050565b8183526000602080850194508260005b858110156120ee5781356120d3816117ed565b6001600160a01b0316875295820195908201906001016120c0565b509495945050505050565b81835260006001600160fb1b0383111561211257600080fd5b8260051b80836020870137939093016020019392505050565b8781526001600160a01b0387811660208301528616604082015260a06060820181905260009061215e90830186886120b0565b82810360808401526121718185876120f9565b9a9950505050505050505050565b6040815260006121936040830186886120b0565b8281036020840152611dd98185876120f9565b600082516121b8818460208701611cd7565b9190910192915050565b6000602082840312156121d457600080fd5b505191905056fe526f6f744d696e7461626c654552433732315072656469636174653a20494e56a2646970667358221220d1bfc2912b6d936204f8bcd526922cd1de25280dfe606eaddf8c127bfcff177364736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101e65760003560e01c8063b17680651161010a578063e0563ab1116100ad578063f2fde38b1161007c578063f2fde38b14610466578063f4a120f714610479578063f64512551461048c578063f8c8765e146104b3578063ff6f870c146104c657600080fd5b8063e0563ab114610426578063e30c39781461042f578063eeb4994514610440578063f213159c1461045357600080fd5b8063b17680651461033e578063b68ad1e414610365578063c1225a2014610378578063c5ac2b1c1461038b578063c5e4683a146103b2578063d41f1771146103c5578063d7c9e3ec146103ec578063d8dd17731461041357600080fd5b806351351d531161018d57806379ba50971161015c57806379ba5097146102e85780637efab4f5146102f05780638da5cb5b1461031a578063947287cf1461032b57806397e5230d1461033457600080fd5b806351351d53146102ad57806355b01e4d146102bb5780635ea5df79146102c9578063715018a6146102e057600080fd5b806305dc2e8f146101eb57806307b3e2521461021b578063150b7a02146102295780631bc114ba14610260578063284017f5146102735780633b878c221461027c57806347e7ef24146102855780634fdca69d1461029a575b600080fd5b60fd546101fe906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101fe6004600360981b0181565b61024761023736600461186f565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610212565b60fc546101fe906001600160a01b031681565b6101fe61202081565b6101fe61101081565b61029861029336600461191d565b6104d9565b005b60fe546101fe906001600160a01b031681565b6101fe6002600160a01b0381565b6101fe6004600160991b0181565b6102d261138881565b604051908152602001610212565b6102986104e8565b6102986104fc565b6101fe6102fe366004611949565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b03166101fe565b6102d261520881565b6102d2620249f081565b6102d27f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff546101fe906001600160a01b031681565b61029861038636600461197d565b61057b565b6102d27faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6102986103c036600461197d565b6105ca565b6102d27f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102d27f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b610298610421366004611998565b610611565b6101fe61203081565b6065546001600160a01b03166101fe565b61029861044e366004611a2a565b610732565b610298610461366004611ab2565b61090d565b610298610474366004611949565b61091d565b6101fe610487366004611949565b61098e565b6102d27f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b6102986104c1366004611af3565b610ce9565b6102986104d4366004611b9a565b610de2565b6104e4823383610e40565b5050565b6104f0610fc7565b6104fa6000611021565b565b60655433906001600160a01b0316811461056f5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61057881611021565b50565b610583610fc7565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b6105d2610fc7565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b03146106385760405163973d02cb60e01b815260040161056690611c1c565b600054610100900460ff16158080156106585750600054600160ff909116105b806106725750303b158015610672575060005460ff166001145b61068e5760405162461bcd60e51b815260040161056690611c40565b6000805460ff1916600117905580156106b1576000805461ff0019166101001790555b6106bd8888888861103a565b60c9805461ffff191685151561ff00191617610100851515021790556106e282611021565b8015610728576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146107a55760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c654552433732315072656469636174653a204f4e4c60448201526f2cafa9aa20aa22afa922a1a2a4ab22a960811b6064820152608401610566565b60fe546001600160a01b0384811691161461081c5760405162461bcd60e51b815260206004820152603160248201527f526f6f744d696e7461626c654552433732315072656469636174653a204f4e4c604482015270595f4348494c445f50524544494341544560781b6064820152608401610566565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286961084b602060008486611c8e565b61085491611cb8565b036108735761086e6108698260208186611c8e565b611136565b610907565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed26108a2602060008486611c8e565b6108ab91611cb8565b036108ba5761086e8282611235565b60405162461bcd60e51b815260206004820152602e60248201526000805160206121dc83398151915260448201526d414c49445f5349474e415455524560901b6064820152608401610566565b50505050565b610918838383610e40565b505050565b610925610fc7565b606580546001600160a01b0383166001600160a01b031990911681179091556109566033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60006001600160a01b0382166109e75760405162461bcd60e51b815260206004820152602a60248201526000805160206121dc83398151915260448201526920a624a22faa27a5a2a760b11b6064820152608401610566565b6001600160a01b03828116600090815261010060205260409020541615610a645760405162461bcd60e51b815260206004820152602b60248201527f526f6f744d696e7461626c654552433732315072656469636174653a20414c5260448201526a1150511657d3505414115160aa1b6064820152608401610566565b60fe5460ff546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b0392831692600092610b1292911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b038581166000818152610100602052604080822080546001600160a01b03191686861617905560fc5481516306fdde0360e01b81529151959650909316936316f198319387937f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad938b9391926306fdde0392600480830193928290030181865afa158015610bab573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bd39190810190611cfb565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c11573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c399190810190611cfb565b604051602001610c4c9493929190611d9d565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610c78929190611de4565b600060405180830381600087803b158015610c9257600080fd5b505af1158015610ca6573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a39392505050565b336002600160a01b0314610d105760405163973d02cb60e01b815260040161056690611c1c565b600054610100900460ff1615808015610d305750600054600160ff909116105b80610d4a5750303b158015610d4a575060005460ff166001145b610d665760405162461bcd60e51b815260040161056690611c40565b6000805460ff191660011790558015610d89576000805461ff0019166101001790555b610d958585858561103a565b8015610ddb576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b828114610e335760405162461bcd60e51b815260206004820152602b60248201526000805160206121dc83398151915260448201526a082989288be988a9c8ea8960ab1b6064820152608401610566565b610ddb8585858585611377565b610e48611535565b6000610e538461153d565b604051632142170760e11b81529091506001600160a01b038516906342842e0e90610e8690339030908790600401611e10565b600060405180830381600087803b158015610ea057600080fd5b505af1158015610eb4573d6000803e3d6000fd5b505060fc5460fe54604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038a811682840152336060830152898116608083015260a08083018a90528351808403909101815260c08301938490526316f1983160e01b90935293841695506316f198319450610f44939092169160c401611de4565b600060405180830381600087803b158015610f5e57600080fd5b505af1158015610f72573d6000803e3d6000fd5b505060408051338152602081018690526001600160a01b03808816945085811693508816917fe3abb9ec195b50242582cc6cb7abc990ac26439b9ed7635ed72f7bd720e7477a910160405180910390a4610907565b6033546001600160a01b031633146104fa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610566565b606580546001600160a01b031916905561057881611585565b6001600160a01b0384161580159061105a57506001600160a01b03831615155b801561106e57506001600160a01b03821615155b801561108257506001600160a01b03811615155b6110e65760405162461bcd60e51b815260206004820152602f60248201527f526f6f744d696e7461626c654552433732315072656469636174653a2042414460448201526e2fa4a724aa24a0a624ad20aa24a7a760891b6064820152608401610566565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b600080808061114785870187611e34565b6001600160a01b03808516600090815261010060205260409020549498509296509094509250168061117b5761117b611e85565b604051632142170760e11b81526001600160a01b038616906342842e0e906111ab90309087908790600401611e10565b600060405180830381600087803b1580156111c557600080fd5b505af11580156111d9573d6000803e3d6000fd5b5050604080516001600160a01b03888116825260208201879052808816945085811693508916917f80afffd84aa825dd9b3c1ba262eb55eef58f78616634437a367a263f3c48fe3d91015b60405180910390a450505050505050565b600080808061124685870187611f24565b6001600160a01b038085166000908152610100602052604090205494995092975090955093501690508061127c5761127c611e85565b60005b825181101561132757856001600160a01b03166342842e0e308684815181106112aa576112aa612016565b60200260200101518685815181106112c4576112c4612016565b60200260200101516040518463ffffffff1660e01b81526004016112ea93929190611e10565b600060405180830381600087803b15801561130457600080fd5b505af1158015611318573d6000803e3d6000fd5b5050505080600101905061127f565b50836001600160a01b0316816001600160a01b0316866001600160a01b03167ff64537485d843fa8a1f4354cb9937954c64282de0828be9f096355006222186b868660405161122492919061202c565b61137f611535565b600061138a8661153d565b905060005b8281101561141c57866001600160a01b03166342842e0e33308787868181106113ba576113ba612016565b905060200201356040518463ffffffff1660e01b81526004016113df93929190611e10565b600060405180830381600087803b1580156113f957600080fd5b505af115801561140d573d6000803e3d6000fd5b5050505080600101905061138f565b5060fc5460fe546040516001600160a01b03928316926316f19831921690611474907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908b9033908c908c908c908c9060200161212b565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016114a0929190611de4565b600060405180830381600087803b1580156114ba57600080fd5b505af11580156114ce573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316876001600160a01b03167f0ca5d99e0f7e7651c00c76347baa68a333790cbc9fb039a10843d1bd61f578c588888888604051611525949392919061217f565b60405180910390a4505050505050565b6104fa6115d7565b6001600160a01b0380821660009081526101006020526040902054168061156a576115678261098e565b90505b6001600160a01b03811661158057611580611e85565b919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c95460ff16156116e257604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161163991906121a6565b6000604051808303818686fa925050503d8060008114611675576040519150601f19603f3d011682016040523d82523d6000602084013e61167a565b606091505b509150915081801561169f575060008180602001905181019061169d91906121c2565b115b6116df5760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b6044820152606401610566565b50505b60c954610100900460ff16156104fa57604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b01916113889161174991906121a6565b6000604051808303818686fa925050503d8060008114611785576040519150601f19603f3d011682016040523d82523d6000602084013e61178a565b606091505b50915091508180156117b05750808060200190518101906117ab91906121c2565b600114155b6104e45760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b6044820152606401610566565b6001600160a01b038116811461057857600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561184057611840611802565b604052919050565b60006001600160401b0382111561186157611861611802565b50601f01601f191660200190565b6000806000806080858703121561188557600080fd5b8435611890816117ed565b935060208501356118a0816117ed565b92506040850135915060608501356001600160401b038111156118c257600080fd5b8501601f810187136118d357600080fd5b80356118e66118e182611848565b611818565b8181528860208385010111156118fb57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561193057600080fd5b823561193b816117ed565b946020939093013593505050565b60006020828403121561195b57600080fd5b8135611966816117ed565b9392505050565b8035801515811461158057600080fd5b60006020828403121561198f57600080fd5b6119668261196d565b600080600080600080600060e0888a0312156119b357600080fd5b87356119be816117ed565b965060208801356119ce816117ed565b955060408801356119de816117ed565b945060608801356119ee816117ed565b93506119fc6080890161196d565b9250611a0a60a0890161196d565b915060c0880135611a1a816117ed565b8091505092959891949750929550565b60008060008060608587031215611a4057600080fd5b843593506020850135611a52816117ed565b925060408501356001600160401b0380821115611a6e57600080fd5b818701915087601f830112611a8257600080fd5b813581811115611a9157600080fd5b886020828501011115611aa357600080fd5b95989497505060200194505050565b600080600060608486031215611ac757600080fd5b8335611ad2816117ed565b92506020840135611ae2816117ed565b929592945050506040919091013590565b60008060008060808587031215611b0957600080fd5b8435611b14816117ed565b93506020850135611b24816117ed565b92506040850135611b34816117ed565b91506060850135611b44816117ed565b939692955090935050565b60008083601f840112611b6157600080fd5b5081356001600160401b03811115611b7857600080fd5b6020830191508360208260051b8501011115611b9357600080fd5b9250929050565b600080600080600060608688031215611bb257600080fd5b8535611bbd816117ed565b945060208601356001600160401b0380821115611bd957600080fd5b611be589838a01611b4f565b90965094506040880135915080821115611bfe57600080fd5b50611c0b88828901611b4f565b969995985093965092949392505050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008085851115611c9e57600080fd5b83861115611cab57600080fd5b5050820193919092039150565b80356020831015611cd157600019602084900360031b1b165b92915050565b60005b83811015611cf2578181015183820152602001611cda565b50506000910152565b600060208284031215611d0d57600080fd5b81516001600160401b03811115611d2357600080fd5b8201601f81018413611d3457600080fd5b8051611d426118e182611848565b818152856020838501011115611d5757600080fd5b611d68826020830160208601611cd7565b95945050505050565b60008151808452611d89816020860160208601611cd7565b601f01601f19169290920160200192915050565b8481526001600160a01b0384166020820152608060408201819052600090611dc790830185611d71565b8281036060840152611dd98185611d71565b979650505050505050565b6001600160a01b0383168152604060208201819052600090611e0890830184611d71565b949350505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60008060008060808587031215611e4a57600080fd5b8435611e55816117ed565b93506020850135611e65816117ed565b92506040850135611e75816117ed565b9396929550929360600135925050565b634e487b7160e01b600052600160045260246000fd5b60006001600160401b03821115611eb457611eb4611802565b5060051b60200190565b600082601f830112611ecf57600080fd5b81356020611edf6118e183611e9b565b82815260059290921b84018101918181019086841115611efe57600080fd5b8286015b84811015611f195780358352918301918301611f02565b509695505050505050565b600080600080600060a08688031215611f3c57600080fd5b85359450602080870135611f4f816117ed565b94506040870135611f5f816117ed565b935060608701356001600160401b0380821115611f7b57600080fd5b818901915089601f830112611f8f57600080fd5b8135611f9d6118e182611e9b565b81815260059190911b8301840190848101908c831115611fbc57600080fd5b938501935b82851015611fe3578435611fd4816117ed565b82529385019390850190611fc1565b965050506080890135925080831115611ffb57600080fd5b505061200988828901611ebe565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b8281101561206e5781516001600160a01b031684529284019290840190600101612049565b5050508381038285015284518082528583019183019060005b818110156120a357835183529284019291840191600101612087565b5090979650505050505050565b8183526000602080850194508260005b858110156120ee5781356120d3816117ed565b6001600160a01b0316875295820195908201906001016120c0565b509495945050505050565b81835260006001600160fb1b0383111561211257600080fd5b8260051b80836020870137939093016020019392505050565b8781526001600160a01b0387811660208301528616604082015260a06060820181905260009061215e90830186886120b0565b82810360808401526121718185876120f9565b9a9950505050505050505050565b6040815260006121936040830186886120b0565b8281036020840152611dd98185876120f9565b600082516121b8818460208701611cd7565b9190910192915050565b6000602082840312156121d457600080fd5b505191905056fe526f6f744d696e7461626c654552433732315072656469636174653a20494e56a2646970667358221220d1bfc2912b6d936204f8bcd526922cd1de25280dfe606eaddf8c127bfcff177364736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC1155Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC1155\",\n \"sourceName\": \"contracts/child/ChildERC1155.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bool\",\n \"name\": \"approved\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"ApprovalForAll\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"userAddress\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"relayerAddress\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"functionSignature\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"MetaTransactionExecuted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"ids\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"values\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"TransferBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"TransferSingle\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"string\",\n \"name\": \"value\",\n \"type\": \"string\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"URI\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"accounts\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"ids\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"balanceOfBatch\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"\",\n \"type\": \"uint256[]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"burnBatch\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"userAddress\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"functionSignature\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"sigR\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"sigS\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint8\",\n \"name\": \"sigV\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"executeMetaTransaction\",\n \"outputs\": [\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"user\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"getNonce\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"nonce\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"rootToken_\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"uri_\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"offset\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"invalidateNext\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"isApprovedForAll\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"accounts\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"mintBatch\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"ids\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"safeBatchTransferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"safeTransferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"approved\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setApprovalForAll\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"uri\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612b8b806100206000396000f3fe608060405234801561001057600080fd5b50600436106101155760003560e01c806357128683116100a2578063e619870511610071578063e619870514610279578063e985e9c51461028b578063f242432a146102c7578063f399e22e146102da578063f5298aca146102ed57600080fd5b8063571286831461022d5780636b20c454146102405780639b77ef1114610253578063a22cb4651461026657600080fd5b8063156e29f6116100e9578063156e29f6146101965780631f2d0065146101a95780632d0335ab146101cf5780632eb2c2d6146101f85780634e1273f41461020d57600080fd5b8062fdd58e1461011a57806301ffc9a7146101405780630c53c51c146101635780630e89341c14610183575b600080fd5b61012d610128366004611cd5565b610300565b6040519081526020015b60405180910390f35b61015361014e366004611d15565b61039b565b6040519015158152602001610137565b610176610171366004611d7a565b6103eb565b6040516101379190611e49565b610176610191366004611e5c565b6106c9565b6101536101a4366004611e75565b61075d565b610103546001600160a01b03165b6040516001600160a01b039091168152602001610137565b61012d6101dd366004611ea8565b6001600160a01b031660009081526038602052604090205490565b61020b61020636600461200c565b6107b0565b005b61022061021b3660046120b5565b61080e565b60405161013791906121ba565b61015361023b366004612211565b610937565b61015361024e3660046122aa565b610a53565b61020b610261366004611e5c565b610afb565b61020b61027436600461232a565b610b22565b610102546001600160a01b03166101b7565b610153610299366004612366565b6001600160a01b03918216600090815260d16020908152604080832093909416825291909152205460ff1690565b61020b6102d5366004612399565b610b38565b61020b6102e83660046123fd565b610b8f565b6101536102fb366004611e75565b610da5565b60006001600160a01b0383166103705760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b50600081815260d0602090815260408083206001600160a01b03861684529091529020545b92915050565b60006001600160e01b03198216636cdb3d1360e11b14806103cc57506001600160e01b031982166303a24d0760e21b145b8061039557506301ffc9a760e01b6001600160e01b0319831614610395565b6060600061042e87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610dde92505050565b90506001600160e01b03196000358116908216036104b45760405162461bcd60e51b815260206004820152603d60248201527f66756e6374696f6e5369676e61747572652063616e206e6f74206265206f662060448201527f657865637574654d6574615472616e73616374696f6e206d6574686f640000006064820152608401610367565b604080516060810182526001600160a01b038a16600081815260386020908152848220548452808401929092528351601f8b0183900483028101830185528a815290938301918b908b9081908401838280828437600092019190915250505091525090506105258982888888610df9565b61057b5760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610367565b603860008a6001600160a01b03166001600160a01b031681526020019081526020016000206000815460010191905081905550600080306001600160a01b03168a8a8d6040516020016105d09392919061244f565b60408051601f19818403018152908290526105ea91612475565b6000604051808303816000865af19150503d8060008114610627576040519150601f19603f3d011682016040523d82523d6000602084013e61062c565b606091505b50915091508161067e5760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610367565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b8b338c8c6040516106b39493929190612491565b60405180910390a19a9950505050505050505050565b606060d280546106d8906124dd565b80601f0160208091040260200160405190810160405280929190818152602001828054610704906124dd565b80156107515780601f1061072657610100808354040283529160200191610751565b820191906000526020600020905b81548152906001019060200180831161073457829003601f168201915b50505050509050919050565b610102546000906001600160a01b0316331461078b5760405162461bcd60e51b815260040161036790612517565b6107a684848460405180602001604052806000815250610ed5565b5060019392505050565b6107b8610fe4565b6001600160a01b0316856001600160a01b031614806107de57506107de85610299610fe4565b6107fa5760405162461bcd60e51b81526004016103679061255c565b6108078585858585610ff3565b5050505050565b606081518351146108735760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610367565b600083516001600160401b0381111561088e5761088e611ec3565b6040519080825280602002602001820160405280156108b7578160200160208202803683370190505b50905060005b845181101561092f576109028582815181106108db576108db6125aa565b60200260200101518583815181106108f5576108f56125aa565b6020026020010151610300565b828281518110610914576109146125aa565b6020908102919091010152610928816125d6565b90506108bd565b509392505050565b610102546000906001600160a01b031633146109655760405162461bcd60e51b815260040161036790612517565b85848114801561097457508083145b6109c05760405162461bcd60e51b815260206004820181905260248201527f4368696c64455243313135353a206172726179206c656e206d69736d617463686044820152606401610367565b60005b81811015610a4457610a3c8989838181106109e0576109e06125aa565b90506020020160208101906109f59190611ea8565b888884818110610a0757610a076125aa565b90506020020135878785818110610a2057610a206125aa565b9050602002013560405180602001604052806000815250610ed5565b6001016109c3565b50600198975050505050505050565b610102546000906001600160a01b03163314610a815760405162461bcd60e51b815260040161036790612517565b610aef8686868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a0282810182019093528982529093508992508891829185019084908082843760009201919091525061119d92505050565b50600195945050505050565b3360009081526038602052604081208054839290610b1a9084906125ef565b909155505050565b610b34610b2d610fe4565b8383611334565b5050565b610b40610fe4565b6001600160a01b0316856001600160a01b03161480610b665750610b6685610299610fe4565b610b825760405162461bcd60e51b81526004016103679061255c565b6108078585858585611414565b606b54610100900460ff1615808015610baf5750606b54600160ff909116105b80610bc95750303b158015610bc95750606b5460ff166001145b610c2c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610367565b606b805460ff191660011790558015610c4f57606b805461ff0019166101001790555b6001600160a01b038416610ca55760405162461bcd60e51b815260206004820181905260248201527f4368696c64455243313135353a204241445f494e495449414c495a4154494f4e6044820152606401610367565b61010380546001600160a01b0386166001600160a01b031991821617909155610102805490911633179055604080516020601f8501819004810282018101909252838152610d0d91859085908190840183828082843760009201919091525061153b92505050565b610d59610d22856001600160a01b031661156e565b604051602001610d329190612602565b60408051601f1981840301815282820190915260018252603160f81b602083015290611584565b8015610d9f57606b805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610102546000906001600160a01b03163314610dd35760405162461bcd60e51b815260040161036790612517565b6107a68484846115f0565b60008151600003610df157506000919050565b506020015190565b6000806001610e0f610e0a886116f0565b61176d565b6040805160008152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015610e5d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610eb45760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610367565b866001600160a01b0316816001600160a01b03161491505095945050505050565b6001600160a01b038416610f355760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610367565b6000610f3f610fe4565b90506000610f4c8561179a565b90506000610f598561179a565b9050600086815260d0602090815260408083206001600160a01b038b16845290915281208054879290610f8d9084906125ef565b909155505060408051878152602081018790526001600160a01b03808a169260009291871691600080516020612af3833981519152910160405180910390a4610fdb836000898989896117e5565b50505050505050565b6000610fee611940565b905090565b81518351146110145760405162461bcd60e51b815260040161036790612637565b6001600160a01b03841661103a5760405162461bcd60e51b81526004016103679061267f565b6000611044610fe4565b905060005b845181101561112f576000858281518110611066576110666125aa565b602002602001015190506000858381518110611084576110846125aa565b602090810291909101810151600084815260d0835260408082206001600160a01b038e1683529093529190912054909150818110156110d55760405162461bcd60e51b8152600401610367906126c4565b600083815260d0602090815260408083206001600160a01b038e8116855292528083208585039055908b168252812080548492906111149084906125ef565b9250508190555050505080611128906125d6565b9050611049565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161117f92919061270e565b60405180910390a461119581878787878761199c565b505050505050565b6001600160a01b0383166111c35760405162461bcd60e51b81526004016103679061273c565b80518251146111e45760405162461bcd60e51b815260040161036790612637565b60006111ee610fe4565b604080516020810190915260009052905060005b83518110156112c757600084828151811061121f5761121f6125aa565b60200260200101519050600084838151811061123d5761123d6125aa565b602090810291909101810151600084815260d0835260408082206001600160a01b038c16835290935291909120549091508181101561128e5760405162461bcd60e51b81526004016103679061277f565b600092835260d0602090815260408085206001600160a01b038b16865290915290922091039055806112bf816125d6565b915050611202565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161131892919061270e565b60405180910390a4604080516020810190915260009052610d9f565b816001600160a01b0316836001600160a01b0316036113a75760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610367565b6001600160a01b03838116600081815260d16020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b03841661143a5760405162461bcd60e51b81526004016103679061267f565b6000611444610fe4565b905060006114518561179a565b9050600061145e8561179a565b9050600086815260d0602090815260408083206001600160a01b038c168452909152902054858110156114a35760405162461bcd60e51b8152600401610367906126c4565b600087815260d0602090815260408083206001600160a01b038d8116855292528083208985039055908a168252812080548892906114e29084906125ef565b909155505060408051888152602081018890526001600160a01b03808b16928c82169291881691600080516020612af3833981519152910160405180910390a4611530848a8a8a8a8a6117e5565b505050505050505050565b606b54610100900460ff166115625760405162461bcd60e51b8152600401610367906127c3565b61156b81611a57565b50565b60606103956001600160a01b0383166014611a87565b815160208084019190912082519183019190912060038290556004819055466001557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6115d2818484611c29565b600055600280546001600160a01b0319163017905560055550505050565b6001600160a01b0383166116165760405162461bcd60e51b81526004016103679061273c565b6000611620610fe4565b9050600061162d8461179a565b9050600061163a8461179a565b604080516020808201835260009182905288825260d081528282206001600160a01b038b16835290522054909150848110156116885760405162461bcd60e51b81526004016103679061277f565b600086815260d0602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a9052909290881691600080516020612af3833981519152910160405180910390a4604080516020810190915260009052610fdb565b6000604051806080016040528060438152602001612b136043913980516020918201208351848301516040808701518051908601209051611750950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061039561177a611c72565b8360405161190160f01b8152600281019290925260228201526042902090565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106117d4576117d46125aa565b602090810291909101015292915050565b6001600160a01b0384163b156111955760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611829908990899088908890889060040161280e565b6020604051808303816000875af1925050508015611864575060408051601f3d908101601f1916820190925261186191810190612853565b60015b61191057611870612870565b806308c379a0036118a9575061188461288b565b8061188f57506118ab565b8060405162461bcd60e51b81526004016103679190611e49565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610367565b6001600160e01b0319811663f23a6e6160e01b14610fdb5760405162461bcd60e51b815260040161036790612914565b600030330361199657600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506119999050565b50335b90565b6001600160a01b0384163b156111955760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906119e0908990899088908890889060040161295c565b6020604051808303816000875af1925050508015611a1b575060408051601f3d908101601f19168201909252611a1891810190612853565b60015b611a2757611870612870565b6001600160e01b0319811663bc197c8160e01b14610fdb5760405162461bcd60e51b815260040161036790612914565b606b54610100900460ff16611a7e5760405162461bcd60e51b8152600401610367906127c3565b61156b81611cad565b60606000611a968360026129ba565b611aa19060026125ef565b6001600160401b03811115611ab857611ab8611ec3565b6040519080825280601f01601f191660200182016040528015611ae2576020820181803683370190505b509050600360fc1b81600081518110611afd57611afd6125aa565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611b2c57611b2c6125aa565b60200101906001600160f81b031916908160001a9053506000611b508460026129ba565b611b5b9060016125ef565b90505b6001811115611bd3576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611b8f57611b8f6125aa565b1a60f81b828281518110611ba557611ba56125aa565b60200101906001600160f81b031916908160001a90535060049490941c93611bcc816129d1565b9050611b5e565b508315611c225760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610367565b9392505050565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6002546000906001600160a01b031630148015611c90575060015446145b15611c9c575060005490565b610fee600554600354600454611c29565b60d2610b348282612a33565b80356001600160a01b0381168114611cd057600080fd5b919050565b60008060408385031215611ce857600080fd5b611cf183611cb9565b946020939093013593505050565b6001600160e01b03198116811461156b57600080fd5b600060208284031215611d2757600080fd5b8135611c2281611cff565b60008083601f840112611d4457600080fd5b5081356001600160401b03811115611d5b57600080fd5b602083019150836020828501011115611d7357600080fd5b9250929050565b60008060008060008060a08789031215611d9357600080fd5b611d9c87611cb9565b955060208701356001600160401b03811115611db757600080fd5b611dc389828a01611d32565b9096509450506040870135925060608701359150608087013560ff81168114611deb57600080fd5b809150509295509295509295565b60005b83811015611e14578181015183820152602001611dfc565b50506000910152565b60008151808452611e35816020860160208601611df9565b601f01601f19169290920160200192915050565b602081526000611c226020830184611e1d565b600060208284031215611e6e57600080fd5b5035919050565b600080600060608486031215611e8a57600080fd5b611e9384611cb9565b95602085013595506040909401359392505050565b600060208284031215611eba57600080fd5b611c2282611cb9565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715611efe57611efe611ec3565b6040525050565b60006001600160401b03821115611f1e57611f1e611ec3565b5060051b60200190565b600082601f830112611f3957600080fd5b81356020611f4682611f05565b604051611f538282611ed9565b83815260059390931b8501820192828101915086841115611f7357600080fd5b8286015b84811015611f8e5780358352918301918301611f77565b509695505050505050565b600082601f830112611faa57600080fd5b81356001600160401b03811115611fc357611fc3611ec3565b604051611fda601f8301601f191660200182611ed9565b818152846020838601011115611fef57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561202457600080fd5b61202d86611cb9565b945061203b60208701611cb9565b935060408601356001600160401b038082111561205757600080fd5b61206389838a01611f28565b9450606088013591508082111561207957600080fd5b61208589838a01611f28565b9350608088013591508082111561209b57600080fd5b506120a888828901611f99565b9150509295509295909350565b600080604083850312156120c857600080fd5b82356001600160401b03808211156120df57600080fd5b818501915085601f8301126120f357600080fd5b8135602061210082611f05565b60405161210d8282611ed9565b83815260059390931b850182019282810191508984111561212d57600080fd5b948201945b838610156121525761214386611cb9565b82529482019490820190612132565b9650508601359250508082111561216857600080fd5b5061217585828601611f28565b9150509250929050565b600081518084526020808501945080840160005b838110156121af57815187529582019590820190600101612193565b509495945050505050565b602081526000611c22602083018461217f565b60008083601f8401126121df57600080fd5b5081356001600160401b038111156121f657600080fd5b6020830191508360208260051b8501011115611d7357600080fd5b6000806000806000806060878903121561222a57600080fd5b86356001600160401b038082111561224157600080fd5b61224d8a838b016121cd565b9098509650602089013591508082111561226657600080fd5b6122728a838b016121cd565b9096509450604089013591508082111561228b57600080fd5b5061229889828a016121cd565b979a9699509497509295939492505050565b6000806000806000606086880312156122c257600080fd5b6122cb86611cb9565b945060208601356001600160401b03808211156122e757600080fd5b6122f389838a016121cd565b9096509450604088013591508082111561230c57600080fd5b50612319888289016121cd565b969995985093965092949392505050565b6000806040838503121561233d57600080fd5b61234683611cb9565b91506020830135801515811461235b57600080fd5b809150509250929050565b6000806040838503121561237957600080fd5b61238283611cb9565b915061239060208401611cb9565b90509250929050565b600080600080600060a086880312156123b157600080fd5b6123ba86611cb9565b94506123c860208701611cb9565b9350604086013592506060860135915060808601356001600160401b038111156123f157600080fd5b6120a888828901611f99565b60008060006040848603121561241257600080fd5b61241b84611cb9565b925060208401356001600160401b0381111561243657600080fd5b61244286828701611d32565b9497909650939450505050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251612487818460208701611df9565b9190910192915050565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b600181811c908216806124f157607f821691505b60208210810361251157634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526025908201527f4368696c64455243313135353a204f6e6c79207072656469636174652063616e6040820152640818d85b1b60da1b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016125e8576125e86125c0565b5060010190565b80820180821115610395576103956125c0565b6c4368696c64455243313135352d60981b81526000825161262a81600d850160208701611df9565b91909101600d0192915050565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b604081526000612721604083018561217f565b8281036020840152612733818561217f565b95945050505050565b60208082526023908201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526024908201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604082015263616e636560e01b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061284890830184611e1d565b979650505050505050565b60006020828403121561286557600080fd5b8151611c2281611cff565b600060033d11156119995760046000803e5060005160e01c90565b600060443d10156128995790565b6040516003193d81016004833e81513d6001600160401b0381602484011181841117156128c857505050505090565b82850191508151818111156128e05750505050505090565b843d87010160208285010111156128fa5750505050505090565b61290960208286010187611ed9565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6001600160a01b0386811682528516602082015260a0604082018190526000906129889083018661217f565b828103606084015261299a818661217f565b905082810360808401526129ae8185611e1d565b98975050505050505050565b8082028115828204841417610395576103956125c0565b6000816129e0576129e06125c0565b506000190190565b601f821115612a2e57600081815260208120601f850160051c81016020861015612a0f5750805b601f850160051c820191505b8181101561119557828155600101612a1b565b505050565b81516001600160401b03811115612a4c57612a4c611ec3565b612a6081612a5a84546124dd565b846129e8565b602080601f831160018114612a955760008415612a7d5750858301515b600019600386901b1c1916600185901b178555611195565b600085815260208120601f198616915b82811015612ac457888601518255948401946001909101908401612aa5565b5085821015612ae25787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fec3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f624d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a2646970667358221220e461f7064aa6c6c6ffa4776432fb8d1d9904257257018fc2ec1efb0abb81165064736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101155760003560e01c806357128683116100a2578063e619870511610071578063e619870514610279578063e985e9c51461028b578063f242432a146102c7578063f399e22e146102da578063f5298aca146102ed57600080fd5b8063571286831461022d5780636b20c454146102405780639b77ef1114610253578063a22cb4651461026657600080fd5b8063156e29f6116100e9578063156e29f6146101965780631f2d0065146101a95780632d0335ab146101cf5780632eb2c2d6146101f85780634e1273f41461020d57600080fd5b8062fdd58e1461011a57806301ffc9a7146101405780630c53c51c146101635780630e89341c14610183575b600080fd5b61012d610128366004611cd5565b610300565b6040519081526020015b60405180910390f35b61015361014e366004611d15565b61039b565b6040519015158152602001610137565b610176610171366004611d7a565b6103eb565b6040516101379190611e49565b610176610191366004611e5c565b6106c9565b6101536101a4366004611e75565b61075d565b610103546001600160a01b03165b6040516001600160a01b039091168152602001610137565b61012d6101dd366004611ea8565b6001600160a01b031660009081526038602052604090205490565b61020b61020636600461200c565b6107b0565b005b61022061021b3660046120b5565b61080e565b60405161013791906121ba565b61015361023b366004612211565b610937565b61015361024e3660046122aa565b610a53565b61020b610261366004611e5c565b610afb565b61020b61027436600461232a565b610b22565b610102546001600160a01b03166101b7565b610153610299366004612366565b6001600160a01b03918216600090815260d16020908152604080832093909416825291909152205460ff1690565b61020b6102d5366004612399565b610b38565b61020b6102e83660046123fd565b610b8f565b6101536102fb366004611e75565b610da5565b60006001600160a01b0383166103705760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b50600081815260d0602090815260408083206001600160a01b03861684529091529020545b92915050565b60006001600160e01b03198216636cdb3d1360e11b14806103cc57506001600160e01b031982166303a24d0760e21b145b8061039557506301ffc9a760e01b6001600160e01b0319831614610395565b6060600061042e87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610dde92505050565b90506001600160e01b03196000358116908216036104b45760405162461bcd60e51b815260206004820152603d60248201527f66756e6374696f6e5369676e61747572652063616e206e6f74206265206f662060448201527f657865637574654d6574615472616e73616374696f6e206d6574686f640000006064820152608401610367565b604080516060810182526001600160a01b038a16600081815260386020908152848220548452808401929092528351601f8b0183900483028101830185528a815290938301918b908b9081908401838280828437600092019190915250505091525090506105258982888888610df9565b61057b5760405162461bcd60e51b815260206004820152602160248201527f5369676e657220616e64207369676e617475726520646f206e6f74206d6174636044820152600d60fb1b6064820152608401610367565b603860008a6001600160a01b03166001600160a01b031681526020019081526020016000206000815460010191905081905550600080306001600160a01b03168a8a8d6040516020016105d09392919061244f565b60408051601f19818403018152908290526105ea91612475565b6000604051808303816000865af19150503d8060008114610627576040519150601f19603f3d011682016040523d82523d6000602084013e61062c565b606091505b50915091508161067e5760405162461bcd60e51b815260206004820152601c60248201527f46756e6374696f6e2063616c6c206e6f74207375636365737366756c000000006044820152606401610367565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b8b338c8c6040516106b39493929190612491565b60405180910390a19a9950505050505050505050565b606060d280546106d8906124dd565b80601f0160208091040260200160405190810160405280929190818152602001828054610704906124dd565b80156107515780601f1061072657610100808354040283529160200191610751565b820191906000526020600020905b81548152906001019060200180831161073457829003601f168201915b50505050509050919050565b610102546000906001600160a01b0316331461078b5760405162461bcd60e51b815260040161036790612517565b6107a684848460405180602001604052806000815250610ed5565b5060019392505050565b6107b8610fe4565b6001600160a01b0316856001600160a01b031614806107de57506107de85610299610fe4565b6107fa5760405162461bcd60e51b81526004016103679061255c565b6108078585858585610ff3565b5050505050565b606081518351146108735760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610367565b600083516001600160401b0381111561088e5761088e611ec3565b6040519080825280602002602001820160405280156108b7578160200160208202803683370190505b50905060005b845181101561092f576109028582815181106108db576108db6125aa565b60200260200101518583815181106108f5576108f56125aa565b6020026020010151610300565b828281518110610914576109146125aa565b6020908102919091010152610928816125d6565b90506108bd565b509392505050565b610102546000906001600160a01b031633146109655760405162461bcd60e51b815260040161036790612517565b85848114801561097457508083145b6109c05760405162461bcd60e51b815260206004820181905260248201527f4368696c64455243313135353a206172726179206c656e206d69736d617463686044820152606401610367565b60005b81811015610a4457610a3c8989838181106109e0576109e06125aa565b90506020020160208101906109f59190611ea8565b888884818110610a0757610a076125aa565b90506020020135878785818110610a2057610a206125aa565b9050602002013560405180602001604052806000815250610ed5565b6001016109c3565b50600198975050505050505050565b610102546000906001600160a01b03163314610a815760405162461bcd60e51b815260040161036790612517565b610aef8686868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a0282810182019093528982529093508992508891829185019084908082843760009201919091525061119d92505050565b50600195945050505050565b3360009081526038602052604081208054839290610b1a9084906125ef565b909155505050565b610b34610b2d610fe4565b8383611334565b5050565b610b40610fe4565b6001600160a01b0316856001600160a01b03161480610b665750610b6685610299610fe4565b610b825760405162461bcd60e51b81526004016103679061255c565b6108078585858585611414565b606b54610100900460ff1615808015610baf5750606b54600160ff909116105b80610bc95750303b158015610bc95750606b5460ff166001145b610c2c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610367565b606b805460ff191660011790558015610c4f57606b805461ff0019166101001790555b6001600160a01b038416610ca55760405162461bcd60e51b815260206004820181905260248201527f4368696c64455243313135353a204241445f494e495449414c495a4154494f4e6044820152606401610367565b61010380546001600160a01b0386166001600160a01b031991821617909155610102805490911633179055604080516020601f8501819004810282018101909252838152610d0d91859085908190840183828082843760009201919091525061153b92505050565b610d59610d22856001600160a01b031661156e565b604051602001610d329190612602565b60408051601f1981840301815282820190915260018252603160f81b602083015290611584565b8015610d9f57606b805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b610102546000906001600160a01b03163314610dd35760405162461bcd60e51b815260040161036790612517565b6107a68484846115f0565b60008151600003610df157506000919050565b506020015190565b6000806001610e0f610e0a886116f0565b61176d565b6040805160008152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015610e5d573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610eb45760405162461bcd60e51b8152602060048201526011602482015270496e76616c6964207369676e617475726560781b6044820152606401610367565b866001600160a01b0316816001600160a01b03161491505095945050505050565b6001600160a01b038416610f355760405162461bcd60e51b815260206004820152602160248201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736044820152607360f81b6064820152608401610367565b6000610f3f610fe4565b90506000610f4c8561179a565b90506000610f598561179a565b9050600086815260d0602090815260408083206001600160a01b038b16845290915281208054879290610f8d9084906125ef565b909155505060408051878152602081018790526001600160a01b03808a169260009291871691600080516020612af3833981519152910160405180910390a4610fdb836000898989896117e5565b50505050505050565b6000610fee611940565b905090565b81518351146110145760405162461bcd60e51b815260040161036790612637565b6001600160a01b03841661103a5760405162461bcd60e51b81526004016103679061267f565b6000611044610fe4565b905060005b845181101561112f576000858281518110611066576110666125aa565b602002602001015190506000858381518110611084576110846125aa565b602090810291909101810151600084815260d0835260408082206001600160a01b038e1683529093529190912054909150818110156110d55760405162461bcd60e51b8152600401610367906126c4565b600083815260d0602090815260408083206001600160a01b038e8116855292528083208585039055908b168252812080548492906111149084906125ef565b9250508190555050505080611128906125d6565b9050611049565b50846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb878760405161117f92919061270e565b60405180910390a461119581878787878761199c565b505050505050565b6001600160a01b0383166111c35760405162461bcd60e51b81526004016103679061273c565b80518251146111e45760405162461bcd60e51b815260040161036790612637565b60006111ee610fe4565b604080516020810190915260009052905060005b83518110156112c757600084828151811061121f5761121f6125aa565b60200260200101519050600084838151811061123d5761123d6125aa565b602090810291909101810151600084815260d0835260408082206001600160a01b038c16835290935291909120549091508181101561128e5760405162461bcd60e51b81526004016103679061277f565b600092835260d0602090815260408085206001600160a01b038b16865290915290922091039055806112bf816125d6565b915050611202565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb868660405161131892919061270e565b60405180910390a4604080516020810190915260009052610d9f565b816001600160a01b0316836001600160a01b0316036113a75760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610367565b6001600160a01b03838116600081815260d16020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6001600160a01b03841661143a5760405162461bcd60e51b81526004016103679061267f565b6000611444610fe4565b905060006114518561179a565b9050600061145e8561179a565b9050600086815260d0602090815260408083206001600160a01b038c168452909152902054858110156114a35760405162461bcd60e51b8152600401610367906126c4565b600087815260d0602090815260408083206001600160a01b038d8116855292528083208985039055908a168252812080548892906114e29084906125ef565b909155505060408051888152602081018890526001600160a01b03808b16928c82169291881691600080516020612af3833981519152910160405180910390a4611530848a8a8a8a8a6117e5565b505050505050505050565b606b54610100900460ff166115625760405162461bcd60e51b8152600401610367906127c3565b61156b81611a57565b50565b60606103956001600160a01b0383166014611a87565b815160208084019190912082519183019190912060038290556004819055466001557f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6115d2818484611c29565b600055600280546001600160a01b0319163017905560055550505050565b6001600160a01b0383166116165760405162461bcd60e51b81526004016103679061273c565b6000611620610fe4565b9050600061162d8461179a565b9050600061163a8461179a565b604080516020808201835260009182905288825260d081528282206001600160a01b038b16835290522054909150848110156116885760405162461bcd60e51b81526004016103679061277f565b600086815260d0602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a9052909290881691600080516020612af3833981519152910160405180910390a4604080516020810190915260009052610fdb565b6000604051806080016040528060438152602001612b136043913980516020918201208351848301516040808701518051908601209051611750950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b600061039561177a611c72565b8360405161190160f01b8152600281019290925260228201526042902090565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106117d4576117d46125aa565b602090810291909101015292915050565b6001600160a01b0384163b156111955760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611829908990899088908890889060040161280e565b6020604051808303816000875af1925050508015611864575060408051601f3d908101601f1916820190925261186191810190612853565b60015b61191057611870612870565b806308c379a0036118a9575061188461288b565b8061188f57506118ab565b8060405162461bcd60e51b81526004016103679190611e49565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610367565b6001600160e01b0319811663f23a6e6160e01b14610fdb5760405162461bcd60e51b815260040161036790612914565b600030330361199657600080368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050503601516001600160a01b031691506119999050565b50335b90565b6001600160a01b0384163b156111955760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906119e0908990899088908890889060040161295c565b6020604051808303816000875af1925050508015611a1b575060408051601f3d908101601f19168201909252611a1891810190612853565b60015b611a2757611870612870565b6001600160e01b0319811663bc197c8160e01b14610fdb5760405162461bcd60e51b815260040161036790612914565b606b54610100900460ff16611a7e5760405162461bcd60e51b8152600401610367906127c3565b61156b81611cad565b60606000611a968360026129ba565b611aa19060026125ef565b6001600160401b03811115611ab857611ab8611ec3565b6040519080825280601f01601f191660200182016040528015611ae2576020820181803683370190505b509050600360fc1b81600081518110611afd57611afd6125aa565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611b2c57611b2c6125aa565b60200101906001600160f81b031916908160001a9053506000611b508460026129ba565b611b5b9060016125ef565b90505b6001811115611bd3576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611b8f57611b8f6125aa565b1a60f81b828281518110611ba557611ba56125aa565b60200101906001600160f81b031916908160001a90535060049490941c93611bcc816129d1565b9050611b5e565b508315611c225760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610367565b9392505050565b6040805160208101859052908101839052606081018290524660808201523060a082015260009060c0016040516020818303038152906040528051906020012090509392505050565b6002546000906001600160a01b031630148015611c90575060015446145b15611c9c575060005490565b610fee600554600354600454611c29565b60d2610b348282612a33565b80356001600160a01b0381168114611cd057600080fd5b919050565b60008060408385031215611ce857600080fd5b611cf183611cb9565b946020939093013593505050565b6001600160e01b03198116811461156b57600080fd5b600060208284031215611d2757600080fd5b8135611c2281611cff565b60008083601f840112611d4457600080fd5b5081356001600160401b03811115611d5b57600080fd5b602083019150836020828501011115611d7357600080fd5b9250929050565b60008060008060008060a08789031215611d9357600080fd5b611d9c87611cb9565b955060208701356001600160401b03811115611db757600080fd5b611dc389828a01611d32565b9096509450506040870135925060608701359150608087013560ff81168114611deb57600080fd5b809150509295509295509295565b60005b83811015611e14578181015183820152602001611dfc565b50506000910152565b60008151808452611e35816020860160208601611df9565b601f01601f19169290920160200192915050565b602081526000611c226020830184611e1d565b600060208284031215611e6e57600080fd5b5035919050565b600080600060608486031215611e8a57600080fd5b611e9384611cb9565b95602085013595506040909401359392505050565b600060208284031215611eba57600080fd5b611c2282611cb9565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715611efe57611efe611ec3565b6040525050565b60006001600160401b03821115611f1e57611f1e611ec3565b5060051b60200190565b600082601f830112611f3957600080fd5b81356020611f4682611f05565b604051611f538282611ed9565b83815260059390931b8501820192828101915086841115611f7357600080fd5b8286015b84811015611f8e5780358352918301918301611f77565b509695505050505050565b600082601f830112611faa57600080fd5b81356001600160401b03811115611fc357611fc3611ec3565b604051611fda601f8301601f191660200182611ed9565b818152846020838601011115611fef57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561202457600080fd5b61202d86611cb9565b945061203b60208701611cb9565b935060408601356001600160401b038082111561205757600080fd5b61206389838a01611f28565b9450606088013591508082111561207957600080fd5b61208589838a01611f28565b9350608088013591508082111561209b57600080fd5b506120a888828901611f99565b9150509295509295909350565b600080604083850312156120c857600080fd5b82356001600160401b03808211156120df57600080fd5b818501915085601f8301126120f357600080fd5b8135602061210082611f05565b60405161210d8282611ed9565b83815260059390931b850182019282810191508984111561212d57600080fd5b948201945b838610156121525761214386611cb9565b82529482019490820190612132565b9650508601359250508082111561216857600080fd5b5061217585828601611f28565b9150509250929050565b600081518084526020808501945080840160005b838110156121af57815187529582019590820190600101612193565b509495945050505050565b602081526000611c22602083018461217f565b60008083601f8401126121df57600080fd5b5081356001600160401b038111156121f657600080fd5b6020830191508360208260051b8501011115611d7357600080fd5b6000806000806000806060878903121561222a57600080fd5b86356001600160401b038082111561224157600080fd5b61224d8a838b016121cd565b9098509650602089013591508082111561226657600080fd5b6122728a838b016121cd565b9096509450604089013591508082111561228b57600080fd5b5061229889828a016121cd565b979a9699509497509295939492505050565b6000806000806000606086880312156122c257600080fd5b6122cb86611cb9565b945060208601356001600160401b03808211156122e757600080fd5b6122f389838a016121cd565b9096509450604088013591508082111561230c57600080fd5b50612319888289016121cd565b969995985093965092949392505050565b6000806040838503121561233d57600080fd5b61234683611cb9565b91506020830135801515811461235b57600080fd5b809150509250929050565b6000806040838503121561237957600080fd5b61238283611cb9565b915061239060208401611cb9565b90509250929050565b600080600080600060a086880312156123b157600080fd5b6123ba86611cb9565b94506123c860208701611cb9565b9350604086013592506060860135915060808601356001600160401b038111156123f157600080fd5b6120a888828901611f99565b60008060006040848603121561241257600080fd5b61241b84611cb9565b925060208401356001600160401b0381111561243657600080fd5b61244286828701611d32565b9497909650939450505050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b60008251612487818460208701611df9565b9190910192915050565b6001600160a01b0385811682528416602082015260606040820181905281018290526000828460808401376000608084840101526080601f19601f850116830101905095945050505050565b600181811c908216806124f157607f821691505b60208210810361251157634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526025908201527f4368696c64455243313135353a204f6e6c79207072656469636174652063616e6040820152640818d85b1b60da1b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016125e8576125e86125c0565b5060010190565b80820180821115610395576103956125c0565b6c4368696c64455243313135352d60981b81526000825161262a81600d850160208701611df9565b91909101600d0192915050565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b604081526000612721604083018561217f565b8281036020840152612733818561217f565b95945050505050565b60208082526023908201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526024908201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604082015263616e636560e01b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061284890830184611e1d565b979650505050505050565b60006020828403121561286557600080fd5b8151611c2281611cff565b600060033d11156119995760046000803e5060005160e01c90565b600060443d10156128995790565b6040516003193d81016004833e81513d6001600160401b0381602484011181841117156128c857505050505090565b82850191508151818111156128e05750505050505090565b843d87010160208285010111156128fa5750505050505090565b61290960208286010187611ed9565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b6001600160a01b0386811682528516602082015260a0604082018190526000906129889083018661217f565b828103606084015261299a818661217f565b905082810360808401526129ae8185611e1d565b98975050505050505050565b8082028115828204841417610395576103956125c0565b6000816129e0576129e06125c0565b506000190190565b601f821115612a2e57600081815260208120601f850160051c81016020861015612a0f5750805b601f850160051c820191505b8181101561119557828155600101612a1b565b505050565b81516001600160401b03811115612a4c57612a4c611ec3565b612a6081612a5a84546124dd565b846129e8565b602080601f831160018114612a955760008415612a7d5750858301515b600019600386901b1c1916600185901b178555611195565b600085815260208120601f198616915b82811015612ac457888601518255948401946001909101908401612aa5565b5085821015612ae25787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fec3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f624d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a2646970667358221220e461f7064aa6c6c6ffa4776432fb8d1d9904257257018fc2ec1efb0abb81165064736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC1155PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC1155Predicate\",\n \"sourceName\": \"contracts/child/ChildERC1155Predicate.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC1155Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2ERC1155DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC1155Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2ERC1155WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC1155Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC1155Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"withdrawBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612040806100206000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c806397e5230d116100c3578063d41f17711161007c578063d41f1771146102de578063d7c9e3ec14610305578063e0563ab11461032c578063eeb4994514610335578063f645125514610348578063f8c8765e1461036f57600080fd5b806397e5230d1461024d578063b176806514610257578063b5c5f6721461027e578063b68ad1e414610291578063b8cd3ec0146102a4578063c5ac2b1c146102b757600080fd5b806351351d531161011557806351351d53146101d357806355b01e4d146101e15780635ea5df79146101ef5780637efab4f51461020657806386937eb41461022f578063947287cf1461024457600080fd5b8063051eb2e21461015d57806305dc2e8f1461018d57806307b3e252146101a05780631bc114ba146101ae578063284017f5146101c15780633b878c22146101ca575b600080fd5b603554610170906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b603454610170906001600160a01b031681565b6101706004600360981b0181565b603354610170906001600160a01b031681565b61017061202081565b61017061101081565b6101706002600160a01b0381565b6101706004600160991b0181565b6101f861138881565b604051908152602001610184565b610170610214366004611648565b6037602052600090815260409020546001600160a01b031681565b61024261023d3660046116b7565b610382565b005b6101f861520881565b6101f8620249f081565b6101f87f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b61024261028c366004611763565b61039a565b603654610170906001600160a01b031681565b6102426102b2366004611798565b6103ab565b6101f87faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6101f87f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101f87f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61017061203081565b6102426103433660046117de565b6103bd565b6101f87f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61024261037d366004611866565b6105dd565b6103918787878787878761073a565b50505050505050565b6103a683338484610ab9565b505050565b6103b784848484610ab9565b50505050565b6034546001600160a01b0316331461042f5760405162461bcd60e51b815260206004820152602a60248201527f4368696c64455243313135355072656469636174653a204f4e4c595f5354415460448201526922afa922a1a2a4ab22a960b11b60648201526084015b60405180910390fd5b6035546001600160a01b0384811691161461049f5760405162461bcd60e51b815260206004820152602a60248201527f4368696c64455243313135355072656469636174653a204f4e4c595f524f4f546044820152695f50524544494341544560b01b6064820152608401610426565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216104ce6020600084866118c2565b6104d7916118ec565b036104f6576104f16104ec82602081866118c2565b610dce565b6103b7565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d186105256020600084866118c2565b61052e916118ec565b0361053d576104f18282611039565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad61056c6020600084866118c2565b610575916118ec565b03610584576104f182826112a6565b60405162461bcd60e51b815260206004820152602860248201527f4368696c64455243313135355072656469636174653a20494e56414c49445f5360448201526749474e415455524560c01b6064820152608401610426565b336002600160a01b03146106215760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b6044820152606401610426565b600054610100900460ff16158080156106415750600054600160ff909116105b8061065b5750303b15801561065b575060005460ff166001145b6106be5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610426565b6000805460ff1916600117905580156106e1576000805461ff0019166101001790555b6106ed8585858561140e565b8015610733576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b8661074481611504565b6107605760405162461bcd60e51b81526004016104269061190a565b6000886001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c4919061194d565b6001600160a01b038181166000908152603760205260409020549192508a81169116146108035760405162461bcd60e51b81526004016104269061196a565b6001600160a01b038116610819576108196119af565b306001600160a01b0316896001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610861573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610885919061194d565b6001600160a01b03161461089b5761089b6119af565b86851480156108a957508483145b6109035760405162461bcd60e51b815260206004820152602560248201527f4368696c64455243313135355072656469636174653a20494e56414c49445f4c60448201526408a9c8ea8960db1b6064820152608401610426565b604051631ac8311560e21b81526001600160a01b038a1690636b20c454906109379033908a908a908a908a906004016119f7565b6020604051808303816000875af1158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190611a3b565b6109965760405162461bcd60e51b815260040161042690611a5d565b6033546035546040516001600160a01b03928316926316f198319216906109f1907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908f908f908f908f908f908f90602001611ae8565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610a1d929190611b99565b600060405180830381600087803b158015610a3757600080fd5b505af1158015610a4b573d6000803e3d6000fd5b50505050336001600160a01b0316896001600160a01b0316826001600160a01b03167f7a10660242ca367951ff3777cdb3c2a761e3ccad204bac118501e24693f3683d8b8b8b8b8b8b604051610aa696959493929190611bc5565b60405180910390a4505050505050505050565b83610ac381611504565b610adf5760405162461bcd60e51b81526004016104269061190a565b6000856001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b43919061194d565b6001600160a01b03818116600090815260376020526040902054919250878116911614610b825760405162461bcd60e51b81526004016104269061196a565b6001600160a01b038116610b9857610b986119af565b306001600160a01b0316866001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c04919061194d565b6001600160a01b031614610c1a57610c1a6119af565b604051637a94c56560e11b81526001600160a01b0387169063f5298aca90610c4a90339088908890600401611c0e565b6020604051808303816000875af1158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190611a3b565b610ca95760405162461bcd60e51b815260040161042690611a5d565b603354603554604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152898116608083015260a0820189905260c08083018990528351808403909101815260e08301938490526316f1983160e01b909352938416936316f1983193610d3b9391169160e401611b99565b600060405180830381600087803b158015610d5557600080fd5b505af1158015610d69573d6000803e3d6000fd5b50505050846001600160a01b0316866001600160a01b0316826001600160a01b03167f2ca9093e8b5356801039806c6a08003e5b7013fb8ae48f720fc90fc1c1a8bec2338888604051610dbe93929190611c0e565b60405180910390a4505050505050565b600080808080610de086880188611c2f565b6001600160a01b03808616600090815260376020526040902054959a50939850919650945092501680610e255760405162461bcd60e51b81526004016104269061196a565b610e2e81611504565b610e3a57610e3a6119af565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e919061194d565b9050866001600160a01b0316816001600160a01b031614610ec157610ec16119af565b6001600160a01b038116610ed757610ed76119af565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f43919061194d565b6001600160a01b031614610f5957610f596119af565b604051630ab714fb60e11b81526001600160a01b0383169063156e29f690610f8990889088908890600401611c0e565b6020604051808303816000875af1158015610fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcc9190611a3b565b610fe85760405162461bcd60e51b815260040161042690611c8a565b846001600160a01b0316826001600160a01b0316886001600160a01b03167f2930d932c1cccd6add2e0e2d706ede9015db8a194405f2a3e1783703515e104f898888604051610aa693929190611c0e565b60008080808061104b86880188611da0565b6001600160a01b03808616600090815260376020526040902054959b5093995091975095509350169050806110925760405162461bcd60e51b81526004016104269061196a565b61109b81611504565b6110a7576110a76119af565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110b919061194d565b9050866001600160a01b0316816001600160a01b03161461112e5761112e6119af565b6001600160a01b038116611144576111446119af565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561118c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b0919061194d565b6001600160a01b0316146111c6576111c66119af565b604051635712868360e01b81526001600160a01b038316906357128683906111f690889088908890600401611ee5565b6020604051808303816000875af1158015611215573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112399190611a3b565b6112555760405162461bcd60e51b815260040161042690611c8a565b856001600160a01b0316826001600160a01b0316886001600160a01b03167f17304b99f8dfa5a2b8dd5695d82f9947c2abfbc9cb64bab610b9a1a0feadb9a0888888604051610aa693929190611ee5565b6000806112b583850185611f5a565b9093509150506001600160a01b0382166112d1576112d16119af565b6001600160a01b0382811660009081526037602052604090205416156112f9576112f96119af565b6036546040516bffffffffffffffffffffffff19606085901b166020820152600091611349916001600160a01b039091169060340160405160208183030381529060405280519060200120611599565b6001600160a01b038481166000908152603760205260409081902080546001600160a01b0319169284169283179055516379ccf11760e11b81529192509063f399e22e9061139d9086908690600401611b99565b600060405180830381600087803b1580156113b757600080fd5b505af11580156113cb573d6000803e3d6000fd5b50506040516001600160a01b038085169350861691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a35050505050565b6001600160a01b0384161580159061142e57506001600160a01b03831615155b801561144257506001600160a01b03821615155b801561145657506001600160a01b03811615155b6114b45760405162461bcd60e51b815260206004820152602960248201527f4368696c64455243313135355072656469636174653a204241445f494e49544960448201526820a624ad20aa24a7a760b91b6064820152608401610426565b603380546001600160a01b039586166001600160a01b0319918216179091556034805494861694821694909417909355603580549285169284169290921790915560368054919093169116179055565b6000816001600160a01b03163b60000361152057506000919050565b6040516301ffc9a760e01b8152636cdb3d1360e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611587575060408051601f3d908101601f1916820190925261158491810190611a3b565b60015b61159357506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b0381166115935760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b6044820152606401610426565b6001600160a01b038116811461164557600080fd5b50565b60006020828403121561165a57600080fd5b813561166581611630565b9392505050565b60008083601f84011261167e57600080fd5b5081356001600160401b0381111561169557600080fd5b6020830191508360208260051b85010111156116b057600080fd5b9250929050565b60008060008060008060006080888a0312156116d257600080fd5b87356116dd81611630565b965060208801356001600160401b03808211156116f957600080fd5b6117058b838c0161166c565b909850965060408a013591508082111561171e57600080fd5b61172a8b838c0161166c565b909650945060608a013591508082111561174357600080fd5b506117508a828b0161166c565b989b979a50959850939692959293505050565b60008060006060848603121561177857600080fd5b833561178381611630565b95602085013595506040909401359392505050565b600080600080608085870312156117ae57600080fd5b84356117b981611630565b935060208501356117c981611630565b93969395505050506040820135916060013590565b600080600080606085870312156117f457600080fd5b84359350602085013561180681611630565b925060408501356001600160401b038082111561182257600080fd5b818701915087601f83011261183657600080fd5b81358181111561184557600080fd5b88602082850101111561185757600080fd5b95989497505060200194505050565b6000806000806080858703121561187c57600080fd5b843561188781611630565b9350602085013561189781611630565b925060408501356118a781611630565b915060608501356118b781611630565b939692955090935050565b600080858511156118d257600080fd5b838611156118df57600080fd5b5050820193919092039150565b8035602083101561159357600019602084900360031b1b1692915050565b60208082526023908201527f4368696c64455243313135355072656469636174653a204e4f545f434f4e54526040820152621050d560ea1b606082015260800190565b60006020828403121561195f57600080fd5b815161166581611630565b60208082526025908201527f4368696c64455243313135355072656469636174653a20554e4d41505045445f6040820152642a27a5a2a760d91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b038311156119de57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0386168152606060208201819052600090611a1c90830186886119c5565b8281036040840152611a2f8185876119c5565b98975050505050505050565b600060208284031215611a4d57600080fd5b8151801515811461166557600080fd5b60208082526022908201527f4368696c64455243313135355072656469636174653a204255524e5f4641494c604082015261115160f21b606082015260800190565b8183526000602080850194508260005b85811015611add578135611ac281611630565b6001600160a01b031687529582019590820190600101611aaf565b509495945050505050565b8981526001600160a01b0389811660208301528816604082015260c060608201819052600090611b1b908301888a611a9f565b8281036080840152611b2e8187896119c5565b905082810360a0840152611b438185876119c5565b9c9b505050505050505050505050565b6000815180845260005b81811015611b7957602081850181015186830182015201611b5d565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611bbd90830184611b53565b949350505050565b606081526000611bd960608301888a611a9f565b8281036020840152611bec8187896119c5565b90508281036040840152611c018185876119c5565b9998505050505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b600080600080600060a08688031215611c4757600080fd5b8535611c5281611630565b94506020860135611c6281611630565b93506040860135611c7281611630565b94979396509394606081013594506080013592915050565b60208082526022908201527f4368696c64455243313135355072656469636174653a204d494e545f4641494c604082015261115160f21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611d0a57611d0a611ccc565b604052919050565b60006001600160401b03821115611d2b57611d2b611ccc565b5060051b60200190565b600082601f830112611d4657600080fd5b81356020611d5b611d5683611d12565b611ce2565b82815260059290921b84018101918181019086841115611d7a57600080fd5b8286015b84811015611d955780358352918301918301611d7e565b509695505050505050565b60008060008060008060c08789031215611db957600080fd5b86359550602080880135611dcc81611630565b95506040880135611ddc81611630565b945060608801356001600160401b0380821115611df857600080fd5b818a0191508a601f830112611e0c57600080fd5b8135611e1a611d5682611d12565b81815260059190911b8301840190848101908d831115611e3957600080fd5b938501935b82851015611e60578435611e5181611630565b82529385019390850190611e3e565b9750505060808a0135925080831115611e7857600080fd5b611e848b848c01611d35565b945060a08a0135925080831115611e9a57600080fd5b5050611ea889828a01611d35565b9150509295509295509295565b600081518084526020808501945080840160005b83811015611add57815187529582019590820190600101611ec9565b606080825284519082018190526000906020906080840190828801845b82811015611f275781516001600160a01b031684529284019290840190600101611f02565b50505083810382850152611f3b8187611eb5565b9150508281036040840152611f508185611eb5565b9695505050505050565b600080600060608486031215611f6f57600080fd5b83359250602080850135611f8281611630565b925060408501356001600160401b0380821115611f9e57600080fd5b818701915087601f830112611fb257600080fd5b813581811115611fc457611fc4611ccc565b611fd6601f8201601f19168501611ce2565b91508082528884828501011115611fec57600080fd5b8084840185840137600084828401015250809350505050925092509256fea26469706673582212209e5ec9c7e81df1c7e5f79d00b92077b70b934e338148ee522cc77885369daf6d64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101585760003560e01c806397e5230d116100c3578063d41f17711161007c578063d41f1771146102de578063d7c9e3ec14610305578063e0563ab11461032c578063eeb4994514610335578063f645125514610348578063f8c8765e1461036f57600080fd5b806397e5230d1461024d578063b176806514610257578063b5c5f6721461027e578063b68ad1e414610291578063b8cd3ec0146102a4578063c5ac2b1c146102b757600080fd5b806351351d531161011557806351351d53146101d357806355b01e4d146101e15780635ea5df79146101ef5780637efab4f51461020657806386937eb41461022f578063947287cf1461024457600080fd5b8063051eb2e21461015d57806305dc2e8f1461018d57806307b3e252146101a05780631bc114ba146101ae578063284017f5146101c15780633b878c22146101ca575b600080fd5b603554610170906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b603454610170906001600160a01b031681565b6101706004600360981b0181565b603354610170906001600160a01b031681565b61017061202081565b61017061101081565b6101706002600160a01b0381565b6101706004600160991b0181565b6101f861138881565b604051908152602001610184565b610170610214366004611648565b6037602052600090815260409020546001600160a01b031681565b61024261023d3660046116b7565b610382565b005b6101f861520881565b6101f8620249f081565b6101f87f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b61024261028c366004611763565b61039a565b603654610170906001600160a01b031681565b6102426102b2366004611798565b6103ab565b6101f87faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6101f87f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101f87f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61017061203081565b6102426103433660046117de565b6103bd565b6101f87f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61024261037d366004611866565b6105dd565b6103918787878787878761073a565b50505050505050565b6103a683338484610ab9565b505050565b6103b784848484610ab9565b50505050565b6034546001600160a01b0316331461042f5760405162461bcd60e51b815260206004820152602a60248201527f4368696c64455243313135355072656469636174653a204f4e4c595f5354415460448201526922afa922a1a2a4ab22a960b11b60648201526084015b60405180910390fd5b6035546001600160a01b0384811691161461049f5760405162461bcd60e51b815260206004820152602a60248201527f4368696c64455243313135355072656469636174653a204f4e4c595f524f4f546044820152695f50524544494341544560b01b6064820152608401610426565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216104ce6020600084866118c2565b6104d7916118ec565b036104f6576104f16104ec82602081866118c2565b610dce565b6103b7565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d186105256020600084866118c2565b61052e916118ec565b0361053d576104f18282611039565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad61056c6020600084866118c2565b610575916118ec565b03610584576104f182826112a6565b60405162461bcd60e51b815260206004820152602860248201527f4368696c64455243313135355072656469636174653a20494e56414c49445f5360448201526749474e415455524560c01b6064820152608401610426565b336002600160a01b03146106215760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b6044820152606401610426565b600054610100900460ff16158080156106415750600054600160ff909116105b8061065b5750303b15801561065b575060005460ff166001145b6106be5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610426565b6000805460ff1916600117905580156106e1576000805461ff0019166101001790555b6106ed8585858561140e565b8015610733576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b8661074481611504565b6107605760405162461bcd60e51b81526004016104269061190a565b6000886001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107c4919061194d565b6001600160a01b038181166000908152603760205260409020549192508a81169116146108035760405162461bcd60e51b81526004016104269061196a565b6001600160a01b038116610819576108196119af565b306001600160a01b0316896001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610861573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610885919061194d565b6001600160a01b03161461089b5761089b6119af565b86851480156108a957508483145b6109035760405162461bcd60e51b815260206004820152602560248201527f4368696c64455243313135355072656469636174653a20494e56414c49445f4c60448201526408a9c8ea8960db1b6064820152608401610426565b604051631ac8311560e21b81526001600160a01b038a1690636b20c454906109379033908a908a908a908a906004016119f7565b6020604051808303816000875af1158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190611a3b565b6109965760405162461bcd60e51b815260040161042690611a5d565b6033546035546040516001600160a01b03928316926316f198319216906109f1907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908f908f908f908f908f908f90602001611ae8565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610a1d929190611b99565b600060405180830381600087803b158015610a3757600080fd5b505af1158015610a4b573d6000803e3d6000fd5b50505050336001600160a01b0316896001600160a01b0316826001600160a01b03167f7a10660242ca367951ff3777cdb3c2a761e3ccad204bac118501e24693f3683d8b8b8b8b8b8b604051610aa696959493929190611bc5565b60405180910390a4505050505050505050565b83610ac381611504565b610adf5760405162461bcd60e51b81526004016104269061190a565b6000856001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b43919061194d565b6001600160a01b03818116600090815260376020526040902054919250878116911614610b825760405162461bcd60e51b81526004016104269061196a565b6001600160a01b038116610b9857610b986119af565b306001600160a01b0316866001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610be0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c04919061194d565b6001600160a01b031614610c1a57610c1a6119af565b604051637a94c56560e11b81526001600160a01b0387169063f5298aca90610c4a90339088908890600401611c0e565b6020604051808303816000875af1158015610c69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8d9190611a3b565b610ca95760405162461bcd60e51b815260040161042690611a5d565b603354603554604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152898116608083015260a0820189905260c08083018990528351808403909101815260e08301938490526316f1983160e01b909352938416936316f1983193610d3b9391169160e401611b99565b600060405180830381600087803b158015610d5557600080fd5b505af1158015610d69573d6000803e3d6000fd5b50505050846001600160a01b0316866001600160a01b0316826001600160a01b03167f2ca9093e8b5356801039806c6a08003e5b7013fb8ae48f720fc90fc1c1a8bec2338888604051610dbe93929190611c0e565b60405180910390a4505050505050565b600080808080610de086880188611c2f565b6001600160a01b03808616600090815260376020526040902054959a50939850919650945092501680610e255760405162461bcd60e51b81526004016104269061196a565b610e2e81611504565b610e3a57610e3a6119af565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e9e919061194d565b9050866001600160a01b0316816001600160a01b031614610ec157610ec16119af565b6001600160a01b038116610ed757610ed76119af565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f43919061194d565b6001600160a01b031614610f5957610f596119af565b604051630ab714fb60e11b81526001600160a01b0383169063156e29f690610f8990889088908890600401611c0e565b6020604051808303816000875af1158015610fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcc9190611a3b565b610fe85760405162461bcd60e51b815260040161042690611c8a565b846001600160a01b0316826001600160a01b0316886001600160a01b03167f2930d932c1cccd6add2e0e2d706ede9015db8a194405f2a3e1783703515e104f898888604051610aa693929190611c0e565b60008080808061104b86880188611da0565b6001600160a01b03808616600090815260376020526040902054959b5093995091975095509350169050806110925760405162461bcd60e51b81526004016104269061196a565b61109b81611504565b6110a7576110a76119af565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110b919061194d565b9050866001600160a01b0316816001600160a01b03161461112e5761112e6119af565b6001600160a01b038116611144576111446119af565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561118c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b0919061194d565b6001600160a01b0316146111c6576111c66119af565b604051635712868360e01b81526001600160a01b038316906357128683906111f690889088908890600401611ee5565b6020604051808303816000875af1158015611215573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112399190611a3b565b6112555760405162461bcd60e51b815260040161042690611c8a565b856001600160a01b0316826001600160a01b0316886001600160a01b03167f17304b99f8dfa5a2b8dd5695d82f9947c2abfbc9cb64bab610b9a1a0feadb9a0888888604051610aa693929190611ee5565b6000806112b583850185611f5a565b9093509150506001600160a01b0382166112d1576112d16119af565b6001600160a01b0382811660009081526037602052604090205416156112f9576112f96119af565b6036546040516bffffffffffffffffffffffff19606085901b166020820152600091611349916001600160a01b039091169060340160405160208183030381529060405280519060200120611599565b6001600160a01b038481166000908152603760205260409081902080546001600160a01b0319169284169283179055516379ccf11760e11b81529192509063f399e22e9061139d9086908690600401611b99565b600060405180830381600087803b1580156113b757600080fd5b505af11580156113cb573d6000803e3d6000fd5b50506040516001600160a01b038085169350861691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a35050505050565b6001600160a01b0384161580159061142e57506001600160a01b03831615155b801561144257506001600160a01b03821615155b801561145657506001600160a01b03811615155b6114b45760405162461bcd60e51b815260206004820152602960248201527f4368696c64455243313135355072656469636174653a204241445f494e49544960448201526820a624ad20aa24a7a760b91b6064820152608401610426565b603380546001600160a01b039586166001600160a01b0319918216179091556034805494861694821694909417909355603580549285169284169290921790915560368054919093169116179055565b6000816001600160a01b03163b60000361152057506000919050565b6040516301ffc9a760e01b8152636cdb3d1360e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611587575060408051601f3d908101601f1916820190925261158491810190611a3b565b60015b61159357506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b0381166115935760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b6044820152606401610426565b6001600160a01b038116811461164557600080fd5b50565b60006020828403121561165a57600080fd5b813561166581611630565b9392505050565b60008083601f84011261167e57600080fd5b5081356001600160401b0381111561169557600080fd5b6020830191508360208260051b85010111156116b057600080fd5b9250929050565b60008060008060008060006080888a0312156116d257600080fd5b87356116dd81611630565b965060208801356001600160401b03808211156116f957600080fd5b6117058b838c0161166c565b909850965060408a013591508082111561171e57600080fd5b61172a8b838c0161166c565b909650945060608a013591508082111561174357600080fd5b506117508a828b0161166c565b989b979a50959850939692959293505050565b60008060006060848603121561177857600080fd5b833561178381611630565b95602085013595506040909401359392505050565b600080600080608085870312156117ae57600080fd5b84356117b981611630565b935060208501356117c981611630565b93969395505050506040820135916060013590565b600080600080606085870312156117f457600080fd5b84359350602085013561180681611630565b925060408501356001600160401b038082111561182257600080fd5b818701915087601f83011261183657600080fd5b81358181111561184557600080fd5b88602082850101111561185757600080fd5b95989497505060200194505050565b6000806000806080858703121561187c57600080fd5b843561188781611630565b9350602085013561189781611630565b925060408501356118a781611630565b915060608501356118b781611630565b939692955090935050565b600080858511156118d257600080fd5b838611156118df57600080fd5b5050820193919092039150565b8035602083101561159357600019602084900360031b1b1692915050565b60208082526023908201527f4368696c64455243313135355072656469636174653a204e4f545f434f4e54526040820152621050d560ea1b606082015260800190565b60006020828403121561195f57600080fd5b815161166581611630565b60208082526025908201527f4368696c64455243313135355072656469636174653a20554e4d41505045445f6040820152642a27a5a2a760d91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b038311156119de57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b0386168152606060208201819052600090611a1c90830186886119c5565b8281036040840152611a2f8185876119c5565b98975050505050505050565b600060208284031215611a4d57600080fd5b8151801515811461166557600080fd5b60208082526022908201527f4368696c64455243313135355072656469636174653a204255524e5f4641494c604082015261115160f21b606082015260800190565b8183526000602080850194508260005b85811015611add578135611ac281611630565b6001600160a01b031687529582019590820190600101611aaf565b509495945050505050565b8981526001600160a01b0389811660208301528816604082015260c060608201819052600090611b1b908301888a611a9f565b8281036080840152611b2e8187896119c5565b905082810360a0840152611b438185876119c5565b9c9b505050505050505050505050565b6000815180845260005b81811015611b7957602081850181015186830182015201611b5d565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611bbd90830184611b53565b949350505050565b606081526000611bd960608301888a611a9f565b8281036020840152611bec8187896119c5565b90508281036040840152611c018185876119c5565b9998505050505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b600080600080600060a08688031215611c4757600080fd5b8535611c5281611630565b94506020860135611c6281611630565b93506040860135611c7281611630565b94979396509394606081013594506080013592915050565b60208082526022908201527f4368696c64455243313135355072656469636174653a204d494e545f4641494c604082015261115160f21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611d0a57611d0a611ccc565b604052919050565b60006001600160401b03821115611d2b57611d2b611ccc565b5060051b60200190565b600082601f830112611d4657600080fd5b81356020611d5b611d5683611d12565b611ce2565b82815260059290921b84018101918181019086841115611d7a57600080fd5b8286015b84811015611d955780358352918301918301611d7e565b509695505050505050565b60008060008060008060c08789031215611db957600080fd5b86359550602080880135611dcc81611630565b95506040880135611ddc81611630565b945060608801356001600160401b0380821115611df857600080fd5b818a0191508a601f830112611e0c57600080fd5b8135611e1a611d5682611d12565b81815260059190911b8301840190848101908d831115611e3957600080fd5b938501935b82851015611e60578435611e5181611630565b82529385019390850190611e3e565b9750505060808a0135925080831115611e7857600080fd5b611e848b848c01611d35565b945060a08a0135925080831115611e9a57600080fd5b5050611ea889828a01611d35565b9150509295509295509295565b600081518084526020808501945080840160005b83811015611add57815187529582019590820190600101611ec9565b606080825284519082018190526000906020906080840190828801845b82811015611f275781516001600160a01b031684529284019290840190600101611f02565b50505083810382850152611f3b8187611eb5565b9150508281036040840152611f508185611eb5565b9695505050505050565b600080600060608486031215611f6f57600080fd5b83359250602080850135611f8281611630565b925060408501356001600160401b0380821115611f9e57600080fd5b818701915087601f830112611fb257600080fd5b813581811115611fc457611fc4611ccc565b611fd6601f8201601f19168501611ce2565b91508082528884828501011115611fec57600080fd5b8084840185840137600084828401015250809350505050925092509256fea26469706673582212209e5ec9c7e81df1c7e5f79d00b92077b70b934e338148ee522cc77885369daf6d64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildERC1155PredicateACLArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildERC1155PredicateAccessList\",\n \"sourceName\": \"contracts/child/ChildERC1155PredicateAccessList.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"AllowListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"BlockListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC1155Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2ERC1155DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2ERC1155Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2ERC1155WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC1155Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC1155Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC1155Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setAllowList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setBlockList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"withdrawBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506127d8806100206000396000f3fe608060405234801561001057600080fd5b50600436106101b05760003560e01c8063b1768065116100ef578063d7c9e3ec11610092578063d7c9e3ec146103a5578063d8dd1773146103cc578063e0563ab1146103df578063e30c3978146103e8578063eeb49945146103f9578063f2fde38b1461040c578063f64512551461041f578063f8c8765e1461044657600080fd5b8063b1768065146102d1578063b5c5f672146102f8578063b68ad1e41461030b578063b8cd3ec01461031e578063c1225a2014610331578063c5ac2b1c14610344578063c5e4683a1461036b578063d41f17711461037e57600080fd5b80635ea5df79116101575780635ea5df7914610247578063715018a61461025e57806379ba5097146102685780637efab4f51461027057806386937eb41461029a5780638da5cb5b146102ad578063947287cf146102be57806397e5230d146102c757600080fd5b8063051eb2e2146101b557806305dc2e8f146101e557806307b3e252146101f85780631bc114ba14610206578063284017f5146102195780633b878c221461022257806351351d531461022b57806355b01e4d14610239575b600080fd5b60fe546101c8906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fd546101c8906001600160a01b031681565b6101c86004600360981b0181565b60fc546101c8906001600160a01b031681565b6101c861202081565b6101c861101081565b6101c86002600160a01b0381565b6101c86004600160991b0181565b61025061138881565b6040519081526020016101dc565b610266610459565b005b61026661046d565b6101c861027e366004611c73565b610100602052600090815260409020546001600160a01b031681565b6102666102a8366004611ce2565b6104ec565b6033546001600160a01b03166101c8565b61025061520881565b610250620249f081565b6102507f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b610266610306366004611d8e565b61050c565b60ff546101c8906001600160a01b031681565b61026661032c366004611dc3565b610525565b61026661033f366004611e17565b61053f565b6102507faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b610266610379366004611e17565b61058e565b6102507f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102507f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b6102666103da366004611e34565b6105d5565b6101c861203081565b6065546001600160a01b03166101c8565b610266610407366004611eca565b6106f6565b61026661041a366004611c73565b610911565b6102507f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b610266610454366004611f52565b610982565b610461610a7b565b61046b6000610ad5565b565b60655433906001600160a01b031681146104e05760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b6104e981610ad5565b50565b6104f4610aee565b61050387878787878787610af6565b50505050505050565b610514610aee565b61052083338484610e76565b505050565b61052d610aee565b61053984848484610e76565b50505050565b610547610a7b565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b610596610a7b565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b03146105fc5760405163973d02cb60e01b81526004016104d790611fae565b600054610100900460ff161580801561061c5750600054600160ff909116105b806106365750303b158015610636575060005460ff166001145b6106525760405162461bcd60e51b81526004016104d790611fd2565b6000805460ff191660011790558015610675576000805461ff0019166101001790555b6106818888888861118c565b60c9805461ffff191685151561ff00191617610100851515021790556106a682610ad5565b80156106ec576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146107635760405162461bcd60e51b815260206004820152602a60248201527f4368696c64455243313135355072656469636174653a204f4e4c595f5354415460448201526922afa922a1a2a4ab22a960b11b60648201526084016104d7565b60fe546001600160a01b038481169116146107d35760405162461bcd60e51b815260206004820152602a60248201527f4368696c64455243313135355072656469636174653a204f4e4c595f524f4f546044820152695f50524544494341544560b01b60648201526084016104d7565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f821610802602060008486612020565b61080b9161204a565b0361082a576108256108208260208186612020565b611282565b610539565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18610859602060008486612020565b6108629161204a565b036108715761082582826114ee565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6108a0602060008486612020565b6108a99161204a565b036108b857610825828261175c565b60405162461bcd60e51b815260206004820152602860248201527f4368696c64455243313135355072656469636174653a20494e56414c49445f5360448201526749474e415455524560c01b60648201526084016104d7565b610919610a7b565b606580546001600160a01b0383166001600160a01b0319909116811790915561094a6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b336002600160a01b03146109a95760405163973d02cb60e01b81526004016104d790611fae565b600054610100900460ff16158080156109c95750600054600160ff909116105b806109e35750303b1580156109e3575060005460ff166001145b6109ff5760405162461bcd60e51b81526004016104d790611fd2565b6000805460ff191660011790558015610a22576000805461ff0019166101001790555b610a2e8585858561118c565b8015610a74576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6033546001600160a01b0316331461046b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104d7565b606580546001600160a01b03191690556104e9816118c6565b61046b611918565b86610b0081611b32565b610b1c5760405162461bcd60e51b81526004016104d790612068565b6000886001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8091906120ab565b6001600160a01b03818116600090815261010060205260409020549192508a8116911614610bc05760405162461bcd60e51b81526004016104d7906120c8565b6001600160a01b038116610bd657610bd661210d565b306001600160a01b0316896001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4291906120ab565b6001600160a01b031614610c5857610c5861210d565b8685148015610c6657508483145b610cc05760405162461bcd60e51b815260206004820152602560248201527f4368696c64455243313135355072656469636174653a20494e56414c49445f4c60448201526408a9c8ea8960db1b60648201526084016104d7565b604051631ac8311560e21b81526001600160a01b038a1690636b20c45490610cf49033908a908a908a908a90600401612155565b6020604051808303816000875af1158015610d13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d379190612199565b610d535760405162461bcd60e51b81526004016104d7906121b6565b60fc5460fe546040516001600160a01b03928316926316f19831921690610dae907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908f908f908f908f908f908f90602001612241565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610dda9291906122fc565b600060405180830381600087803b158015610df457600080fd5b505af1158015610e08573d6000803e3d6000fd5b50505050336001600160a01b0316896001600160a01b0316826001600160a01b03167f7a10660242ca367951ff3777cdb3c2a761e3ccad204bac118501e24693f3683d8b8b8b8b8b8b604051610e6396959493929190612328565b60405180910390a4505050505050505050565b83610e8081611b32565b610e9c5760405162461bcd60e51b81526004016104d790612068565b6000856001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0091906120ab565b6001600160a01b0381811660009081526101006020526040902054919250878116911614610f405760405162461bcd60e51b81526004016104d7906120c8565b6001600160a01b038116610f5657610f5661210d565b306001600160a01b0316866001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc291906120ab565b6001600160a01b031614610fd857610fd861210d565b604051637a94c56560e11b81526001600160a01b0387169063f5298aca9061100890339088908890600401612371565b6020604051808303816000875af1158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b9190612199565b6110675760405162461bcd60e51b81526004016104d7906121b6565b60fc5460fe54604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152898116608083015260a0820189905260c08083018990528351808403909101815260e08301938490526316f1983160e01b909352938416936316f19831936110f99391169160e4016122fc565b600060405180830381600087803b15801561111357600080fd5b505af1158015611127573d6000803e3d6000fd5b50505050846001600160a01b0316866001600160a01b0316826001600160a01b03167f2ca9093e8b5356801039806c6a08003e5b7013fb8ae48f720fc90fc1c1a8bec233888860405161117c93929190612371565b60405180910390a4505050505050565b6001600160a01b038416158015906111ac57506001600160a01b03831615155b80156111c057506001600160a01b03821615155b80156111d457506001600160a01b03811615155b6112325760405162461bcd60e51b815260206004820152602960248201527f4368696c64455243313135355072656469636174653a204241445f494e49544960448201526820a624ad20aa24a7a760b91b60648201526084016104d7565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b60008080808061129486880188612392565b6001600160a01b0380861660009081526101006020526040902054959a509398509196509450925016806112da5760405162461bcd60e51b81526004016104d7906120c8565b6112e381611b32565b6112ef576112ef61210d565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561132f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135391906120ab565b9050866001600160a01b0316816001600160a01b0316146113765761137661210d565b6001600160a01b03811661138c5761138c61210d565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f891906120ab565b6001600160a01b03161461140e5761140e61210d565b604051630ab714fb60e11b81526001600160a01b0383169063156e29f69061143e90889088908890600401612371565b6020604051808303816000875af115801561145d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114819190612199565b61149d5760405162461bcd60e51b81526004016104d7906123ed565b846001600160a01b0316826001600160a01b0316886001600160a01b03167f2930d932c1cccd6add2e0e2d706ede9015db8a194405f2a3e1783703515e104f898888604051610e6393929190612371565b60008080808061150086880188612503565b6001600160a01b0380861660009081526101006020526040902054959b5093995091975095509350169050806115485760405162461bcd60e51b81526004016104d7906120c8565b61155181611b32565b61155d5761155d61210d565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561159d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c191906120ab565b9050866001600160a01b0316816001600160a01b0316146115e4576115e461210d565b6001600160a01b0381166115fa576115fa61210d565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015611642573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166691906120ab565b6001600160a01b03161461167c5761167c61210d565b604051635712868360e01b81526001600160a01b038316906357128683906116ac90889088908890600401612648565b6020604051808303816000875af11580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190612199565b61170b5760405162461bcd60e51b81526004016104d7906123ed565b856001600160a01b0316826001600160a01b0316886001600160a01b03167f17304b99f8dfa5a2b8dd5695d82f9947c2abfbc9cb64bab610b9a1a0feadb9a0888888604051610e6393929190612648565b60008061176b838501856126bd565b9093509150506001600160a01b0382166117875761178761210d565b6001600160a01b038281166000908152610100602052604090205416156117b0576117b061210d565b60ff546040516bffffffffffffffffffffffff19606085901b166020820152600091611800916001600160a01b039091169060340160405160208183030381529060405280519060200120611bc7565b6001600160a01b03848116600090815261010060205260409081902080546001600160a01b0319169284169283179055516379ccf11760e11b81529192509063f399e22e9061185590869086906004016122fc565b600060405180830381600087803b15801561186f57600080fd5b505af1158015611883573d6000803e3d6000fd5b50506040516001600160a01b038085169350861691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a35050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c95460ff1615611a2357604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161197a919061276d565b6000604051808303818686fa925050503d80600081146119b6576040519150601f19603f3d011682016040523d82523d6000602084013e6119bb565b606091505b50915091508180156119e057506000818060200190518101906119de9190612789565b115b611a205760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b60448201526064016104d7565b50505b60c954610100900460ff161561046b57604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b019161138891611a8a919061276d565b6000604051808303818686fa925050503d8060008114611ac6576040519150601f19603f3d011682016040523d82523d6000602084013e611acb565b606091505b5091509150818015611af1575080806020019051810190611aec9190612789565b600114155b611b2e5760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b60448201526064016104d7565b5050565b6000816001600160a01b03163b600003611b4e57506000919050565b6040516301ffc9a760e01b8152636cdb3d1360e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611bb5575060408051601f3d908101601f19168201909252611bb291810190612199565b60015b611bc157506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116611bc15760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016104d7565b6001600160a01b03811681146104e957600080fd5b600060208284031215611c8557600080fd5b8135611c9081611c5e565b9392505050565b60008083601f840112611ca957600080fd5b5081356001600160401b03811115611cc057600080fd5b6020830191508360208260051b8501011115611cdb57600080fd5b9250929050565b60008060008060008060006080888a031215611cfd57600080fd5b8735611d0881611c5e565b965060208801356001600160401b0380821115611d2457600080fd5b611d308b838c01611c97565b909850965060408a0135915080821115611d4957600080fd5b611d558b838c01611c97565b909650945060608a0135915080821115611d6e57600080fd5b50611d7b8a828b01611c97565b989b979a50959850939692959293505050565b600080600060608486031215611da357600080fd5b8335611dae81611c5e565b95602085013595506040909401359392505050565b60008060008060808587031215611dd957600080fd5b8435611de481611c5e565b93506020850135611df481611c5e565b93969395505050506040820135916060013590565b80151581146104e957600080fd5b600060208284031215611e2957600080fd5b8135611c9081611e09565b600080600080600080600060e0888a031215611e4f57600080fd5b8735611e5a81611c5e565b96506020880135611e6a81611c5e565b95506040880135611e7a81611c5e565b94506060880135611e8a81611c5e565b93506080880135611e9a81611e09565b925060a0880135611eaa81611e09565b915060c0880135611eba81611c5e565b8091505092959891949750929550565b60008060008060608587031215611ee057600080fd5b843593506020850135611ef281611c5e565b925060408501356001600160401b0380821115611f0e57600080fd5b818701915087601f830112611f2257600080fd5b813581811115611f3157600080fd5b886020828501011115611f4357600080fd5b95989497505060200194505050565b60008060008060808587031215611f6857600080fd5b8435611f7381611c5e565b93506020850135611f8381611c5e565b92506040850135611f9381611c5e565b91506060850135611fa381611c5e565b939692955090935050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000808585111561203057600080fd5b8386111561203d57600080fd5b5050820193919092039150565b80356020831015611bc157600019602084900360031b1b1692915050565b60208082526023908201527f4368696c64455243313135355072656469636174653a204e4f545f434f4e54526040820152621050d560ea1b606082015260800190565b6000602082840312156120bd57600080fd5b8151611c9081611c5e565b60208082526025908201527f4368696c64455243313135355072656469636174653a20554e4d41505045445f6040820152642a27a5a2a760d91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b0383111561213c57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038616815260606020820181905260009061217a9083018688612123565b828103604084015261218d818587612123565b98975050505050505050565b6000602082840312156121ab57600080fd5b8151611c9081611e09565b60208082526022908201527f4368696c64455243313135355072656469636174653a204255524e5f4641494c604082015261115160f21b606082015260800190565b8183526000602080850194508260005b8581101561223657813561221b81611c5e565b6001600160a01b031687529582019590820190600101612208565b509495945050505050565b8981526001600160a01b0389811660208301528816604082015260c060608201819052600090612274908301888a6121f8565b8281036080840152612287818789612123565b905082810360a084015261229c818587612123565b9c9b505050505050505050505050565b60005b838110156122c75781810151838201526020016122af565b50506000910152565b600081518084526122e88160208601602086016122ac565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090612320908301846122d0565b949350505050565b60608152600061233c60608301888a6121f8565b828103602084015261234f818789612123565b90508281036040840152612364818587612123565b9998505050505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b600080600080600060a086880312156123aa57600080fd5b85356123b581611c5e565b945060208601356123c581611c5e565b935060408601356123d581611c5e565b94979396509394606081013594506080013592915050565b60208082526022908201527f4368696c64455243313135355072656469636174653a204d494e545f4641494c604082015261115160f21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561246d5761246d61242f565b604052919050565b60006001600160401b0382111561248e5761248e61242f565b5060051b60200190565b600082601f8301126124a957600080fd5b813560206124be6124b983612475565b612445565b82815260059290921b840181019181810190868411156124dd57600080fd5b8286015b848110156124f857803583529183019183016124e1565b509695505050505050565b60008060008060008060c0878903121561251c57600080fd5b8635955060208088013561252f81611c5e565b9550604088013561253f81611c5e565b945060608801356001600160401b038082111561255b57600080fd5b818a0191508a601f83011261256f57600080fd5b813561257d6124b982612475565b81815260059190911b8301840190848101908d83111561259c57600080fd5b938501935b828510156125c35784356125b481611c5e565b825293850193908501906125a1565b9750505060808a01359250808311156125db57600080fd5b6125e78b848c01612498565b945060a08a01359250808311156125fd57600080fd5b505061260b89828a01612498565b9150509295509295509295565b600081518084526020808501945080840160005b838110156122365781518752958201959082019060010161262c565b606080825284519082018190526000906020906080840190828801845b8281101561268a5781516001600160a01b031684529284019290840190600101612665565b5050508381038285015261269e8187612618565b91505082810360408401526126b38185612618565b9695505050505050565b6000806000606084860312156126d257600080fd5b833592506020808501356126e581611c5e565b925060408501356001600160401b038082111561270157600080fd5b818701915087601f83011261271557600080fd5b8135818111156127275761272761242f565b612739601f8201601f19168501612445565b9150808252888482850101111561274f57600080fd5b80848401858401376000848284010152508093505050509250925092565b6000825161277f8184602087016122ac565b9190910192915050565b60006020828403121561279b57600080fd5b505191905056fea26469706673582212203a31f88332ccb328b6f5d85c4214142bbdd2dfd217a190599f91a6ebebb2eda764736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101b05760003560e01c8063b1768065116100ef578063d7c9e3ec11610092578063d7c9e3ec146103a5578063d8dd1773146103cc578063e0563ab1146103df578063e30c3978146103e8578063eeb49945146103f9578063f2fde38b1461040c578063f64512551461041f578063f8c8765e1461044657600080fd5b8063b1768065146102d1578063b5c5f672146102f8578063b68ad1e41461030b578063b8cd3ec01461031e578063c1225a2014610331578063c5ac2b1c14610344578063c5e4683a1461036b578063d41f17711461037e57600080fd5b80635ea5df79116101575780635ea5df7914610247578063715018a61461025e57806379ba5097146102685780637efab4f51461027057806386937eb41461029a5780638da5cb5b146102ad578063947287cf146102be57806397e5230d146102c757600080fd5b8063051eb2e2146101b557806305dc2e8f146101e557806307b3e252146101f85780631bc114ba14610206578063284017f5146102195780633b878c221461022257806351351d531461022b57806355b01e4d14610239575b600080fd5b60fe546101c8906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b60fd546101c8906001600160a01b031681565b6101c86004600360981b0181565b60fc546101c8906001600160a01b031681565b6101c861202081565b6101c861101081565b6101c86002600160a01b0381565b6101c86004600160991b0181565b61025061138881565b6040519081526020016101dc565b610266610459565b005b61026661046d565b6101c861027e366004611c73565b610100602052600090815260409020546001600160a01b031681565b6102666102a8366004611ce2565b6104ec565b6033546001600160a01b03166101c8565b61025061520881565b610250620249f081565b6102507f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b610266610306366004611d8e565b61050c565b60ff546101c8906001600160a01b031681565b61026661032c366004611dc3565b610525565b61026661033f366004611e17565b61053f565b6102507faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b610266610379366004611e17565b61058e565b6102507f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102507f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b6102666103da366004611e34565b6105d5565b6101c861203081565b6065546001600160a01b03166101c8565b610266610407366004611eca565b6106f6565b61026661041a366004611c73565b610911565b6102507f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b610266610454366004611f52565b610982565b610461610a7b565b61046b6000610ad5565b565b60655433906001600160a01b031681146104e05760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b6104e981610ad5565b50565b6104f4610aee565b61050387878787878787610af6565b50505050505050565b610514610aee565b61052083338484610e76565b505050565b61052d610aee565b61053984848484610e76565b50505050565b610547610a7b565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b610596610a7b565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b03146105fc5760405163973d02cb60e01b81526004016104d790611fae565b600054610100900460ff161580801561061c5750600054600160ff909116105b806106365750303b158015610636575060005460ff166001145b6106525760405162461bcd60e51b81526004016104d790611fd2565b6000805460ff191660011790558015610675576000805461ff0019166101001790555b6106818888888861118c565b60c9805461ffff191685151561ff00191617610100851515021790556106a682610ad5565b80156106ec576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146107635760405162461bcd60e51b815260206004820152602a60248201527f4368696c64455243313135355072656469636174653a204f4e4c595f5354415460448201526922afa922a1a2a4ab22a960b11b60648201526084016104d7565b60fe546001600160a01b038481169116146107d35760405162461bcd60e51b815260206004820152602a60248201527f4368696c64455243313135355072656469636174653a204f4e4c595f524f4f546044820152695f50524544494341544560b01b60648201526084016104d7565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f821610802602060008486612020565b61080b9161204a565b0361082a576108256108208260208186612020565b611282565b610539565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18610859602060008486612020565b6108629161204a565b036108715761082582826114ee565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6108a0602060008486612020565b6108a99161204a565b036108b857610825828261175c565b60405162461bcd60e51b815260206004820152602860248201527f4368696c64455243313135355072656469636174653a20494e56414c49445f5360448201526749474e415455524560c01b60648201526084016104d7565b610919610a7b565b606580546001600160a01b0383166001600160a01b0319909116811790915561094a6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b336002600160a01b03146109a95760405163973d02cb60e01b81526004016104d790611fae565b600054610100900460ff16158080156109c95750600054600160ff909116105b806109e35750303b1580156109e3575060005460ff166001145b6109ff5760405162461bcd60e51b81526004016104d790611fd2565b6000805460ff191660011790558015610a22576000805461ff0019166101001790555b610a2e8585858561118c565b8015610a74576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6033546001600160a01b0316331461046b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016104d7565b606580546001600160a01b03191690556104e9816118c6565b61046b611918565b86610b0081611b32565b610b1c5760405162461bcd60e51b81526004016104d790612068565b6000886001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8091906120ab565b6001600160a01b03818116600090815261010060205260409020549192508a8116911614610bc05760405162461bcd60e51b81526004016104d7906120c8565b6001600160a01b038116610bd657610bd661210d565b306001600160a01b0316896001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4291906120ab565b6001600160a01b031614610c5857610c5861210d565b8685148015610c6657508483145b610cc05760405162461bcd60e51b815260206004820152602560248201527f4368696c64455243313135355072656469636174653a20494e56414c49445f4c60448201526408a9c8ea8960db1b60648201526084016104d7565b604051631ac8311560e21b81526001600160a01b038a1690636b20c45490610cf49033908a908a908a908a90600401612155565b6020604051808303816000875af1158015610d13573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d379190612199565b610d535760405162461bcd60e51b81526004016104d7906121b6565b60fc5460fe546040516001600160a01b03928316926316f19831921690610dae907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908f908f908f908f908f908f90602001612241565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610dda9291906122fc565b600060405180830381600087803b158015610df457600080fd5b505af1158015610e08573d6000803e3d6000fd5b50505050336001600160a01b0316896001600160a01b0316826001600160a01b03167f7a10660242ca367951ff3777cdb3c2a761e3ccad204bac118501e24693f3683d8b8b8b8b8b8b604051610e6396959493929190612328565b60405180910390a4505050505050505050565b83610e8081611b32565b610e9c5760405162461bcd60e51b81526004016104d790612068565b6000856001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610edc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f0091906120ab565b6001600160a01b0381811660009081526101006020526040902054919250878116911614610f405760405162461bcd60e51b81526004016104d7906120c8565b6001600160a01b038116610f5657610f5661210d565b306001600160a01b0316866001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fc291906120ab565b6001600160a01b031614610fd857610fd861210d565b604051637a94c56560e11b81526001600160a01b0387169063f5298aca9061100890339088908890600401612371565b6020604051808303816000875af1158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b9190612199565b6110675760405162461bcd60e51b81526004016104d7906121b6565b60fc5460fe54604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152898116608083015260a0820189905260c08083018990528351808403909101815260e08301938490526316f1983160e01b909352938416936316f19831936110f99391169160e4016122fc565b600060405180830381600087803b15801561111357600080fd5b505af1158015611127573d6000803e3d6000fd5b50505050846001600160a01b0316866001600160a01b0316826001600160a01b03167f2ca9093e8b5356801039806c6a08003e5b7013fb8ae48f720fc90fc1c1a8bec233888860405161117c93929190612371565b60405180910390a4505050505050565b6001600160a01b038416158015906111ac57506001600160a01b03831615155b80156111c057506001600160a01b03821615155b80156111d457506001600160a01b03811615155b6112325760405162461bcd60e51b815260206004820152602960248201527f4368696c64455243313135355072656469636174653a204241445f494e49544960448201526820a624ad20aa24a7a760b91b60648201526084016104d7565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b60008080808061129486880188612392565b6001600160a01b0380861660009081526101006020526040902054959a509398509196509450925016806112da5760405162461bcd60e51b81526004016104d7906120c8565b6112e381611b32565b6112ef576112ef61210d565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561132f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135391906120ab565b9050866001600160a01b0316816001600160a01b0316146113765761137661210d565b6001600160a01b03811661138c5761138c61210d565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f891906120ab565b6001600160a01b03161461140e5761140e61210d565b604051630ab714fb60e11b81526001600160a01b0383169063156e29f69061143e90889088908890600401612371565b6020604051808303816000875af115801561145d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114819190612199565b61149d5760405162461bcd60e51b81526004016104d7906123ed565b846001600160a01b0316826001600160a01b0316886001600160a01b03167f2930d932c1cccd6add2e0e2d706ede9015db8a194405f2a3e1783703515e104f898888604051610e6393929190612371565b60008080808061150086880188612503565b6001600160a01b0380861660009081526101006020526040902054959b5093995091975095509350169050806115485760405162461bcd60e51b81526004016104d7906120c8565b61155181611b32565b61155d5761155d61210d565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561159d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115c191906120ab565b9050866001600160a01b0316816001600160a01b0316146115e4576115e461210d565b6001600160a01b0381166115fa576115fa61210d565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015611642573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166691906120ab565b6001600160a01b03161461167c5761167c61210d565b604051635712868360e01b81526001600160a01b038316906357128683906116ac90889088908890600401612648565b6020604051808303816000875af11580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190612199565b61170b5760405162461bcd60e51b81526004016104d7906123ed565b856001600160a01b0316826001600160a01b0316886001600160a01b03167f17304b99f8dfa5a2b8dd5695d82f9947c2abfbc9cb64bab610b9a1a0feadb9a0888888604051610e6393929190612648565b60008061176b838501856126bd565b9093509150506001600160a01b0382166117875761178761210d565b6001600160a01b038281166000908152610100602052604090205416156117b0576117b061210d565b60ff546040516bffffffffffffffffffffffff19606085901b166020820152600091611800916001600160a01b039091169060340160405160208183030381529060405280519060200120611bc7565b6001600160a01b03848116600090815261010060205260409081902080546001600160a01b0319169284169283179055516379ccf11760e11b81529192509063f399e22e9061185590869086906004016122fc565b600060405180830381600087803b15801561186f57600080fd5b505af1158015611883573d6000803e3d6000fd5b50506040516001600160a01b038085169350861691507f46bd56f98e1b14fd35691959270a6e1edf7cb8fcd489e0f9dda89e46c0d1ff0d90600090a35050505050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c95460ff1615611a2357604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161197a919061276d565b6000604051808303818686fa925050503d80600081146119b6576040519150601f19603f3d011682016040523d82523d6000602084013e6119bb565b606091505b50915091508180156119e057506000818060200190518101906119de9190612789565b115b611a205760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b60448201526064016104d7565b50505b60c954610100900460ff161561046b57604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b019161138891611a8a919061276d565b6000604051808303818686fa925050503d8060008114611ac6576040519150601f19603f3d011682016040523d82523d6000602084013e611acb565b606091505b5091509150818015611af1575080806020019051810190611aec9190612789565b600114155b611b2e5760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b60448201526064016104d7565b5050565b6000816001600160a01b03163b600003611b4e57506000919050565b6040516301ffc9a760e01b8152636cdb3d1360e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611bb5575060408051601f3d908101601f19168201909252611bb291810190612199565b60015b611bc157506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116611bc15760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016104d7565b6001600160a01b03811681146104e957600080fd5b600060208284031215611c8557600080fd5b8135611c9081611c5e565b9392505050565b60008083601f840112611ca957600080fd5b5081356001600160401b03811115611cc057600080fd5b6020830191508360208260051b8501011115611cdb57600080fd5b9250929050565b60008060008060008060006080888a031215611cfd57600080fd5b8735611d0881611c5e565b965060208801356001600160401b0380821115611d2457600080fd5b611d308b838c01611c97565b909850965060408a0135915080821115611d4957600080fd5b611d558b838c01611c97565b909650945060608a0135915080821115611d6e57600080fd5b50611d7b8a828b01611c97565b989b979a50959850939692959293505050565b600080600060608486031215611da357600080fd5b8335611dae81611c5e565b95602085013595506040909401359392505050565b60008060008060808587031215611dd957600080fd5b8435611de481611c5e565b93506020850135611df481611c5e565b93969395505050506040820135916060013590565b80151581146104e957600080fd5b600060208284031215611e2957600080fd5b8135611c9081611e09565b600080600080600080600060e0888a031215611e4f57600080fd5b8735611e5a81611c5e565b96506020880135611e6a81611c5e565b95506040880135611e7a81611c5e565b94506060880135611e8a81611c5e565b93506080880135611e9a81611e09565b925060a0880135611eaa81611e09565b915060c0880135611eba81611c5e565b8091505092959891949750929550565b60008060008060608587031215611ee057600080fd5b843593506020850135611ef281611c5e565b925060408501356001600160401b0380821115611f0e57600080fd5b818701915087601f830112611f2257600080fd5b813581811115611f3157600080fd5b886020828501011115611f4357600080fd5b95989497505060200194505050565b60008060008060808587031215611f6857600080fd5b8435611f7381611c5e565b93506020850135611f8381611c5e565b92506040850135611f9381611c5e565b91506060850135611fa381611c5e565b939692955090935050565b6020808252600a908201526914d654d5115350d0531360b21b604082015260600190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6000808585111561203057600080fd5b8386111561203d57600080fd5b5050820193919092039150565b80356020831015611bc157600019602084900360031b1b1692915050565b60208082526023908201527f4368696c64455243313135355072656469636174653a204e4f545f434f4e54526040820152621050d560ea1b606082015260800190565b6000602082840312156120bd57600080fd5b8151611c9081611c5e565b60208082526025908201527f4368696c64455243313135355072656469636174653a20554e4d41505045445f6040820152642a27a5a2a760d91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b0383111561213c57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038616815260606020820181905260009061217a9083018688612123565b828103604084015261218d818587612123565b98975050505050505050565b6000602082840312156121ab57600080fd5b8151611c9081611e09565b60208082526022908201527f4368696c64455243313135355072656469636174653a204255524e5f4641494c604082015261115160f21b606082015260800190565b8183526000602080850194508260005b8581101561223657813561221b81611c5e565b6001600160a01b031687529582019590820190600101612208565b509495945050505050565b8981526001600160a01b0389811660208301528816604082015260c060608201819052600090612274908301888a6121f8565b8281036080840152612287818789612123565b905082810360a084015261229c818587612123565b9c9b505050505050505050505050565b60005b838110156122c75781810151838201526020016122af565b50506000910152565b600081518084526122e88160208601602086016122ac565b601f01601f19169290920160200192915050565b6001600160a01b0383168152604060208201819052600090612320908301846122d0565b949350505050565b60608152600061233c60608301888a6121f8565b828103602084015261234f818789612123565b90508281036040840152612364818587612123565b9998505050505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b600080600080600060a086880312156123aa57600080fd5b85356123b581611c5e565b945060208601356123c581611c5e565b935060408601356123d581611c5e565b94979396509394606081013594506080013592915050565b60208082526022908201527f4368696c64455243313135355072656469636174653a204d494e545f4641494c604082015261115160f21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561246d5761246d61242f565b604052919050565b60006001600160401b0382111561248e5761248e61242f565b5060051b60200190565b600082601f8301126124a957600080fd5b813560206124be6124b983612475565b612445565b82815260059290921b840181019181810190868411156124dd57600080fd5b8286015b848110156124f857803583529183019183016124e1565b509695505050505050565b60008060008060008060c0878903121561251c57600080fd5b8635955060208088013561252f81611c5e565b9550604088013561253f81611c5e565b945060608801356001600160401b038082111561255b57600080fd5b818a0191508a601f83011261256f57600080fd5b813561257d6124b982612475565b81815260059190911b8301840190848101908d83111561259c57600080fd5b938501935b828510156125c35784356125b481611c5e565b825293850193908501906125a1565b9750505060808a01359250808311156125db57600080fd5b6125e78b848c01612498565b945060a08a01359250808311156125fd57600080fd5b505061260b89828a01612498565b9150509295509295509295565b600081518084526020808501945080840160005b838110156122365781518752958201959082019060010161262c565b606080825284519082018190526000906020906080840190828801845b8281101561268a5781516001600160a01b031684529284019290840190600101612665565b5050508381038285015261269e8187612618565b91505082810360408401526126b38185612618565b9695505050505050565b6000806000606084860312156126d257600080fd5b833592506020808501356126e581611c5e565b925060408501356001600160401b038082111561270157600080fd5b818701915087601f83011261271557600080fd5b8135818111156127275761272761242f565b612739601f8201601f19168501612445565b9150808252888482850101111561274f57600080fd5b80848401858401376000848284010152508093505050509250925092565b6000825161277f8184602087016122ac565b9190910192915050565b60006020828403121561279b57600080fd5b505191905056fea26469706673582212203a31f88332ccb328b6f5d85c4214142bbdd2dfd217a190599f91a6ebebb2eda764736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RootMintableERC1155PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootMintableERC1155Predicate\",\n \"sourceName\": \"contracts/child/RootMintableERC1155Predicate.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC1155Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2MintableERC1155DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC1155Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2MintableERC1155WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC1155Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"depositBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC1155Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC1155BatchReceived\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC1155Received\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611c01806100206000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063b68ad1e4116100ad578063eeb4994511610071578063eeb49945146102fe578063f23a6e6114610311578063f4a120f714610330578063f645125514610343578063f8c8765e1461036a57600080fd5b8063b68ad1e41461023e578063bc197c8114610251578063c5ac2b1c14610289578063d41f1771146102b0578063d7c9e3ec146102d757600080fd5b80634c4c45de116100f45780634c4c45de146101a7578063654715e6146101ba5780637efab4f5146101cd578063a78e111c146101f6578063b17680651461020957600080fd5b806301ffc9a71461012657806305dc2e8f1461014e5780630efe6a8b146101795780631bc114ba1461018e575b600080fd5b610139610134366004611182565b61037d565b60405190151581526020015b60405180910390f35b600154610161906001600160a01b031681565b6040516001600160a01b039091168152602001610145565b61018c6101873660046111cb565b6103b4565b005b600054610161906201000090046001600160a01b031681565b61018c6101b536600461124b565b6103c5565b600254610161906001600160a01b031681565b6101616101db3660046112f7565b6004602052600090815260409020546001600160a01b031681565b61018c610204366004611314565b61043f565b6102307f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610145565b600354610161906001600160a01b031681565b61027061025f3660046114a6565b63bc197c8160e01b95945050505050565b6040516001600160e01b03199091168152602001610145565b6102307faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6102307f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102307f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61018c61030c366004611553565b610451565b61027061031f3660046115db565b63f23a6e6160e01b95945050505050565b61016161033e3660046112f7565b610629565b6102307f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61018c610378366004611643565b610944565b60006001600160e01b03198216630271189760e51b14806103ae57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6103c083338484610a5d565b505050565b84831480156103d357508481145b6104275760405162461bcd60e51b815260206004820152602c6024820152600080516020611bac83398151915260448201526b0ac82989288be988a9c8ea8960a31b60648201526084015b60405180910390fd5b61043687878787878787610bf3565b50505050505050565b61044b84848484610a5d565b50505050565b6001546001600160a01b031633146104c55760405162461bcd60e51b815260206004820152603160248201527f526f6f744d696e7461626c65455243313135355072656469636174653a204f4e604482015270262cafa9aa20aa22afa922a1a2a4ab22a960791b606482015260840161041e565b6002546001600160a01b0384811691161461053d5760405162461bcd60e51b815260206004820152603260248201527f526f6f744d696e7461626c65455243313135355072656469636174653a204f4e6044820152714c595f4348494c445f50524544494341544560701b606482015260840161041e565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286961056c60206000848661169f565b610575916116c9565b036105945761058f61058a826020818661169f565b610dd3565b61044b565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed26105c360206000848661169f565b6105cc916116c9565b036105db5761058f8282610ed2565b60405162461bcd60e51b815260206004820152602f6024820152600080516020611bac83398151915260448201526e56414c49445f5349474e415455524560881b606482015260840161041e565b60006001600160a01b0382166106835760405162461bcd60e51b815260206004820152602b6024820152600080516020611bac83398151915260448201526a2b20a624a22faa27a5a2a760a91b606482015260840161041e565b6001600160a01b0382811660009081526004602052604090205416156107005760405162461bcd60e51b815260206004820152602c60248201527f526f6f744d696e7461626c65455243313135355072656469636174653a20414c60448201526b149150511657d3505414115160a21b606482015260840161041e565b6002546003546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b03928316926107aa921690603401604051602081830303815290604052805190602001208360405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b03848116600081815260046020818152604080842080546001600160a01b031916968816969096179095558451908101855282815293516303a24d0760e21b8152908101919091529294509091630e89341c90602401600060405180830381865afa92505050801561084557506040513d6000823e601f3d908101601f19168201604052610842919081019061170b565b60015b1561084d5790505b600060029054906101000a90046001600160a01b03166001600160a01b03166316f19831837f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad87856040516020016108a7939291906117ad565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016108d39291906117d7565b600060405180830381600087803b1580156108ed57600080fd5b505af1158015610901573d6000803e3d6000fd5b50506040516001600160a01b038087169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a35050919050565b600054610100900460ff16158080156109645750600054600160ff909116105b8061097e5750303b15801561097e575060005460ff166001145b6109e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161041e565b6000805460ff191660011790558015610a04576000805461ff0019166101001790555b610a1085858585611033565b8015610a56576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6000610a688561113b565b604051637921219560e11b81529091506001600160a01b0386169063f242432a90610a9d903390309088908890600401611803565b600060405180830381600087803b158015610ab757600080fd5b505af1158015610acb573d6000803e3d6000fd5b5050600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038b8116828401523360608301528a8116608083015260a082018a905260c08083018a90528351808403909101815260e08301938490526316f1983160e01b90935262010000909404841695506316f198319450610b68939092169160e4016117d7565b600060405180830381600087803b158015610b8257600080fd5b505af1158015610b96573d6000803e3d6000fd5b505060408051338152602081018790529081018590526001600160a01b03808816935084811692508816907fe6f1fb6bb1930a5d4b997d56e0a4a8cb6f3f941f0d5391f63c1f6914ee01e0b89060600160405180910390a4610a56565b6000610bfe8861113b565b905060005b84811015610caa57886001600160a01b031663f242432a3330898986818110610c2e57610c2e61183b565b90506020020135888887818110610c4757610c4761183b565b905060200201356040518563ffffffff1660e01b8152600401610c6d9493929190611803565b600060405180830381600087803b158015610c8757600080fd5b505af1158015610c9b573d6000803e3d6000fd5b50505050806001019050610c03565b506000546002546040516001600160a01b03620100009093048316926316f19831921690610d0c907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908d9033908e908e908e908e908e908e906020016118cc565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610d389291906117d7565b600060405180830381600087803b158015610d5257600080fd5b505af1158015610d66573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316896001600160a01b03167fa7d9cd27143f817fe006011faf3c04351f70f75cd30e7b21405817f2f670041e8a8a8a8a8a8a604051610dc196959493929190611937565b60405180910390a45050505050505050565b600080808080610de586880188611980565b6001600160a01b03808616600090815260046020526040902054959a50939850919650945092501680610e1a57610e1a6119db565b604051637921219560e11b81526001600160a01b0387169063f242432a90610e4c903090889088908890600401611803565b600060405180830381600087803b158015610e6657600080fd5b505af1158015610e7a573d6000803e3d6000fd5b5050604080516001600160a01b0389811682526020820188905291810186905281881693508482169250908916907f52cdfbe452878311d3237a4c20a951600d8e3a4fe6691d967d33788dc12d19c690606001610dc1565b600080808080610ee4868801886119f1565b6001600160a01b03808616600090815260046020526040902054959b509399509197509550935016905080610f1b57610f1b6119db565b60005b8351811015610fe157866001600160a01b031663f242432a30878481518110610f4957610f4961183b565b6020026020010151878581518110610f6357610f6361183b565b6020026020010151878681518110610f7d57610f7d61183b565b60200260200101516040518563ffffffff1660e01b8152600401610fa49493929190611803565b600060405180830381600087803b158015610fbe57600080fd5b505af1158015610fd2573d6000803e3d6000fd5b50505050806001019050610f1e565b50846001600160a01b0316816001600160a01b0316876001600160a01b03167f52733a40a0466155541c2fc4044165dd37a3db116bc834bab2f020665e90fd20878787604051610dc193929190611b36565b6001600160a01b0384161580159061105357506001600160a01b03831615155b801561106757506001600160a01b03821615155b801561107b57506001600160a01b03811615155b6110e05760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c65455243313135355072656469636174653a20424160448201526f222fa4a724aa24a0a624ad20aa24a7a760811b606482015260840161041e565b600080546001600160a01b03958616620100000262010000600160b01b0319909116179055600180549385166001600160a01b0319948516179055600280549285169284169290921790915560038054919093169116179055565b6001600160a01b0380821660009081526004602052604090205416806111675761116482610629565b90505b6001600160a01b03811661117d5761117d6119db565b919050565b60006020828403121561119457600080fd5b81356001600160e01b0319811681146111ac57600080fd5b9392505050565b6001600160a01b03811681146111c857600080fd5b50565b6000806000606084860312156111e057600080fd5b83356111eb816111b3565b95602085013595506040909401359392505050565b60008083601f84011261121257600080fd5b5081356001600160401b0381111561122957600080fd5b6020830191508360208260051b850101111561124457600080fd5b9250929050565b60008060008060008060006080888a03121561126657600080fd5b8735611271816111b3565b965060208801356001600160401b038082111561128d57600080fd5b6112998b838c01611200565b909850965060408a01359150808211156112b257600080fd5b6112be8b838c01611200565b909650945060608a01359150808211156112d757600080fd5b506112e48a828b01611200565b989b979a50959850939692959293505050565b60006020828403121561130957600080fd5b81356111ac816111b3565b6000806000806080858703121561132a57600080fd5b8435611335816111b3565b93506020850135611345816111b3565b93969395505050506040820135916060013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156113985761139861135a565b604052919050565b60006001600160401b038211156113b9576113b961135a565b5060051b60200190565b600082601f8301126113d457600080fd5b813560206113e96113e4836113a0565b611370565b82815260059290921b8401810191818101908684111561140857600080fd5b8286015b84811015611423578035835291830191830161140c565b509695505050505050565b60006001600160401b038211156114475761144761135a565b50601f01601f191660200190565b600082601f83011261146657600080fd5b81356114746113e48261142e565b81815284602083860101111561148957600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156114be57600080fd5b85356114c9816111b3565b945060208601356114d9816111b3565b935060408601356001600160401b03808211156114f557600080fd5b61150189838a016113c3565b9450606088013591508082111561151757600080fd5b61152389838a016113c3565b9350608088013591508082111561153957600080fd5b5061154688828901611455565b9150509295509295909350565b6000806000806060858703121561156957600080fd5b84359350602085013561157b816111b3565b925060408501356001600160401b038082111561159757600080fd5b818701915087601f8301126115ab57600080fd5b8135818111156115ba57600080fd5b8860208285010111156115cc57600080fd5b95989497505060200194505050565b600080600080600060a086880312156115f357600080fd5b85356115fe816111b3565b9450602086013561160e816111b3565b9350604086013592506060860135915060808601356001600160401b0381111561163757600080fd5b61154688828901611455565b6000806000806080858703121561165957600080fd5b8435611664816111b3565b93506020850135611674816111b3565b92506040850135611684816111b3565b91506060850135611694816111b3565b939692955090935050565b600080858511156116af57600080fd5b838611156116bc57600080fd5b5050820193919092039150565b803560208310156103ae57600019602084900360031b1b1692915050565b60005b838110156117025781810151838201526020016116ea565b50506000910152565b60006020828403121561171d57600080fd5b81516001600160401b0381111561173357600080fd5b8201601f8101841361174457600080fd5b80516117526113e48261142e565b81815285602083850101111561176757600080fd5b6117788260208301602086016116e7565b95945050505050565b600081518084526117998160208601602086016116e7565b601f01601f19169290920160200192915050565b8381526001600160a01b038316602082015260606040820181905260009061177890830184611781565b6001600160a01b03831681526040602082018190526000906117fb90830184611781565b949350505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052603260045260246000fd5b8183526000602080850194508260005b8581101561188f578135611874816111b3565b6001600160a01b031687529582019590820190600101611861565b509495945050505050565b81835260006001600160fb1b038311156118b357600080fd5b8260051b80836020870137939093016020019392505050565b8981526001600160a01b0389811660208301528816604082015260c0606082018190526000906118ff908301888a611851565b828103608084015261191281878961189a565b905082810360a084015261192781858761189a565b9c9b505050505050505050505050565b60608152600061194b60608301888a611851565b828103602084015261195e81878961189a565b9050828103604084015261197381858761189a565b9998505050505050505050565b600080600080600060a0868803121561199857600080fd5b85356119a3816111b3565b945060208601356119b3816111b3565b935060408601356119c3816111b3565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052600160045260246000fd5b60008060008060008060c08789031215611a0a57600080fd5b86359550602080880135611a1d816111b3565b95506040880135611a2d816111b3565b945060608801356001600160401b0380821115611a4957600080fd5b818a0191508a601f830112611a5d57600080fd5b8135611a6b6113e4826113a0565b81815260059190911b8301840190848101908d831115611a8a57600080fd5b938501935b82851015611ab1578435611aa2816111b3565b82529385019390850190611a8f565b9750505060808a0135925080831115611ac957600080fd5b611ad58b848c016113c3565b945060a08a0135925080831115611aeb57600080fd5b5050611af989828a016113c3565b9150509295509295509295565b600081518084526020808501945080840160005b8381101561188f57815187529582019590820190600101611b1a565b606080825284519082018190526000906020906080840190828801845b82811015611b785781516001600160a01b031684529284019290840190600101611b53565b50505083810382850152611b8c8187611b06565b9150508281036040840152611ba18185611b06565b969550505050505056fe526f6f744d696e7461626c65455243313135355072656469636174653a20494ea2646970667358221220041be07610d061e0ff1ac458a256b6bf3a4db091a6a166a3ae82fa20cc5953f564736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063b68ad1e4116100ad578063eeb4994511610071578063eeb49945146102fe578063f23a6e6114610311578063f4a120f714610330578063f645125514610343578063f8c8765e1461036a57600080fd5b8063b68ad1e41461023e578063bc197c8114610251578063c5ac2b1c14610289578063d41f1771146102b0578063d7c9e3ec146102d757600080fd5b80634c4c45de116100f45780634c4c45de146101a7578063654715e6146101ba5780637efab4f5146101cd578063a78e111c146101f6578063b17680651461020957600080fd5b806301ffc9a71461012657806305dc2e8f1461014e5780630efe6a8b146101795780631bc114ba1461018e575b600080fd5b610139610134366004611182565b61037d565b60405190151581526020015b60405180910390f35b600154610161906001600160a01b031681565b6040516001600160a01b039091168152602001610145565b61018c6101873660046111cb565b6103b4565b005b600054610161906201000090046001600160a01b031681565b61018c6101b536600461124b565b6103c5565b600254610161906001600160a01b031681565b6101616101db3660046112f7565b6004602052600090815260409020546001600160a01b031681565b61018c610204366004611314565b61043f565b6102307f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610145565b600354610161906001600160a01b031681565b61027061025f3660046114a6565b63bc197c8160e01b95945050505050565b6040516001600160e01b03199091168152602001610145565b6102307faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6102307f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102307f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61018c61030c366004611553565b610451565b61027061031f3660046115db565b63f23a6e6160e01b95945050505050565b61016161033e3660046112f7565b610629565b6102307f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61018c610378366004611643565b610944565b60006001600160e01b03198216630271189760e51b14806103ae57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6103c083338484610a5d565b505050565b84831480156103d357508481145b6104275760405162461bcd60e51b815260206004820152602c6024820152600080516020611bac83398151915260448201526b0ac82989288be988a9c8ea8960a31b60648201526084015b60405180910390fd5b61043687878787878787610bf3565b50505050505050565b61044b84848484610a5d565b50505050565b6001546001600160a01b031633146104c55760405162461bcd60e51b815260206004820152603160248201527f526f6f744d696e7461626c65455243313135355072656469636174653a204f4e604482015270262cafa9aa20aa22afa922a1a2a4ab22a960791b606482015260840161041e565b6002546001600160a01b0384811691161461053d5760405162461bcd60e51b815260206004820152603260248201527f526f6f744d696e7461626c65455243313135355072656469636174653a204f4e6044820152714c595f4348494c445f50524544494341544560701b606482015260840161041e565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286961056c60206000848661169f565b610575916116c9565b036105945761058f61058a826020818661169f565b610dd3565b61044b565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed26105c360206000848661169f565b6105cc916116c9565b036105db5761058f8282610ed2565b60405162461bcd60e51b815260206004820152602f6024820152600080516020611bac83398151915260448201526e56414c49445f5349474e415455524560881b606482015260840161041e565b60006001600160a01b0382166106835760405162461bcd60e51b815260206004820152602b6024820152600080516020611bac83398151915260448201526a2b20a624a22faa27a5a2a760a91b606482015260840161041e565b6001600160a01b0382811660009081526004602052604090205416156107005760405162461bcd60e51b815260206004820152602c60248201527f526f6f744d696e7461626c65455243313135355072656469636174653a20414c60448201526b149150511657d3505414115160a21b606482015260840161041e565b6002546003546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b03928316926107aa921690603401604051602081830303815290604052805190602001208360405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b03848116600081815260046020818152604080842080546001600160a01b031916968816969096179095558451908101855282815293516303a24d0760e21b8152908101919091529294509091630e89341c90602401600060405180830381865afa92505050801561084557506040513d6000823e601f3d908101601f19168201604052610842919081019061170b565b60015b1561084d5790505b600060029054906101000a90046001600160a01b03166001600160a01b03166316f19831837f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad87856040516020016108a7939291906117ad565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016108d39291906117d7565b600060405180830381600087803b1580156108ed57600080fd5b505af1158015610901573d6000803e3d6000fd5b50506040516001600160a01b038087169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a35050919050565b600054610100900460ff16158080156109645750600054600160ff909116105b8061097e5750303b15801561097e575060005460ff166001145b6109e15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161041e565b6000805460ff191660011790558015610a04576000805461ff0019166101001790555b610a1085858585611033565b8015610a56576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6000610a688561113b565b604051637921219560e11b81529091506001600160a01b0386169063f242432a90610a9d903390309088908890600401611803565b600060405180830381600087803b158015610ab757600080fd5b505af1158015610acb573d6000803e3d6000fd5b5050600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038b8116828401523360608301528a8116608083015260a082018a905260c08083018a90528351808403909101815260e08301938490526316f1983160e01b90935262010000909404841695506316f198319450610b68939092169160e4016117d7565b600060405180830381600087803b158015610b8257600080fd5b505af1158015610b96573d6000803e3d6000fd5b505060408051338152602081018790529081018590526001600160a01b03808816935084811692508816907fe6f1fb6bb1930a5d4b997d56e0a4a8cb6f3f941f0d5391f63c1f6914ee01e0b89060600160405180910390a4610a56565b6000610bfe8861113b565b905060005b84811015610caa57886001600160a01b031663f242432a3330898986818110610c2e57610c2e61183b565b90506020020135888887818110610c4757610c4761183b565b905060200201356040518563ffffffff1660e01b8152600401610c6d9493929190611803565b600060405180830381600087803b158015610c8757600080fd5b505af1158015610c9b573d6000803e3d6000fd5b50505050806001019050610c03565b506000546002546040516001600160a01b03620100009093048316926316f19831921690610d0c907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908d9033908e908e908e908e908e908e906020016118cc565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610d389291906117d7565b600060405180830381600087803b158015610d5257600080fd5b505af1158015610d66573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316896001600160a01b03167fa7d9cd27143f817fe006011faf3c04351f70f75cd30e7b21405817f2f670041e8a8a8a8a8a8a604051610dc196959493929190611937565b60405180910390a45050505050505050565b600080808080610de586880188611980565b6001600160a01b03808616600090815260046020526040902054959a50939850919650945092501680610e1a57610e1a6119db565b604051637921219560e11b81526001600160a01b0387169063f242432a90610e4c903090889088908890600401611803565b600060405180830381600087803b158015610e6657600080fd5b505af1158015610e7a573d6000803e3d6000fd5b5050604080516001600160a01b0389811682526020820188905291810186905281881693508482169250908916907f52cdfbe452878311d3237a4c20a951600d8e3a4fe6691d967d33788dc12d19c690606001610dc1565b600080808080610ee4868801886119f1565b6001600160a01b03808616600090815260046020526040902054959b509399509197509550935016905080610f1b57610f1b6119db565b60005b8351811015610fe157866001600160a01b031663f242432a30878481518110610f4957610f4961183b565b6020026020010151878581518110610f6357610f6361183b565b6020026020010151878681518110610f7d57610f7d61183b565b60200260200101516040518563ffffffff1660e01b8152600401610fa49493929190611803565b600060405180830381600087803b158015610fbe57600080fd5b505af1158015610fd2573d6000803e3d6000fd5b50505050806001019050610f1e565b50846001600160a01b0316816001600160a01b0316876001600160a01b03167f52733a40a0466155541c2fc4044165dd37a3db116bc834bab2f020665e90fd20878787604051610dc193929190611b36565b6001600160a01b0384161580159061105357506001600160a01b03831615155b801561106757506001600160a01b03821615155b801561107b57506001600160a01b03811615155b6110e05760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c65455243313135355072656469636174653a20424160448201526f222fa4a724aa24a0a624ad20aa24a7a760811b606482015260840161041e565b600080546001600160a01b03958616620100000262010000600160b01b0319909116179055600180549385166001600160a01b0319948516179055600280549285169284169290921790915560038054919093169116179055565b6001600160a01b0380821660009081526004602052604090205416806111675761116482610629565b90505b6001600160a01b03811661117d5761117d6119db565b919050565b60006020828403121561119457600080fd5b81356001600160e01b0319811681146111ac57600080fd5b9392505050565b6001600160a01b03811681146111c857600080fd5b50565b6000806000606084860312156111e057600080fd5b83356111eb816111b3565b95602085013595506040909401359392505050565b60008083601f84011261121257600080fd5b5081356001600160401b0381111561122957600080fd5b6020830191508360208260051b850101111561124457600080fd5b9250929050565b60008060008060008060006080888a03121561126657600080fd5b8735611271816111b3565b965060208801356001600160401b038082111561128d57600080fd5b6112998b838c01611200565b909850965060408a01359150808211156112b257600080fd5b6112be8b838c01611200565b909650945060608a01359150808211156112d757600080fd5b506112e48a828b01611200565b989b979a50959850939692959293505050565b60006020828403121561130957600080fd5b81356111ac816111b3565b6000806000806080858703121561132a57600080fd5b8435611335816111b3565b93506020850135611345816111b3565b93969395505050506040820135916060013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156113985761139861135a565b604052919050565b60006001600160401b038211156113b9576113b961135a565b5060051b60200190565b600082601f8301126113d457600080fd5b813560206113e96113e4836113a0565b611370565b82815260059290921b8401810191818101908684111561140857600080fd5b8286015b84811015611423578035835291830191830161140c565b509695505050505050565b60006001600160401b038211156114475761144761135a565b50601f01601f191660200190565b600082601f83011261146657600080fd5b81356114746113e48261142e565b81815284602083860101111561148957600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156114be57600080fd5b85356114c9816111b3565b945060208601356114d9816111b3565b935060408601356001600160401b03808211156114f557600080fd5b61150189838a016113c3565b9450606088013591508082111561151757600080fd5b61152389838a016113c3565b9350608088013591508082111561153957600080fd5b5061154688828901611455565b9150509295509295909350565b6000806000806060858703121561156957600080fd5b84359350602085013561157b816111b3565b925060408501356001600160401b038082111561159757600080fd5b818701915087601f8301126115ab57600080fd5b8135818111156115ba57600080fd5b8860208285010111156115cc57600080fd5b95989497505060200194505050565b600080600080600060a086880312156115f357600080fd5b85356115fe816111b3565b9450602086013561160e816111b3565b9350604086013592506060860135915060808601356001600160401b0381111561163757600080fd5b61154688828901611455565b6000806000806080858703121561165957600080fd5b8435611664816111b3565b93506020850135611674816111b3565b92506040850135611684816111b3565b91506060850135611694816111b3565b939692955090935050565b600080858511156116af57600080fd5b838611156116bc57600080fd5b5050820193919092039150565b803560208310156103ae57600019602084900360031b1b1692915050565b60005b838110156117025781810151838201526020016116ea565b50506000910152565b60006020828403121561171d57600080fd5b81516001600160401b0381111561173357600080fd5b8201601f8101841361174457600080fd5b80516117526113e48261142e565b81815285602083850101111561176757600080fd5b6117788260208301602086016116e7565b95945050505050565b600081518084526117998160208601602086016116e7565b601f01601f19169290920160200192915050565b8381526001600160a01b038316602082015260606040820181905260009061177890830184611781565b6001600160a01b03831681526040602082018190526000906117fb90830184611781565b949350505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052603260045260246000fd5b8183526000602080850194508260005b8581101561188f578135611874816111b3565b6001600160a01b031687529582019590820190600101611861565b509495945050505050565b81835260006001600160fb1b038311156118b357600080fd5b8260051b80836020870137939093016020019392505050565b8981526001600160a01b0389811660208301528816604082015260c0606082018190526000906118ff908301888a611851565b828103608084015261191281878961189a565b905082810360a084015261192781858761189a565b9c9b505050505050505050505050565b60608152600061194b60608301888a611851565b828103602084015261195e81878961189a565b9050828103604084015261197381858761189a565b9998505050505050505050565b600080600080600060a0868803121561199857600080fd5b85356119a3816111b3565b945060208601356119b3816111b3565b935060408601356119c3816111b3565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052600160045260246000fd5b60008060008060008060c08789031215611a0a57600080fd5b86359550602080880135611a1d816111b3565b95506040880135611a2d816111b3565b945060608801356001600160401b0380821115611a4957600080fd5b818a0191508a601f830112611a5d57600080fd5b8135611a6b6113e4826113a0565b81815260059190911b8301840190848101908d831115611a8a57600080fd5b938501935b82851015611ab1578435611aa2816111b3565b82529385019390850190611a8f565b9750505060808a0135925080831115611ac957600080fd5b611ad58b848c016113c3565b945060a08a0135925080831115611aeb57600080fd5b5050611af989828a016113c3565b9150509295509295509295565b600081518084526020808501945080840160005b8381101561188f57815187529582019590820190600101611b1a565b606080825284519082018190526000906020906080840190828801845b82811015611b785781516001600160a01b031684529284019290840190600101611b53565b50505083810382850152611b8c8187611b06565b9150508281036040840152611ba18185611b06565b969550505050505056fe526f6f744d696e7461626c65455243313135355072656469636174653a20494ea2646970667358221220041be07610d061e0ff1ac458a256b6bf3a4db091a6a166a3ae82fa20cc5953f564736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RootMintableERC1155PredicateACLArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootMintableERC1155PredicateAccessList\",\n \"sourceName\": \"contracts/child/RootMintableERC1155PredicateAccessList.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"AllowListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"block\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"status\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"BlockListUsageSet\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC1155Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2MintableERC1155DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"L2MintableERC1155Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"L2MintableERC1155WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"L2MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC1155Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"depositBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC1155Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newL2StateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC1155Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"l2StateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC1155BatchReceived\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC1155Received\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseAllowList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setAllowList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"newUseBlockList\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setBlockList\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateReceiver\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612480806100206000396000f3fe608060405234801561001057600080fd5b506004361061021c5760003560e01c8063a78e111c11610125578063d8dd1773116100ad578063f23a6e611161007c578063f23a6e61146104d3578063f2fde38b146104f2578063f4a120f714610505578063f645125514610518578063f8c8765e1461053f57600080fd5b8063d8dd177314610493578063e0563ab1146104a6578063e30c3978146104af578063eeb49945146104c057600080fd5b8063c1225a20116100f4578063c1225a20146103f8578063c5ac2b1c1461040b578063c5e4683a14610432578063d41f177114610445578063d7c9e3ec1461046c57600080fd5b8063a78e111c14610373578063b176806514610386578063b68ad1e4146103ad578063bc197c81146103c057600080fd5b806355b01e4d116101a857806379ba50971161017757806379ba50971461031d5780637efab4f5146103255780638da5cb5b1461034f578063947287cf1461036057806397e5230d1461036957600080fd5b806355b01e4d146102dd5780635ea5df79146102eb578063654715e614610302578063715018a61461031557600080fd5b80631bc114ba116101ef5780631bc114ba14610297578063284017f5146102aa5780633b878c22146102b35780634c4c45de146102bc57806351351d53146102cf57600080fd5b806301ffc9a71461022157806305dc2e8f1461024957806307b3e252146102745780630efe6a8b14610282575b600080fd5b61023461022f3660046118c4565b610552565b60405190151581526020015b60405180910390f35b60fd5461025c906001600160a01b031681565b6040516001600160a01b039091168152602001610240565b61025c6004600360981b0181565b61029561029036600461190a565b610589565b005b60fc5461025c906001600160a01b031681565b61025c61202081565b61025c61101081565b6102956102ca36600461198a565b61059a565b61025c6002600160a01b0381565b61025c6004600160991b0181565b6102f461138881565b604051908152602001610240565b60fe5461025c906001600160a01b031681565b610295610614565b610295610628565b61025c610333366004611a36565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b031661025c565b6102f461520881565b6102f4620249f081565b610295610381366004611a53565b6106a2565b6102f47f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff5461025c906001600160a01b031681565b6103df6103ce366004611be5565b63bc197c8160e01b95945050505050565b6040516001600160e01b03199091168152602001610240565b610295610406366004611ca2565b6106b4565b6102f47faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b610295610440366004611ca2565b610703565b6102f47f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102f47f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b6102956104a1366004611cbd565b61074a565b61025c61203081565b6065546001600160a01b031661025c565b6102956104ce366004611d4f565b610888565b6103df6104e1366004611dd7565b63f23a6e6160e01b95945050505050565b610295610500366004611a36565b610a60565b61025c610513366004611a36565b610ad1565b6102f47f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61029561054d366004611e3f565b610de1565b60006001600160e01b03198216630271189760e51b148061058357506301ffc9a760e01b6001600160e01b03198316145b92915050565b61059583338484610eb3565b505050565b84831480156105a857508481145b6105fc5760405162461bcd60e51b815260206004820152602c602482015260008051602061242b83398151915260448201526b0ac82989288be988a9c8ea8960a31b60648201526084015b60405180910390fd5b61060b8787878787878761104b565b50505050505050565b61061c611228565b6106266000611282565b565b60655433906001600160a01b031681146106965760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016105f3565b61069f81611282565b50565b6106ae84848484610eb3565b50505050565b6106bc611228565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b61070b611228565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b031461078e5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064016105f3565b600054610100900460ff16158080156107ae5750600054600160ff909116105b806107c85750303b1580156107c8575060005460ff166001145b6107e45760405162461bcd60e51b81526004016105f390611e9b565b6000805460ff191660011790558015610807576000805461ff0019166101001790555b6108138888888861129b565b60c9805461ffff191685151561ff001916176101008515150217905561083882611282565b801561087e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146108fc5760405162461bcd60e51b815260206004820152603160248201527f526f6f744d696e7461626c65455243313135355072656469636174653a204f4e604482015270262cafa9aa20aa22afa922a1a2a4ab22a960791b60648201526084016105f3565b60fe546001600160a01b038481169116146109745760405162461bcd60e51b815260206004820152603260248201527f526f6f744d696e7461626c65455243313135355072656469636174653a204f4e6044820152714c595f4348494c445f50524544494341544560701b60648201526084016105f3565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696109a3602060008486611ee9565b6109ac91611f13565b036109cb576109c66109c18260208186611ee9565b611398565b6106ae565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed26109fa602060008486611ee9565b610a0391611f13565b03610a12576109c682826114a6565b60405162461bcd60e51b815260206004820152602f602482015260008051602061242b83398151915260448201526e56414c49445f5349474e415455524560881b60648201526084016105f3565b610a68611228565b606580546001600160a01b0383166001600160a01b03199091168117909155610a996033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60006001600160a01b038216610b2b5760405162461bcd60e51b815260206004820152602b602482015260008051602061242b83398151915260448201526a2b20a624a22faa27a5a2a760a91b60648201526084016105f3565b6001600160a01b03828116600090815261010060205260409020541615610ba95760405162461bcd60e51b815260206004820152602c60248201527f526f6f744d696e7461626c65455243313135355072656469636174653a20414c60448201526b149150511657d3505414115160a21b60648201526084016105f3565b60fe5460ff546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b0392831692610c53921690603401604051602081830303815290604052805190602001208360405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b0384811660008181526101006020908152604080832080546001600160a01b031916958716959095179094558351908101845281815292516303a24d0760e21b815260048101919091529294509091630e89341c90602401600060405180830381865afa925050508015610cf057506040513d6000823e601f3d908101601f19168201604052610ced9190810190611f55565b60015b15610cf85790505b60fc546040516001600160a01b03909116906316f19831908490610d44907f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad9089908790602001611ff7565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610d70929190612021565b600060405180830381600087803b158015610d8a57600080fd5b505af1158015610d9e573d6000803e3d6000fd5b50506040516001600160a01b038087169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a35050919050565b600054610100900460ff1615808015610e015750600054600160ff909116105b80610e1b5750303b158015610e1b575060005460ff166001145b610e375760405162461bcd60e51b81526004016105f390611e9b565b6000805460ff191660011790558015610e5a576000805461ff0019166101001790555b610e668585858561129b565b8015610eac576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b610ebb611608565b6000610ec685611610565b604051637921219560e11b81529091506001600160a01b0386169063f242432a90610efb90339030908890889060040161204d565b600060405180830381600087803b158015610f1557600080fd5b505af1158015610f29573d6000803e3d6000fd5b505060fc5460fe54604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038b8116828401523360608301528a8116608083015260a082018a905260c08083018a90528351808403909101815260e08301938490526316f1983160e01b90935293841695506316f198319450610fc0939092169160e401612021565b600060405180830381600087803b158015610fda57600080fd5b505af1158015610fee573d6000803e3d6000fd5b505060408051338152602081018790529081018590526001600160a01b03808816935084811692508816907fe6f1fb6bb1930a5d4b997d56e0a4a8cb6f3f941f0d5391f63c1f6914ee01e0b89060600160405180910390a4610eac565b611053611608565b600061105e88611610565b905060005b8481101561110a57886001600160a01b031663f242432a333089898681811061108e5761108e612085565b905060200201358888878181106110a7576110a7612085565b905060200201356040518563ffffffff1660e01b81526004016110cd949392919061204d565b600060405180830381600087803b1580156110e757600080fd5b505af11580156110fb573d6000803e3d6000fd5b50505050806001019050611063565b5060fc5460fe546040516001600160a01b03928316926316f19831921690611166907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908d9033908e908e908e908e908e908e90602001612116565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611192929190612021565b600060405180830381600087803b1580156111ac57600080fd5b505af11580156111c0573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316896001600160a01b03167fa7d9cd27143f817fe006011faf3c04351f70f75cd30e7b21405817f2f670041e8a8a8a8a8a8a60405161121b96959493929190612181565b60405180910390a461087e565b6033546001600160a01b031633146106265760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105f3565b606580546001600160a01b031916905561069f81611658565b6001600160a01b038416158015906112bb57506001600160a01b03831615155b80156112cf57506001600160a01b03821615155b80156112e357506001600160a01b03811615155b6113485760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c65455243313135355072656469636174653a20424160448201526f222fa4a724aa24a0a624ad20aa24a7a760811b60648201526084016105f3565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b6000808080806113aa868801886121ca565b6001600160a01b0380861660009081526101006020526040902054959a509398509196509450925016806113e0576113e0612225565b604051637921219560e11b81526001600160a01b0387169063f242432a9061141290309088908890889060040161204d565b600060405180830381600087803b15801561142c57600080fd5b505af1158015611440573d6000803e3d6000fd5b5050604080516001600160a01b0389811682526020820188905291810186905281881693508482169250908916907f52cdfbe452878311d3237a4c20a951600d8e3a4fe6691d967d33788dc12d19c6906060015b60405180910390a45050505050505050565b6000808080806114b88688018861223b565b6001600160a01b0380861660009081526101006020526040902054959b5093995091975095509350169050806114f0576114f0612225565b60005b83518110156115b657866001600160a01b031663f242432a3087848151811061151e5761151e612085565b602002602001015187858151811061153857611538612085565b602002602001015187868151811061155257611552612085565b60200260200101516040518563ffffffff1660e01b8152600401611579949392919061204d565b600060405180830381600087803b15801561159357600080fd5b505af11580156115a7573d6000803e3d6000fd5b505050508060010190506114f3565b50846001600160a01b0316816001600160a01b0316876001600160a01b03167f52733a40a0466155541c2fc4044165dd37a3db116bc834bab2f020665e90fd2087878760405161149493929190612380565b6106266116aa565b6001600160a01b0380821660009081526101006020526040902054168061163d5761163a82610ad1565b90505b6001600160a01b03811661165357611653612225565b919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c95460ff16156117b557604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161170c91906123f5565b6000604051808303818686fa925050503d8060008114611748576040519150601f19603f3d011682016040523d82523d6000602084013e61174d565b606091505b509150915081801561177257506000818060200190518101906117709190612411565b115b6117b25760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b60448201526064016105f3565b50505b60c954610100900460ff161561062657604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b01916113889161181c91906123f5565b6000604051808303818686fa925050503d8060008114611858576040519150601f19603f3d011682016040523d82523d6000602084013e61185d565b606091505b509150915081801561188357508080602001905181019061187e9190612411565b600114155b6118c05760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b60448201526064016105f3565b5050565b6000602082840312156118d657600080fd5b81356001600160e01b0319811681146118ee57600080fd5b9392505050565b6001600160a01b038116811461069f57600080fd5b60008060006060848603121561191f57600080fd5b833561192a816118f5565b95602085013595506040909401359392505050565b60008083601f84011261195157600080fd5b5081356001600160401b0381111561196857600080fd5b6020830191508360208260051b850101111561198357600080fd5b9250929050565b60008060008060008060006080888a0312156119a557600080fd5b87356119b0816118f5565b965060208801356001600160401b03808211156119cc57600080fd5b6119d88b838c0161193f565b909850965060408a01359150808211156119f157600080fd5b6119fd8b838c0161193f565b909650945060608a0135915080821115611a1657600080fd5b50611a238a828b0161193f565b989b979a50959850939692959293505050565b600060208284031215611a4857600080fd5b81356118ee816118f5565b60008060008060808587031215611a6957600080fd5b8435611a74816118f5565b93506020850135611a84816118f5565b93969395505050506040820135916060013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611ad757611ad7611a99565b604052919050565b60006001600160401b03821115611af857611af8611a99565b5060051b60200190565b600082601f830112611b1357600080fd5b81356020611b28611b2383611adf565b611aaf565b82815260059290921b84018101918181019086841115611b4757600080fd5b8286015b84811015611b625780358352918301918301611b4b565b509695505050505050565b60006001600160401b03821115611b8657611b86611a99565b50601f01601f191660200190565b600082601f830112611ba557600080fd5b8135611bb3611b2382611b6d565b818152846020838601011115611bc857600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215611bfd57600080fd5b8535611c08816118f5565b94506020860135611c18816118f5565b935060408601356001600160401b0380821115611c3457600080fd5b611c4089838a01611b02565b94506060880135915080821115611c5657600080fd5b611c6289838a01611b02565b93506080880135915080821115611c7857600080fd5b50611c8588828901611b94565b9150509295509295909350565b8035801515811461165357600080fd5b600060208284031215611cb457600080fd5b6118ee82611c92565b600080600080600080600060e0888a031215611cd857600080fd5b8735611ce3816118f5565b96506020880135611cf3816118f5565b95506040880135611d03816118f5565b94506060880135611d13816118f5565b9350611d2160808901611c92565b9250611d2f60a08901611c92565b915060c0880135611d3f816118f5565b8091505092959891949750929550565b60008060008060608587031215611d6557600080fd5b843593506020850135611d77816118f5565b925060408501356001600160401b0380821115611d9357600080fd5b818701915087601f830112611da757600080fd5b813581811115611db657600080fd5b886020828501011115611dc857600080fd5b95989497505060200194505050565b600080600080600060a08688031215611def57600080fd5b8535611dfa816118f5565b94506020860135611e0a816118f5565b9350604086013592506060860135915060808601356001600160401b03811115611e3357600080fd5b611c8588828901611b94565b60008060008060808587031215611e5557600080fd5b8435611e60816118f5565b93506020850135611e70816118f5565b92506040850135611e80816118f5565b91506060850135611e90816118f5565b939692955090935050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008085851115611ef957600080fd5b83861115611f0657600080fd5b5050820193919092039150565b8035602083101561058357600019602084900360031b1b1692915050565b60005b83811015611f4c578181015183820152602001611f34565b50506000910152565b600060208284031215611f6757600080fd5b81516001600160401b03811115611f7d57600080fd5b8201601f81018413611f8e57600080fd5b8051611f9c611b2382611b6d565b818152856020838501011115611fb157600080fd5b611fc2826020830160208601611f31565b95945050505050565b60008151808452611fe3816020860160208601611f31565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090611fc290830184611fcb565b6001600160a01b038316815260406020820181905260009061204590830184611fcb565b949350505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052603260045260246000fd5b8183526000602080850194508260005b858110156120d95781356120be816118f5565b6001600160a01b0316875295820195908201906001016120ab565b509495945050505050565b81835260006001600160fb1b038311156120fd57600080fd5b8260051b80836020870137939093016020019392505050565b8981526001600160a01b0389811660208301528816604082015260c060608201819052600090612149908301888a61209b565b828103608084015261215c8187896120e4565b905082810360a08401526121718185876120e4565b9c9b505050505050505050505050565b60608152600061219560608301888a61209b565b82810360208401526121a88187896120e4565b905082810360408401526121bd8185876120e4565b9998505050505050505050565b600080600080600060a086880312156121e257600080fd5b85356121ed816118f5565b945060208601356121fd816118f5565b9350604086013561220d816118f5565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052600160045260246000fd5b60008060008060008060c0878903121561225457600080fd5b86359550602080880135612267816118f5565b95506040880135612277816118f5565b945060608801356001600160401b038082111561229357600080fd5b818a0191508a601f8301126122a757600080fd5b81356122b5611b2382611adf565b81815260059190911b8301840190848101908d8311156122d457600080fd5b938501935b828510156122fb5784356122ec816118f5565b825293850193908501906122d9565b9750505060808a013592508083111561231357600080fd5b61231f8b848c01611b02565b945060a08a013592508083111561233557600080fd5b505061234389828a01611b02565b9150509295509295509295565b600081518084526020808501945080840160005b838110156120d957815187529582019590820190600101612364565b606080825284519082018190526000906020906080840190828801845b828110156123c25781516001600160a01b03168452928401929084019060010161239d565b505050838103828501526123d68187612350565b91505082810360408401526123eb8185612350565b9695505050505050565b60008251612407818460208701611f31565b9190910192915050565b60006020828403121561242357600080fd5b505191905056fe526f6f744d696e7461626c65455243313135355072656469636174653a20494ea2646970667358221220965ae0a80f2c0fef1177c03f5c9015e9cb11183a07cb364acd575c0d5b96410c64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061021c5760003560e01c8063a78e111c11610125578063d8dd1773116100ad578063f23a6e611161007c578063f23a6e61146104d3578063f2fde38b146104f2578063f4a120f714610505578063f645125514610518578063f8c8765e1461053f57600080fd5b8063d8dd177314610493578063e0563ab1146104a6578063e30c3978146104af578063eeb49945146104c057600080fd5b8063c1225a20116100f4578063c1225a20146103f8578063c5ac2b1c1461040b578063c5e4683a14610432578063d41f177114610445578063d7c9e3ec1461046c57600080fd5b8063a78e111c14610373578063b176806514610386578063b68ad1e4146103ad578063bc197c81146103c057600080fd5b806355b01e4d116101a857806379ba50971161017757806379ba50971461031d5780637efab4f5146103255780638da5cb5b1461034f578063947287cf1461036057806397e5230d1461036957600080fd5b806355b01e4d146102dd5780635ea5df79146102eb578063654715e614610302578063715018a61461031557600080fd5b80631bc114ba116101ef5780631bc114ba14610297578063284017f5146102aa5780633b878c22146102b35780634c4c45de146102bc57806351351d53146102cf57600080fd5b806301ffc9a71461022157806305dc2e8f1461024957806307b3e252146102745780630efe6a8b14610282575b600080fd5b61023461022f3660046118c4565b610552565b60405190151581526020015b60405180910390f35b60fd5461025c906001600160a01b031681565b6040516001600160a01b039091168152602001610240565b61025c6004600360981b0181565b61029561029036600461190a565b610589565b005b60fc5461025c906001600160a01b031681565b61025c61202081565b61025c61101081565b6102956102ca36600461198a565b61059a565b61025c6002600160a01b0381565b61025c6004600160991b0181565b6102f461138881565b604051908152602001610240565b60fe5461025c906001600160a01b031681565b610295610614565b610295610628565b61025c610333366004611a36565b610100602052600090815260409020546001600160a01b031681565b6033546001600160a01b031661025c565b6102f461520881565b6102f4620249f081565b610295610381366004611a53565b6106a2565b6102f47f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60ff5461025c906001600160a01b031681565b6103df6103ce366004611be5565b63bc197c8160e01b95945050505050565b6040516001600160e01b03199091168152602001610240565b610295610406366004611ca2565b6106b4565b6102f47faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b610295610440366004611ca2565b610703565b6102f47f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102f47f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b6102956104a1366004611cbd565b61074a565b61025c61203081565b6065546001600160a01b031661025c565b6102956104ce366004611d4f565b610888565b6103df6104e1366004611dd7565b63f23a6e6160e01b95945050505050565b610295610500366004611a36565b610a60565b61025c610513366004611a36565b610ad1565b6102f47f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61029561054d366004611e3f565b610de1565b60006001600160e01b03198216630271189760e51b148061058357506301ffc9a760e01b6001600160e01b03198316145b92915050565b61059583338484610eb3565b505050565b84831480156105a857508481145b6105fc5760405162461bcd60e51b815260206004820152602c602482015260008051602061242b83398151915260448201526b0ac82989288be988a9c8ea8960a31b60648201526084015b60405180910390fd5b61060b8787878787878761104b565b50505050505050565b61061c611228565b6106266000611282565b565b60655433906001600160a01b031681146106965760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016105f3565b61069f81611282565b50565b6106ae84848484610eb3565b50505050565b6106bc611228565b60c9805461ff0019166101008315159081029190911790915560405143907f61d574757cde41a357d030b39b2705796ccd699578037ab9a1cfd8117d82bf8690600090a350565b61070b611228565b60c9805460ff191682151590811790915560405143907fe0a0f0fa52db091cb71c202d80420311430ce1ae2e7794149877b6720ce8bf0b90600090a350565b336002600160a01b031461078e5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064016105f3565b600054610100900460ff16158080156107ae5750600054600160ff909116105b806107c85750303b1580156107c8575060005460ff166001145b6107e45760405162461bcd60e51b81526004016105f390611e9b565b6000805460ff191660011790558015610807576000805461ff0019166101001790555b6108138888888861129b565b60c9805461ffff191685151561ff001916176101008515150217905561083882611282565b801561087e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60fd546001600160a01b031633146108fc5760405162461bcd60e51b815260206004820152603160248201527f526f6f744d696e7461626c65455243313135355072656469636174653a204f4e604482015270262cafa9aa20aa22afa922a1a2a4ab22a960791b60648201526084016105f3565b60fe546001600160a01b038481169116146109745760405162461bcd60e51b815260206004820152603260248201527f526f6f744d696e7461626c65455243313135355072656469636174653a204f4e6044820152714c595f4348494c445f50524544494341544560701b60648201526084016105f3565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696109a3602060008486611ee9565b6109ac91611f13565b036109cb576109c66109c18260208186611ee9565b611398565b6106ae565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed26109fa602060008486611ee9565b610a0391611f13565b03610a12576109c682826114a6565b60405162461bcd60e51b815260206004820152602f602482015260008051602061242b83398151915260448201526e56414c49445f5349474e415455524560881b60648201526084016105f3565b610a68611228565b606580546001600160a01b0383166001600160a01b03199091168117909155610a996033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60006001600160a01b038216610b2b5760405162461bcd60e51b815260206004820152602b602482015260008051602061242b83398151915260448201526a2b20a624a22faa27a5a2a760a91b60648201526084016105f3565b6001600160a01b03828116600090815261010060205260409020541615610ba95760405162461bcd60e51b815260206004820152602c60248201527f526f6f744d696e7461626c65455243313135355072656469636174653a20414c60448201526b149150511657d3505414115160a21b60648201526084016105f3565b60fe5460ff546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b0392831692610c53921690603401604051602081830303815290604052805190602001208360405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b0384811660008181526101006020908152604080832080546001600160a01b031916958716959095179094558351908101845281815292516303a24d0760e21b815260048101919091529294509091630e89341c90602401600060405180830381865afa925050508015610cf057506040513d6000823e601f3d908101601f19168201604052610ced9190810190611f55565b60015b15610cf85790505b60fc546040516001600160a01b03909116906316f19831908490610d44907f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad9089908790602001611ff7565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610d70929190612021565b600060405180830381600087803b158015610d8a57600080fd5b505af1158015610d9e573d6000803e3d6000fd5b50506040516001600160a01b038087169350871691507fb96a191bae4e25ffdff7f4136994eb0dec75d263750a07c035202c348c9515f090600090a35050919050565b600054610100900460ff1615808015610e015750600054600160ff909116105b80610e1b5750303b158015610e1b575060005460ff166001145b610e375760405162461bcd60e51b81526004016105f390611e9b565b6000805460ff191660011790558015610e5a576000805461ff0019166101001790555b610e668585858561129b565b8015610eac576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b610ebb611608565b6000610ec685611610565b604051637921219560e11b81529091506001600160a01b0386169063f242432a90610efb90339030908890889060040161204d565b600060405180830381600087803b158015610f1557600080fd5b505af1158015610f29573d6000803e3d6000fd5b505060fc5460fe54604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038b8116828401523360608301528a8116608083015260a082018a905260c08083018a90528351808403909101815260e08301938490526316f1983160e01b90935293841695506316f198319450610fc0939092169160e401612021565b600060405180830381600087803b158015610fda57600080fd5b505af1158015610fee573d6000803e3d6000fd5b505060408051338152602081018790529081018590526001600160a01b03808816935084811692508816907fe6f1fb6bb1930a5d4b997d56e0a4a8cb6f3f941f0d5391f63c1f6914ee01e0b89060600160405180910390a4610eac565b611053611608565b600061105e88611610565b905060005b8481101561110a57886001600160a01b031663f242432a333089898681811061108e5761108e612085565b905060200201358888878181106110a7576110a7612085565b905060200201356040518563ffffffff1660e01b81526004016110cd949392919061204d565b600060405180830381600087803b1580156110e757600080fd5b505af11580156110fb573d6000803e3d6000fd5b50505050806001019050611063565b5060fc5460fe546040516001600160a01b03928316926316f19831921690611166907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908d9033908e908e908e908e908e908e90602001612116565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401611192929190612021565b600060405180830381600087803b1580156111ac57600080fd5b505af11580156111c0573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316896001600160a01b03167fa7d9cd27143f817fe006011faf3c04351f70f75cd30e7b21405817f2f670041e8a8a8a8a8a8a60405161121b96959493929190612181565b60405180910390a461087e565b6033546001600160a01b031633146106265760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105f3565b606580546001600160a01b031916905561069f81611658565b6001600160a01b038416158015906112bb57506001600160a01b03831615155b80156112cf57506001600160a01b03821615155b80156112e357506001600160a01b03811615155b6113485760405162461bcd60e51b815260206004820152603060248201527f526f6f744d696e7461626c65455243313135355072656469636174653a20424160448201526f222fa4a724aa24a0a624ad20aa24a7a760811b60648201526084016105f3565b60fc80546001600160a01b039586166001600160a01b03199182161790915560fd80549486169482169490941790935560fe80549285169284169290921790915560ff8054919093169116179055565b6000808080806113aa868801886121ca565b6001600160a01b0380861660009081526101006020526040902054959a509398509196509450925016806113e0576113e0612225565b604051637921219560e11b81526001600160a01b0387169063f242432a9061141290309088908890889060040161204d565b600060405180830381600087803b15801561142c57600080fd5b505af1158015611440573d6000803e3d6000fd5b5050604080516001600160a01b0389811682526020820188905291810186905281881693508482169250908916907f52cdfbe452878311d3237a4c20a951600d8e3a4fe6691d967d33788dc12d19c6906060015b60405180910390a45050505050505050565b6000808080806114b88688018861223b565b6001600160a01b0380861660009081526101006020526040902054959b5093995091975095509350169050806114f0576114f0612225565b60005b83518110156115b657866001600160a01b031663f242432a3087848151811061151e5761151e612085565b602002602001015187858151811061153857611538612085565b602002602001015187868151811061155257611552612085565b60200260200101516040518563ffffffff1660e01b8152600401611579949392919061204d565b600060405180830381600087803b15801561159357600080fd5b505af11580156115a7573d6000803e3d6000fd5b505050508060010190506114f3565b50846001600160a01b0316816001600160a01b0316876001600160a01b03167f52733a40a0466155541c2fc4044165dd37a3db116bc834bab2f020665e90fd2087878760405161149493929190612380565b6106266116aa565b6001600160a01b0380821660009081526101006020526040902054168061163d5761163a82610ad1565b90505b6001600160a01b03811661165357611653612225565b919050565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60c95460ff16156117b557604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600160991b01916113889161170c91906123f5565b6000604051808303818686fa925050503d8060008114611748576040519150601f19603f3d011682016040523d82523d6000602084013e61174d565b606091505b509150915081801561177257506000818060200190518101906117709190612411565b115b6117b25760405162461bcd60e51b81526020600482015260116024820152702224a9a0a62627aba2a22fa9a2a72222a960791b60448201526064016105f3565b50505b60c954610100900460ff161561062657604080513360248083019190915282518083039091018152604490910182526020810180516001600160e01b031663d78bca6960e01b179052905160009182916004600360981b01916113889161181c91906123f5565b6000604051808303818686fa925050503d8060008114611858576040519150601f19603f3d011682016040523d82523d6000602084013e61185d565b606091505b509150915081801561188357508080602001905181019061187e9190612411565b600114155b6118c05760405162461bcd60e51b815260206004820152600e60248201526d212627a1a5a2a22fa9a2a72222a960911b60448201526064016105f3565b5050565b6000602082840312156118d657600080fd5b81356001600160e01b0319811681146118ee57600080fd5b9392505050565b6001600160a01b038116811461069f57600080fd5b60008060006060848603121561191f57600080fd5b833561192a816118f5565b95602085013595506040909401359392505050565b60008083601f84011261195157600080fd5b5081356001600160401b0381111561196857600080fd5b6020830191508360208260051b850101111561198357600080fd5b9250929050565b60008060008060008060006080888a0312156119a557600080fd5b87356119b0816118f5565b965060208801356001600160401b03808211156119cc57600080fd5b6119d88b838c0161193f565b909850965060408a01359150808211156119f157600080fd5b6119fd8b838c0161193f565b909650945060608a0135915080821115611a1657600080fd5b50611a238a828b0161193f565b989b979a50959850939692959293505050565b600060208284031215611a4857600080fd5b81356118ee816118f5565b60008060008060808587031215611a6957600080fd5b8435611a74816118f5565b93506020850135611a84816118f5565b93969395505050506040820135916060013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611ad757611ad7611a99565b604052919050565b60006001600160401b03821115611af857611af8611a99565b5060051b60200190565b600082601f830112611b1357600080fd5b81356020611b28611b2383611adf565b611aaf565b82815260059290921b84018101918181019086841115611b4757600080fd5b8286015b84811015611b625780358352918301918301611b4b565b509695505050505050565b60006001600160401b03821115611b8657611b86611a99565b50601f01601f191660200190565b600082601f830112611ba557600080fd5b8135611bb3611b2382611b6d565b818152846020838601011115611bc857600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a08688031215611bfd57600080fd5b8535611c08816118f5565b94506020860135611c18816118f5565b935060408601356001600160401b0380821115611c3457600080fd5b611c4089838a01611b02565b94506060880135915080821115611c5657600080fd5b611c6289838a01611b02565b93506080880135915080821115611c7857600080fd5b50611c8588828901611b94565b9150509295509295909350565b8035801515811461165357600080fd5b600060208284031215611cb457600080fd5b6118ee82611c92565b600080600080600080600060e0888a031215611cd857600080fd5b8735611ce3816118f5565b96506020880135611cf3816118f5565b95506040880135611d03816118f5565b94506060880135611d13816118f5565b9350611d2160808901611c92565b9250611d2f60a08901611c92565b915060c0880135611d3f816118f5565b8091505092959891949750929550565b60008060008060608587031215611d6557600080fd5b843593506020850135611d77816118f5565b925060408501356001600160401b0380821115611d9357600080fd5b818701915087601f830112611da757600080fd5b813581811115611db657600080fd5b886020828501011115611dc857600080fd5b95989497505060200194505050565b600080600080600060a08688031215611def57600080fd5b8535611dfa816118f5565b94506020860135611e0a816118f5565b9350604086013592506060860135915060808601356001600160401b03811115611e3357600080fd5b611c8588828901611b94565b60008060008060808587031215611e5557600080fd5b8435611e60816118f5565b93506020850135611e70816118f5565b92506040850135611e80816118f5565b91506060850135611e90816118f5565b939692955090935050565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60008085851115611ef957600080fd5b83861115611f0657600080fd5b5050820193919092039150565b8035602083101561058357600019602084900360031b1b1692915050565b60005b83811015611f4c578181015183820152602001611f34565b50506000910152565b600060208284031215611f6757600080fd5b81516001600160401b03811115611f7d57600080fd5b8201601f81018413611f8e57600080fd5b8051611f9c611b2382611b6d565b818152856020838501011115611fb157600080fd5b611fc2826020830160208601611f31565b95945050505050565b60008151808452611fe3816020860160208601611f31565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090611fc290830184611fcb565b6001600160a01b038316815260406020820181905260009061204590830184611fcb565b949350505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052603260045260246000fd5b8183526000602080850194508260005b858110156120d95781356120be816118f5565b6001600160a01b0316875295820195908201906001016120ab565b509495945050505050565b81835260006001600160fb1b038311156120fd57600080fd5b8260051b80836020870137939093016020019392505050565b8981526001600160a01b0389811660208301528816604082015260c060608201819052600090612149908301888a61209b565b828103608084015261215c8187896120e4565b905082810360a08401526121718185876120e4565b9c9b505050505050505050505050565b60608152600061219560608301888a61209b565b82810360208401526121a88187896120e4565b905082810360408401526121bd8185876120e4565b9998505050505050505050565b600080600080600060a086880312156121e257600080fd5b85356121ed816118f5565b945060208601356121fd816118f5565b9350604086013561220d816118f5565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052600160045260246000fd5b60008060008060008060c0878903121561225457600080fd5b86359550602080880135612267816118f5565b95506040880135612277816118f5565b945060608801356001600160401b038082111561229357600080fd5b818a0191508a601f8301126122a757600080fd5b81356122b5611b2382611adf565b81815260059190911b8301840190848101908d8311156122d457600080fd5b938501935b828510156122fb5784356122ec816118f5565b825293850193908501906122d9565b9750505060808a013592508083111561231357600080fd5b61231f8b848c01611b02565b945060a08a013592508083111561233557600080fd5b505061234389828a01611b02565b9150509295509295509295565b600081518084526020808501945080840160005b838110156120d957815187529582019590820190600101612364565b606080825284519082018190526000906020906080840190828801845b828110156123c25781516001600160a01b03168452928401929084019060010161239d565b505050838103828501526123d68187612350565b91505082810360408401526123eb8185612350565b9695505050505050565b60008251612407818460208701611f31565b9190910192915050565b60006020828403121561242357600080fd5b505191905056fe526f6f744d696e7461626c65455243313135355072656469636174653a20494ea2646970667358221220965ae0a80f2c0fef1177c03f5c9015e9cb11183a07cb364acd575c0d5b96410c64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var SystemArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"System\",\n \"sourceName\": \"contracts/child/System.sol\",\n \"abi\": [\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b5061015a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c806355b01e4d1161006657806355b01e4d146100e35780635ea5df79146100f1578063947287cf1461010857806397e5230d14610111578063e0563ab11461011b57600080fd5b806307b3e25214610098578063284017f5146100c35780633b878c22146100cc57806351351d53146100d5575b600080fd5b6100a66004600360981b0181565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a661202081565b6100a661101081565b6100a66002600160a01b0381565b6100a66004600160991b0181565b6100fa61138881565b6040519081526020016100ba565b6100fa61520881565b6100fa620249f081565b6100a66120308156fea2646970667358221220cdc81f82626224fb8a04246ca1d1898f8b03c160e9b2f63cd0bc4b5d0b55c3f964736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100935760003560e01c806355b01e4d1161006657806355b01e4d146100e35780635ea5df79146100f1578063947287cf1461010857806397e5230d14610111578063e0563ab11461011b57600080fd5b806307b3e25214610098578063284017f5146100c35780633b878c22146100cc57806351351d53146100d5575b600080fd5b6100a66004600360981b0181565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a661202081565b6100a661101081565b6100a66002600160a01b0381565b6100a66004600160991b0181565b6100fa61138881565b6040519081526020016100ba565b6100fa61520881565b6100fa620249f081565b6100a66120308156fea2646970667358221220cdc81f82626224fb8a04246ca1d1898f8b03c160e9b2f63cd0bc4b5d0b55c3f964736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var BLSArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"BLS\",\n \"sourceName\": \"contracts/common/BLS.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"domain\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"message\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"expandMsgTo96\",\n \"outputs\": [\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"domain\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"messages\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"hashToField\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"domain\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"message\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"hashToPoint\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"point\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"name\": \"isOnCurveG1\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"_isOnCurve\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"point\",\n \"type\": \"uint256[4]\"\n }\n ],\n \"name\": \"isOnCurveG2\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"_isOnCurve\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"name\": \"isValidSignature\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"_x\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mapToPoint\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"p\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256[4][]\",\n \"name\": \"pubkeys\",\n \"type\": \"uint256[4][]\"\n },\n {\n \"internalType\": \"uint256[2][]\",\n \"name\": \"messages\",\n \"type\": \"uint256[2][]\"\n }\n ],\n \"name\": \"verifyMultiple\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"checkResult\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"callSuccess\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256[4][]\",\n \"name\": \"pubkeys\",\n \"type\": \"uint256[4][]\"\n },\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"message\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"name\": \"verifyMultipleSameMsg\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"checkResult\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"callSuccess\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"pubkey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"message\",\n \"type\": \"uint256[2]\"\n }\n ],\n \"name\": \"verifySingle\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612df8806100206000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c806391ec2d2b1161006657806391ec2d2b1461013b578063a850a9091461015b578063d58e77331461016e578063e242cce914610181578063ebbdac911461019457600080fd5b8063115000fe146100a3578063247dd9fb146100cb5780633e5476ce146100de5780638669026f146101085780639141376314610128575b600080fd5b6100b66100b1366004612708565b6101a7565b60405190151581526020015b60405180910390f35b6100b66100d9366004612785565b61030e565b6100f16100ec366004612841565b6103b8565b6040805192151583529015156020830152016100c2565b61011b6101163660046128ce565b61079f565b6040516100c29190612957565b6100f1610136366004612988565b6108bb565b61014e6101493660046128ce565b610d5c565b6040516100c29190612a86565b61011b6101693660046128ce565b610ff8565b61011b61017c366004612aa0565b6111d4565b6100b661018f366004612785565b6115aa565b6100f16101a2366004612ab9565b611609565b600081516020830151600080516020612d63833981519152828309600080516020612d638339815191528283098182830101600080516020612d638339815191528283840108600080516020612d638339815191528682600080516020612d6383398151915203860109935050600080516020612d638339815191528483600080516020612d63833981519152038301099150600080516020612d638339815191527f2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e584089450600080516020612d638339815191527e9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2830893506040870151925060608701519150600080516020612d638339815191528083600080516020612d63833981519152038508600080516020612d63833981519152848608099050600080516020612d63833981519152828460011b0994149290931491909116949350505050565b8051600090600080516020612d6383398151915211158061034157506020820151600080516020612d6383398151915211155b1561034e57506000919050565b60405163e242cce960e01b8152309063e242cce990610371908590600401612957565b602060405180830381865afa15801561038e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b29190612b1c565b92915050565b60008083806103e25760405162461bcd60e51b81526004016103d990612b3e565b60405180910390fd5b60006103ef826001612b95565b6103fa906006612ba8565b90506000816001600160401b038111156104165761041661269a565b60405190808252806020026020018201604052801561043f578160200160208202803683370190505b50905088600060200201358160008151811061045d5761045d612b06565b602090810291909101015288600160200201358160018151811061048357610483612b06565b602002602001018181525050600080516020612d43833981519152816002815181106104b1576104b1612b06565b602002602001018181525050600080516020612d23833981519152816003815181106104df576104df612b06565b602002602001018181525050600080516020612d838339815191528160048151811061050d5761050d612b06565b602002602001018181525050600080516020612da38339815191528160058151811061053b5761053b612b06565b60200260200101818152505060005b8381101561075a57863582610560836006612ba8565b61056b906006612b95565b8151811061057b5761057b612b06565b602090810291909101015286600160200201358261059a836006612ba8565b6105a5906007612b95565b815181106105b5576105b5612b06565b6020026020010181815250508888828181106105d3576105d3612b06565b9050608002016001600481106105eb576105eb612b06565b6020020135826105fc836006612ba8565b610607906008612b95565b8151811061061757610617612b06565b60200260200101818152505088888281811061063557610635612b06565b90506080020160006004811061064d5761064d612b06565b60200201358261065e836006612ba8565b610669906009612b95565b8151811061067957610679612b06565b60200260200101818152505088888281811061069757610697612b06565b9050608002016003600481106106af576106af612b06565b6020020135826106c0836006612ba8565b6106cb90600a612b95565b815181106106db576106db612b06565b6020026020010181815250508888828181106106f9576106f9612b06565b90506080020160026004811061071157610711612b06565b602002013582610722836006612ba8565b61072d90600b612b95565b8151811061073d5761073d612b06565b60209081029190910101528061075281612bbf565b91505061054a565b50610763612640565b602081602085026020850160085afa945084610789576000809550955050505050610796565b5115159450600193505050505b94509492505050565b6107a761265e565b6040516391ec2d2b60e01b815260009030906391ec2d2b906107cf9087908790600401612bd8565b600060405180830381865afa1580156107ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108149190810190612bf9565b9050600080600080601885016001600160c01b0381511693506030860190506001600160c01b038151169450600080516020612d6383398151915285600080516020612d63833981519152600160c01b870908604887015160608801516001600160c01b0390811697501694509250600080516020612d6383398151915290508481600160c01b860908604080518082019091529283526020830152509695505050505050565b60008084806108dc5760405162461bcd60e51b81526004016103d990612b3e565b8084146109495760405162461bcd60e51b815260206004820152603560248201527f424c533a206e756d626572206f66207075626c6963206b65797320616e64206d604482015274195cdcd859d95cc81b5d5cdd08189948195c5d585b605a1b60648201526084016103d9565b6000610956826001612b95565b610961906006612ba8565b90506000816001600160401b0381111561097d5761097d61269a565b6040519080825280602002602001820160405280156109a6578160200160208202803683370190505b5090508960006020020135816000815181106109c4576109c4612b06565b60209081029190910101528960016020020135816001815181106109ea576109ea612b06565b602002602001018181525050600080516020612d4383398151915281600281518110610a1857610a18612b06565b602002602001018181525050600080516020612d2383398151915281600381518110610a4657610a46612b06565b602002602001018181525050600080516020612d8383398151915281600481518110610a7457610a74612b06565b602002602001018181525050600080516020612da383398151915281600581518110610aa257610aa2612b06565b60200260200101818152505060005b83811015610d1657878782818110610acb57610acb612b06565b905060400201600060028110610ae357610ae3612b06565b602002013582610af4836006612ba8565b610aff906006612b95565b81518110610b0f57610b0f612b06565b602002602001018181525050878782818110610b2d57610b2d612b06565b905060400201600160028110610b4557610b45612b06565b602002013582610b56836006612ba8565b610b61906007612b95565b81518110610b7157610b71612b06565b602002602001018181525050898982818110610b8f57610b8f612b06565b905060800201600160048110610ba757610ba7612b06565b602002013582610bb8836006612ba8565b610bc3906008612b95565b81518110610bd357610bd3612b06565b602002602001018181525050898982818110610bf157610bf1612b06565b905060800201600060048110610c0957610c09612b06565b602002013582610c1a836006612ba8565b610c25906009612b95565b81518110610c3557610c35612b06565b602002602001018181525050898982818110610c5357610c53612b06565b905060800201600360048110610c6b57610c6b612b06565b602002013582610c7c836006612ba8565b610c8790600a612b95565b81518110610c9757610c97612b06565b602002602001018181525050898982818110610cb557610cb5612b06565b905060800201600260048110610ccd57610ccd612b06565b602002013582610cde836006612ba8565b610ce990600b612b95565b81518110610cf957610cf9612b06565b602090810291909101015280610d0e81612bbf565b915050610ab1565b50610d1f612640565b602081602085026020850160085afa945084610d45576000809550955050505050610d52565b5115159450600193505050505b9550959350505050565b80516060906000610d6e826020612b95565b610d79906040612b95565b610d84906004612b95565b6001600160401b03811115610d9b57610d9b61269a565b6040519080825280601f01601f191660200182016040528015610dc5576020820181803683370190505b5060408051606080825260808201909252919250600091906020820181803683370190505090506060820160005b84811015610e0d5760208188018101518383015201610df3565b5083016000815360010160608153600101600081536001810187905260210160208153506000600283604051610e439190612c6f565b602060405180830381855afa158015610e60573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610e839190612c8b565b9050600060429450848452816020850152600160408501536041840188905260206061850153600284604051610eb99190612c6f565b602060405180830381855afa158015610ed6573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610ef99190612c8b565b905080602084015280821880602086015250600260408501536041840188905260206061850153600284604051610f309190612c6f565b602060405180830381855afa158015610f4d573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610f709190612c8b565b905080604084015280821880602086015250600360408501536041840188905260206061850153600284604051610fa79190612c6f565b602060405180830381855afa158015610fc4573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610fe79190612c8b565b606084015250909695505050505050565b61100061265e565b604051638669026f60e01b81526000903090638669026f906110289087908790600401612bd8565b6040805180830381865afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110689190612ca4565b805160405163d58e773360e01b81526004810191909152909150600090309063d58e7733906024016040805180830381865afa1580156110ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d09190612ca4565b602083015160405163d58e773360e01b81526004810191909152909150600090309063d58e7733906024016040805180830381865afa158015611117573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113b9190612ca4565b905061114561267c565b825181526020808401518282015282516040808401919091529083015160608301526000908460808460066107d05a03fa9050808061118057fe5b50806111c85760405162461bcd60e51b8152602060048201526017602482015276109314ce88189b881859190818d85b1b0819985a5b1959604a1b60448201526064016103d9565b50919695505050505050565b6111dc61265e565b600080516020612d6383398151915282106112455760405162461bcd60e51b815260206004820152602360248201527f6d6170546f506f696e7446543a20696e76616c6964206669656c6420656c656d604482015262195b9d60ea1b60648201526084016103d9565b81600061125182611790565b9150506000600080516020612d638339815191528061127257611272612cf9565b8384099050600080516020612d638339815191526004820890506000600080516020612d6383398151915277b3c4d79d41a91759a9e4c7e359b6b89eaec68e62effffffd850990506000600080516020612d6383398151915283830990506112d9816117b9565b9050600080516020612d638339815191528283099150600080516020612d638339815191528183099150600080516020612d638339815191528286099150600080516020612d6383398151915261133e83600080516020612d63833981519152612d0f565b7759e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe089450600080516020612d638339815191528586099150600080516020612d638339815191528583099150600080516020612d6383398151915260038308915060006113a283611790565b909350905080156113ea57846113cd576113ca83600080516020612d63833981519152612d0f565b92505b505060408051808201909152938452602084015250909392505050565b600080516020612d638339815191526001870861141590600080516020612d63833981519152612d0f565b9550600080516020612d638339815191528687099250600080516020612d638339815191528684099250600080516020612d6383398151915260038408925061145d83611790565b9093509050801561148557846113cd576113ca83600080516020612d63833981519152612d0f565b600080516020612d638339815191528485099550600080516020612d638339815191528687099550600080516020612d638339815191528287099550600080516020612d638339815191528287099550600080516020612d63833981519152600187089550600080516020612d638339815191528687099250600080516020612d638339815191528684099250600080516020612d6383398151915260038408925061153083611790565b90935090508061158d5760405162461bcd60e51b815260206004820152602260248201527f424c533a20626164206674206d617070696e6720696d706c656d656e7461746960448201526137b760f11b60648201526084016103d9565b846113cd576113ca83600080516020612d63833981519152612d0f565b600081516020830151600080516020612d63833981519152828309600080516020612d638339815191528382099050600080516020612d63833981519152600382089050600080516020612d6383398151915282830914949350505050565b60008060006040518061018001604052808760006002811061162d5761162d612b06565b602002013581526020018760016002811061164a5761164a612b06565b60200201358152602001600080516020612d438339815191528152602001600080516020612d238339815191528152602001600080516020612d838339815191528152602001600080516020612da38339815191528152602001856000600281106116b7576116b7612b06565b60200201358152602001856001600281106116d4576116d4612b06565b60200201358152602001866001600481106116f1576116f1612b06565b602002013581526020018660006004811061170e5761170e612b06565b602002013581526020018660036004811061172b5761172b612b06565b602002013581526020018660026004811061174857611748612b06565b602002013590529050611759612640565b60006020826101808560085afa90508061177c5760008094509450505050611788565b50511515925060019150505b935093915050565b60008061179c836117c4565b915082600080516020612d63833981519152838409149050915091565b60006103b282611ef9565b6000600080516020612d638339815191528083840991508083830981838209828283098385830984848309858484098684850997508684840987858409945087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087838a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985050868889099750868889099750868889099750868889099750868889099750868889099750868489099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868689099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868189099750508587880996508587880996508587880996508585880996508587880996508587880996508587880996508585880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508587880996508581880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508584880996508587880996508587880996508587880996508587880996508587880996508581880996505050505050808283099392505050565b6000600080516020612d638339815191528083840991508083830981838209828283098385830984848309858484098684850997508684840987858409945087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087838a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985050868889099750868889099750868889099750868889099750868889099750868889099750868489099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868689099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868189099750508587880996508587880996508587880996508585880996508587880996508587880996508587880996508585880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508587880996508581880996505050838586099450838586099450838586099450838586099450838186099450508284850993508284850993508284850993508281850993508284850993508284850993508285850993508284850993508284850993508284850993508284850993508284850993508284850993508281850995945050505050565b60405180602001604052806001906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156126d2576126d261269a565b60405290565b604051601f8201601f191681016001600160401b03811182821017156127005761270061269a565b604052919050565b60006080828403121561271a57600080fd5b82601f83011261272957600080fd5b604051608081018181106001600160401b038211171561274b5761274b61269a565b60405280608084018581111561276057600080fd5b845b8181101561277a578035835260209283019201612762565b509195945050505050565b60006040828403121561279757600080fd5b82601f8301126127a657600080fd5b6127ae6126b0565b8060408401858111156127c057600080fd5b845b818110156127da5780358452602093840193016127c2565b509095945050505050565b80604081018310156103b257600080fd5b60008083601f84011261280857600080fd5b5081356001600160401b0381111561281f57600080fd5b6020830191508360208260071b850101111561283a57600080fd5b9250929050565b60008060008060a0858703121561285757600080fd5b61286186866127e5565b935060408501356001600160401b0381111561287c57600080fd5b612888878288016127f6565b909450925061289c905086606087016127e5565b905092959194509250565b60006001600160401b038211156128c0576128c061269a565b50601f01601f191660200190565b600080604083850312156128e157600080fd5b8235915060208301356001600160401b038111156128fe57600080fd5b8301601f8101851361290f57600080fd5b803561292261291d826128a7565b6126d8565b81815286602083850101111561293757600080fd5b816020840160208301376000602083830101528093505050509250929050565b60408101818360005b600281101561297f578151835260209283019290910190600101612960565b50505092915050565b6000806000806000608086880312156129a057600080fd5b6129aa87876127e5565b945060408601356001600160401b03808211156129c657600080fd5b6129d289838a016127f6565b909650945060608801359150808211156129eb57600080fd5b818801915088601f8301126129ff57600080fd5b813581811115612a0e57600080fd5b8960208260061b8501011115612a2357600080fd5b9699959850939650602001949392505050565b60005b83811015612a51578181015183820152602001612a39565b50506000910152565b60008151808452612a72816020860160208601612a36565b601f01601f19169290920160200192915050565b602081526000612a996020830184612a5a565b9392505050565b600060208284031215612ab257600080fd5b5035919050565b60008060006101008486031215612acf57600080fd5b612ad985856127e5565b925060c0840185811115612aec57600080fd5b604085019250612afc86826127e5565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612b2e57600080fd5b81518015158114612a9957600080fd5b60208082526021908201527f424c533a206e756d626572206f66207075626c6963206b6579206973207a65726040820152606f60f81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b808201808211156103b2576103b2612b7f565b80820281158282048414176103b2576103b2612b7f565b600060018201612bd157612bd1612b7f565b5060010190565b828152604060208201526000612bf16040830184612a5a565b949350505050565b600060208284031215612c0b57600080fd5b81516001600160401b03811115612c2157600080fd5b8201601f81018413612c3257600080fd5b8051612c4061291d826128a7565b818152856020838501011115612c5557600080fd5b612c66826020830160208601612a36565b95945050505050565b60008251612c81818460208701612a36565b9190910192915050565b600060208284031215612c9d57600080fd5b5051919050565b600060408284031215612cb657600080fd5b82601f830112612cc557600080fd5b612ccd6126b0565b806040840185811115612cdf57600080fd5b845b818110156127da578051845260209384019301612ce1565b634e487b7160e01b600052601260045260246000fd5b818103818111156103b2576103b2612b7f56fe1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9da264697066735822122085f910855a39dd4d2f9582253d737b6f9c450d7d8e7383f636149d598d69b6ac64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061009e5760003560e01c806391ec2d2b1161006657806391ec2d2b1461013b578063a850a9091461015b578063d58e77331461016e578063e242cce914610181578063ebbdac911461019457600080fd5b8063115000fe146100a3578063247dd9fb146100cb5780633e5476ce146100de5780638669026f146101085780639141376314610128575b600080fd5b6100b66100b1366004612708565b6101a7565b60405190151581526020015b60405180910390f35b6100b66100d9366004612785565b61030e565b6100f16100ec366004612841565b6103b8565b6040805192151583529015156020830152016100c2565b61011b6101163660046128ce565b61079f565b6040516100c29190612957565b6100f1610136366004612988565b6108bb565b61014e6101493660046128ce565b610d5c565b6040516100c29190612a86565b61011b6101693660046128ce565b610ff8565b61011b61017c366004612aa0565b6111d4565b6100b661018f366004612785565b6115aa565b6100f16101a2366004612ab9565b611609565b600081516020830151600080516020612d63833981519152828309600080516020612d638339815191528283098182830101600080516020612d638339815191528283840108600080516020612d638339815191528682600080516020612d6383398151915203860109935050600080516020612d638339815191528483600080516020612d63833981519152038301099150600080516020612d638339815191527f2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e584089450600080516020612d638339815191527e9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2830893506040870151925060608701519150600080516020612d638339815191528083600080516020612d63833981519152038508600080516020612d63833981519152848608099050600080516020612d63833981519152828460011b0994149290931491909116949350505050565b8051600090600080516020612d6383398151915211158061034157506020820151600080516020612d6383398151915211155b1561034e57506000919050565b60405163e242cce960e01b8152309063e242cce990610371908590600401612957565b602060405180830381865afa15801561038e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b29190612b1c565b92915050565b60008083806103e25760405162461bcd60e51b81526004016103d990612b3e565b60405180910390fd5b60006103ef826001612b95565b6103fa906006612ba8565b90506000816001600160401b038111156104165761041661269a565b60405190808252806020026020018201604052801561043f578160200160208202803683370190505b50905088600060200201358160008151811061045d5761045d612b06565b602090810291909101015288600160200201358160018151811061048357610483612b06565b602002602001018181525050600080516020612d43833981519152816002815181106104b1576104b1612b06565b602002602001018181525050600080516020612d23833981519152816003815181106104df576104df612b06565b602002602001018181525050600080516020612d838339815191528160048151811061050d5761050d612b06565b602002602001018181525050600080516020612da38339815191528160058151811061053b5761053b612b06565b60200260200101818152505060005b8381101561075a57863582610560836006612ba8565b61056b906006612b95565b8151811061057b5761057b612b06565b602090810291909101015286600160200201358261059a836006612ba8565b6105a5906007612b95565b815181106105b5576105b5612b06565b6020026020010181815250508888828181106105d3576105d3612b06565b9050608002016001600481106105eb576105eb612b06565b6020020135826105fc836006612ba8565b610607906008612b95565b8151811061061757610617612b06565b60200260200101818152505088888281811061063557610635612b06565b90506080020160006004811061064d5761064d612b06565b60200201358261065e836006612ba8565b610669906009612b95565b8151811061067957610679612b06565b60200260200101818152505088888281811061069757610697612b06565b9050608002016003600481106106af576106af612b06565b6020020135826106c0836006612ba8565b6106cb90600a612b95565b815181106106db576106db612b06565b6020026020010181815250508888828181106106f9576106f9612b06565b90506080020160026004811061071157610711612b06565b602002013582610722836006612ba8565b61072d90600b612b95565b8151811061073d5761073d612b06565b60209081029190910101528061075281612bbf565b91505061054a565b50610763612640565b602081602085026020850160085afa945084610789576000809550955050505050610796565b5115159450600193505050505b94509492505050565b6107a761265e565b6040516391ec2d2b60e01b815260009030906391ec2d2b906107cf9087908790600401612bd8565b600060405180830381865afa1580156107ec573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108149190810190612bf9565b9050600080600080601885016001600160c01b0381511693506030860190506001600160c01b038151169450600080516020612d6383398151915285600080516020612d63833981519152600160c01b870908604887015160608801516001600160c01b0390811697501694509250600080516020612d6383398151915290508481600160c01b860908604080518082019091529283526020830152509695505050505050565b60008084806108dc5760405162461bcd60e51b81526004016103d990612b3e565b8084146109495760405162461bcd60e51b815260206004820152603560248201527f424c533a206e756d626572206f66207075626c6963206b65797320616e64206d604482015274195cdcd859d95cc81b5d5cdd08189948195c5d585b605a1b60648201526084016103d9565b6000610956826001612b95565b610961906006612ba8565b90506000816001600160401b0381111561097d5761097d61269a565b6040519080825280602002602001820160405280156109a6578160200160208202803683370190505b5090508960006020020135816000815181106109c4576109c4612b06565b60209081029190910101528960016020020135816001815181106109ea576109ea612b06565b602002602001018181525050600080516020612d4383398151915281600281518110610a1857610a18612b06565b602002602001018181525050600080516020612d2383398151915281600381518110610a4657610a46612b06565b602002602001018181525050600080516020612d8383398151915281600481518110610a7457610a74612b06565b602002602001018181525050600080516020612da383398151915281600581518110610aa257610aa2612b06565b60200260200101818152505060005b83811015610d1657878782818110610acb57610acb612b06565b905060400201600060028110610ae357610ae3612b06565b602002013582610af4836006612ba8565b610aff906006612b95565b81518110610b0f57610b0f612b06565b602002602001018181525050878782818110610b2d57610b2d612b06565b905060400201600160028110610b4557610b45612b06565b602002013582610b56836006612ba8565b610b61906007612b95565b81518110610b7157610b71612b06565b602002602001018181525050898982818110610b8f57610b8f612b06565b905060800201600160048110610ba757610ba7612b06565b602002013582610bb8836006612ba8565b610bc3906008612b95565b81518110610bd357610bd3612b06565b602002602001018181525050898982818110610bf157610bf1612b06565b905060800201600060048110610c0957610c09612b06565b602002013582610c1a836006612ba8565b610c25906009612b95565b81518110610c3557610c35612b06565b602002602001018181525050898982818110610c5357610c53612b06565b905060800201600360048110610c6b57610c6b612b06565b602002013582610c7c836006612ba8565b610c8790600a612b95565b81518110610c9757610c97612b06565b602002602001018181525050898982818110610cb557610cb5612b06565b905060800201600260048110610ccd57610ccd612b06565b602002013582610cde836006612ba8565b610ce990600b612b95565b81518110610cf957610cf9612b06565b602090810291909101015280610d0e81612bbf565b915050610ab1565b50610d1f612640565b602081602085026020850160085afa945084610d45576000809550955050505050610d52565b5115159450600193505050505b9550959350505050565b80516060906000610d6e826020612b95565b610d79906040612b95565b610d84906004612b95565b6001600160401b03811115610d9b57610d9b61269a565b6040519080825280601f01601f191660200182016040528015610dc5576020820181803683370190505b5060408051606080825260808201909252919250600091906020820181803683370190505090506060820160005b84811015610e0d5760208188018101518383015201610df3565b5083016000815360010160608153600101600081536001810187905260210160208153506000600283604051610e439190612c6f565b602060405180830381855afa158015610e60573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610e839190612c8b565b9050600060429450848452816020850152600160408501536041840188905260206061850153600284604051610eb99190612c6f565b602060405180830381855afa158015610ed6573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610ef99190612c8b565b905080602084015280821880602086015250600260408501536041840188905260206061850153600284604051610f309190612c6f565b602060405180830381855afa158015610f4d573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610f709190612c8b565b905080604084015280821880602086015250600360408501536041840188905260206061850153600284604051610fa79190612c6f565b602060405180830381855afa158015610fc4573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190610fe79190612c8b565b606084015250909695505050505050565b61100061265e565b604051638669026f60e01b81526000903090638669026f906110289087908790600401612bd8565b6040805180830381865afa158015611044573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110689190612ca4565b805160405163d58e773360e01b81526004810191909152909150600090309063d58e7733906024016040805180830381865afa1580156110ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d09190612ca4565b602083015160405163d58e773360e01b81526004810191909152909150600090309063d58e7733906024016040805180830381865afa158015611117573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113b9190612ca4565b905061114561267c565b825181526020808401518282015282516040808401919091529083015160608301526000908460808460066107d05a03fa9050808061118057fe5b50806111c85760405162461bcd60e51b8152602060048201526017602482015276109314ce88189b881859190818d85b1b0819985a5b1959604a1b60448201526064016103d9565b50919695505050505050565b6111dc61265e565b600080516020612d6383398151915282106112455760405162461bcd60e51b815260206004820152602360248201527f6d6170546f506f696e7446543a20696e76616c6964206669656c6420656c656d604482015262195b9d60ea1b60648201526084016103d9565b81600061125182611790565b9150506000600080516020612d638339815191528061127257611272612cf9565b8384099050600080516020612d638339815191526004820890506000600080516020612d6383398151915277b3c4d79d41a91759a9e4c7e359b6b89eaec68e62effffffd850990506000600080516020612d6383398151915283830990506112d9816117b9565b9050600080516020612d638339815191528283099150600080516020612d638339815191528183099150600080516020612d638339815191528286099150600080516020612d6383398151915261133e83600080516020612d63833981519152612d0f565b7759e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe089450600080516020612d638339815191528586099150600080516020612d638339815191528583099150600080516020612d6383398151915260038308915060006113a283611790565b909350905080156113ea57846113cd576113ca83600080516020612d63833981519152612d0f565b92505b505060408051808201909152938452602084015250909392505050565b600080516020612d638339815191526001870861141590600080516020612d63833981519152612d0f565b9550600080516020612d638339815191528687099250600080516020612d638339815191528684099250600080516020612d6383398151915260038408925061145d83611790565b9093509050801561148557846113cd576113ca83600080516020612d63833981519152612d0f565b600080516020612d638339815191528485099550600080516020612d638339815191528687099550600080516020612d638339815191528287099550600080516020612d638339815191528287099550600080516020612d63833981519152600187089550600080516020612d638339815191528687099250600080516020612d638339815191528684099250600080516020612d6383398151915260038408925061153083611790565b90935090508061158d5760405162461bcd60e51b815260206004820152602260248201527f424c533a20626164206674206d617070696e6720696d706c656d656e7461746960448201526137b760f11b60648201526084016103d9565b846113cd576113ca83600080516020612d63833981519152612d0f565b600081516020830151600080516020612d63833981519152828309600080516020612d638339815191528382099050600080516020612d63833981519152600382089050600080516020612d6383398151915282830914949350505050565b60008060006040518061018001604052808760006002811061162d5761162d612b06565b602002013581526020018760016002811061164a5761164a612b06565b60200201358152602001600080516020612d438339815191528152602001600080516020612d238339815191528152602001600080516020612d838339815191528152602001600080516020612da38339815191528152602001856000600281106116b7576116b7612b06565b60200201358152602001856001600281106116d4576116d4612b06565b60200201358152602001866001600481106116f1576116f1612b06565b602002013581526020018660006004811061170e5761170e612b06565b602002013581526020018660036004811061172b5761172b612b06565b602002013581526020018660026004811061174857611748612b06565b602002013590529050611759612640565b60006020826101808560085afa90508061177c5760008094509450505050611788565b50511515925060019150505b935093915050565b60008061179c836117c4565b915082600080516020612d63833981519152838409149050915091565b60006103b282611ef9565b6000600080516020612d638339815191528083840991508083830981838209828283098385830984848309858484098684850997508684840987858409945087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087838a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985050868889099750868889099750868889099750868889099750868889099750868889099750868489099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868689099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868189099750508587880996508587880996508587880996508585880996508587880996508587880996508587880996508585880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508587880996508581880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508584880996508587880996508587880996508587880996508587880996508587880996508581880996505050505050808283099392505050565b6000600080516020612d638339815191528083840991508083830981838209828283098385830984848309858484098684850997508684840987858409945087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087878a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a09985087898a09985087898a09985087898a09985087838a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087828a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087848a09985087898a09985087898a09985087898a09985087898a09985087898a09985087868a09985087898a09985087898a099850878a8a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087898a09985087818a09985050868889099750868889099750868889099750868889099750868889099750868889099750868489099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868889099750868989099750868889099750868889099750868889099750868889099750868889099750868689099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868889099750868189099750508587880996508587880996508587880996508585880996508587880996508587880996508587880996508585880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508587880996508583880996508587880996508587880996508587880996508587880996508581880996505050838586099450838586099450838586099450838586099450838186099450508284850993508284850993508284850993508281850993508284850993508284850993508285850993508284850993508284850993508284850993508284850993508284850993508284850993508281850995945050505050565b60405180602001604052806001906020820280368337509192915050565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156126d2576126d261269a565b60405290565b604051601f8201601f191681016001600160401b03811182821017156127005761270061269a565b604052919050565b60006080828403121561271a57600080fd5b82601f83011261272957600080fd5b604051608081018181106001600160401b038211171561274b5761274b61269a565b60405280608084018581111561276057600080fd5b845b8181101561277a578035835260209283019201612762565b509195945050505050565b60006040828403121561279757600080fd5b82601f8301126127a657600080fd5b6127ae6126b0565b8060408401858111156127c057600080fd5b845b818110156127da5780358452602093840193016127c2565b509095945050505050565b80604081018310156103b257600080fd5b60008083601f84011261280857600080fd5b5081356001600160401b0381111561281f57600080fd5b6020830191508360208260071b850101111561283a57600080fd5b9250929050565b60008060008060a0858703121561285757600080fd5b61286186866127e5565b935060408501356001600160401b0381111561287c57600080fd5b612888878288016127f6565b909450925061289c905086606087016127e5565b905092959194509250565b60006001600160401b038211156128c0576128c061269a565b50601f01601f191660200190565b600080604083850312156128e157600080fd5b8235915060208301356001600160401b038111156128fe57600080fd5b8301601f8101851361290f57600080fd5b803561292261291d826128a7565b6126d8565b81815286602083850101111561293757600080fd5b816020840160208301376000602083830101528093505050509250929050565b60408101818360005b600281101561297f578151835260209283019290910190600101612960565b50505092915050565b6000806000806000608086880312156129a057600080fd5b6129aa87876127e5565b945060408601356001600160401b03808211156129c657600080fd5b6129d289838a016127f6565b909650945060608801359150808211156129eb57600080fd5b818801915088601f8301126129ff57600080fd5b813581811115612a0e57600080fd5b8960208260061b8501011115612a2357600080fd5b9699959850939650602001949392505050565b60005b83811015612a51578181015183820152602001612a39565b50506000910152565b60008151808452612a72816020860160208601612a36565b601f01601f19169290920160200192915050565b602081526000612a996020830184612a5a565b9392505050565b600060208284031215612ab257600080fd5b5035919050565b60008060006101008486031215612acf57600080fd5b612ad985856127e5565b925060c0840185811115612aec57600080fd5b604085019250612afc86826127e5565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612b2e57600080fd5b81518015158114612a9957600080fd5b60208082526021908201527f424c533a206e756d626572206f66207075626c6963206b6579206973207a65726040820152606f60f81b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b808201808211156103b2576103b2612b7f565b80820281158282048414176103b2576103b2612b7f565b600060018201612bd157612bd1612b7f565b5060010190565b828152604060208201526000612bf16040830184612a5a565b949350505050565b600060208284031215612c0b57600080fd5b81516001600160401b03811115612c2157600080fd5b8201601f81018413612c3257600080fd5b8051612c4061291d826128a7565b818152856020838501011115612c5557600080fd5b612c66826020830160208601612a36565b95945050505050565b60008251612c81818460208701612a36565b9190910192915050565b600060208284031215612c9d57600080fd5b5051919050565b600060408284031215612cb657600080fd5b82601f830112612cc557600080fd5b612ccd6126b0565b806040840185811115612cdf57600080fd5b845b818110156127da578051845260209384019301612ce1565b634e487b7160e01b600052601260045260246000fd5b818103818111156103b2576103b2612b7f56fe1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9da264697066735822122085f910855a39dd4d2f9582253d737b6f9c450d7d8e7383f636149d598d69b6ac64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var BN256G2Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"BN256G2\",\n \"sourceName\": \"contracts/common/BN256G2.sol\",\n \"abi\": [\n {\n \"inputs\": [],\n \"name\": \"G2_NEG_X_IM\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"G2_NEG_X_RE\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"G2_NEG_Y_IM\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"G2_NEG_Y_RE\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1xx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1xy\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1yx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1yy\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt2xx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt2xy\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt2yx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt2yy\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ecTwistAdd\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"s\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1xx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1xy\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1yx\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"pt1yy\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ecTwistMul\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"getFieldModulus\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"pure\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610dfd806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c80635120675214610072578063779d890d146100ac578063783bde80146100c05780639b0c399a146100e7578063ad50f9c11461010e578063cbe96a5014610135578063defbcdee14610168575b600080fd5b6100997f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d81565b6040519081526020015b60405180910390f35b600080516020610da8833981519152610099565b6100997f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c281565b6100997f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed81565b6100997f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec81565b610148610143366004610c8c565b61017b565b6040805194855260208501939093529183015260608201526080016100a3565b610148610176366004610ce1565b61031a565b60008080808b15801561018c57508a155b8015610196575089155b80156101a0575088155b1561020a57871580156101b1575086155b80156101bb575085155b80156101c5575084155b6101fa576101d5888888886103b1565b6101fa5760405162461bcd60e51b81526004016101f190610d1c565b60405180910390fd5b508692508591508490508361030b565b87158015610216575086155b8015610220575085155b801561022a575084155b156102675761023b8c8c8c8c6103b1565b6102575760405162461bcd60e51b81526004016101f190610d1c565b508a92508991508890508761030b565b6102738c8c8c8c6103b1565b61028f5760405162461bcd60e51b81526004016101f190610d1c565b61029b888888886103b1565b6102b75760405162461bcd60e51b81526004016101f190610d1c565b60006102d18d8d8d8d600160008f8f8f8f60016000610466565b90506103018160005b602090810291909101519083015160408401516060850151608086015160a08701516106f1565b9450945094509450505b98509850985098945050505050565b600080808060018815801561032d575087155b8015610337575086155b8015610341575085155b15610355575060019750879550600061037d565b610361898989896103b1565b61037d5760405162461bcd60e51b81526004016101f190610d1c565b600061038f8b8b8b8b8b87600061075c565b905061039c8160006102da565b929e919d509b50909950975050505050505050565b60008060008060006103c5878789896107df565b90945092506103d6898981816107df565b90925090506103e782828b8b6107df565b90925090506103f884848484610850565b909450925061044884847f2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e57e9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2610850565b909450925083158015610459575082155b9998505050505050505050565b61046e610c50565b8815801561047a575087155b156104bc578686868686868660005b60a089019290925260808801929092526060870192909252604086019290925260208581019390935290910201526106e1565b821580156104c8575081155b156104db578c8c8c8c8c8c866000610489565b6104e785858b8b6107df565b90955093506104f88b8b85856107df565b6060830152604082015261050e87878b8b6107df565b909750955061051f8d8d85856107df565b60a0830152608082018190528714801561053c575060a081015186145b15610581576040810151851480156105575750606081015184145b156105725761056a8d8d8d8d8d8d610892565b866000610489565b60016000818180808681610489565b61058d898985856107df565b90935091506105ad858583600260200201518460035b6020020151610850565b909d509b506105c887878360045b60200201518460056105a3565b909b5099506105d98b8b81816107df565b90995097506105fa89898360045b60200201518460055b60200201516107df565b909550935061060b89898d8d6107df565b909950975061061c898985856107df565b60a083015260808201526106328d8d81816107df565b9097509550610643878785856107df565b909750955061065487878b8b610850565b909750955061066585856002610ada565b909350915061067687878585610850565b90975095506106878b8b89896107df565b6020830152815261069a85858989610850565b909b5099506106ab8d8d8d8d6107df565b909b5099506106c5898983600260200201518460036105f0565b909d509b506106d68b8b8f8f610850565b606083015260408201525b9c9b505050505050505050505050565b600080600080600080610702610c6e565b61070c8989610b0d565b909350915061071d8d8d85856107df565b602083015281526107308b8b85856107df565b60608301819052604083018290528251602090930151929f929e50909c509a5098505050505050505050565b610764610c50565b87156107d45760018816156107a5578051602082015160408301516060840151608085015160a08601516107a29594939291908d8d8d8d8d8d610466565b90505b6107b3878787878787610892565b949b509299509097509550935091506107cd600289610d5e565b9750610764565b979650505050505050565b60008061081d600080516020610da8833981519152858809600080516020610da8833981519152858809600080516020610da8833981519152610b98565b600080516020610da883398151915280868809600080516020610da8833981519152868a09089150915094509492505050565b60008061086c8685600080516020610da8833981519152610b98565b6108858685600080516020610da8833981519152610b98565b9150915094509492505050565b6000806000806000806108a3610c50565b6108af8d8d6003610ada565b602083018190528183526108c591908f8f6107df565b602083015281526108d88b8b8b8b6107df565b90995097506108e98d8d8d8d6107df565b606083015260408201819052610909908260035b60200201518b8b6107df565b60608301526040820152805161092c908260015b602002015183518460016105f0565b6040830151919e509c5061094a908260035b60200201516008610ada565b60a083015260808201526109618d8d8360046105bb565b909d509b50610972898981816107df565b60a083015260808201526040810151606082015161099291906004610ada565b60608301819052604083018290526109ac91908f8f610850565b6060830152604082018190526109c49082600361091d565b606083015260408201526109da8b8b6008610ada565b602083018190528183526109f091908d8d6107df565b60208301819052818352610a0791908360046105e7565b602083015280825260408201516060830151610a25928460016105a3565b60608301526040820152610a3b8d8d6002610ada565b6020830152808252610a4f908260016108fd565b60208301528152610a6389898360046105e7565b60a083015260808201819052610a7b9082600561093e565b826004602002018360056020020191909152528060006020020151816001602002015182600260200201518360036020020151846004602002015185600560200201519650965096509650965096505096509650965096509650969050565b600080600080516020610da8833981519152838609600080516020610da883398151915284860991509150935093915050565b60008080610b4e600080516020610da883398151915280878809600080516020610da883398151915287880908600080516020610da8833981519152610bbc565b9050600080516020610da8833981519152818609600080516020610da8833981519152828609610b8c90600080516020610da8833981519152610d80565b92509250509250929050565b60008180610ba857610ba8610d48565b610bb28484610d80565b8508949350505050565b60008060405160208152602080820152602060408201528460608201526002840360808201528360a082015260208160c08360056107d05a03fa90519250905080610c495760405162461bcd60e51b815260206004820152601a60248201527f6572726f722077697468206d6f64756c617220696e766572736500000000000060448201526064016101f1565b5092915050565b6040518060c001604052806006906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b600080600080600080600080610100898b031215610ca957600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b600080600080600060a08688031215610cf957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b602080825260129082015271706f696e74206e6f7420696e20637572766560701b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082610d7b57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610da157634e487b7160e01b600052601160045260246000fd5b9291505056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47a264697066735822122024dcb3a9296b82f91b23679c198173b7089b6e2bf33b84c731f25089bfd8b7e964736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061006d5760003560e01c80635120675214610072578063779d890d146100ac578063783bde80146100c05780639b0c399a146100e7578063ad50f9c11461010e578063cbe96a5014610135578063defbcdee14610168575b600080fd5b6100997f1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d81565b6040519081526020015b60405180910390f35b600080516020610da8833981519152610099565b6100997f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c281565b6100997f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed81565b6100997f275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec81565b610148610143366004610c8c565b61017b565b6040805194855260208501939093529183015260608201526080016100a3565b610148610176366004610ce1565b61031a565b60008080808b15801561018c57508a155b8015610196575089155b80156101a0575088155b1561020a57871580156101b1575086155b80156101bb575085155b80156101c5575084155b6101fa576101d5888888886103b1565b6101fa5760405162461bcd60e51b81526004016101f190610d1c565b60405180910390fd5b508692508591508490508361030b565b87158015610216575086155b8015610220575085155b801561022a575084155b156102675761023b8c8c8c8c6103b1565b6102575760405162461bcd60e51b81526004016101f190610d1c565b508a92508991508890508761030b565b6102738c8c8c8c6103b1565b61028f5760405162461bcd60e51b81526004016101f190610d1c565b61029b888888886103b1565b6102b75760405162461bcd60e51b81526004016101f190610d1c565b60006102d18d8d8d8d600160008f8f8f8f60016000610466565b90506103018160005b602090810291909101519083015160408401516060850151608086015160a08701516106f1565b9450945094509450505b98509850985098945050505050565b600080808060018815801561032d575087155b8015610337575086155b8015610341575085155b15610355575060019750879550600061037d565b610361898989896103b1565b61037d5760405162461bcd60e51b81526004016101f190610d1c565b600061038f8b8b8b8b8b87600061075c565b905061039c8160006102da565b929e919d509b50909950975050505050505050565b60008060008060006103c5878789896107df565b90945092506103d6898981816107df565b90925090506103e782828b8b6107df565b90925090506103f884848484610850565b909450925061044884847f2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e57e9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2610850565b909450925083158015610459575082155b9998505050505050505050565b61046e610c50565b8815801561047a575087155b156104bc578686868686868660005b60a089019290925260808801929092526060870192909252604086019290925260208581019390935290910201526106e1565b821580156104c8575081155b156104db578c8c8c8c8c8c866000610489565b6104e785858b8b6107df565b90955093506104f88b8b85856107df565b6060830152604082015261050e87878b8b6107df565b909750955061051f8d8d85856107df565b60a0830152608082018190528714801561053c575060a081015186145b15610581576040810151851480156105575750606081015184145b156105725761056a8d8d8d8d8d8d610892565b866000610489565b60016000818180808681610489565b61058d898985856107df565b90935091506105ad858583600260200201518460035b6020020151610850565b909d509b506105c887878360045b60200201518460056105a3565b909b5099506105d98b8b81816107df565b90995097506105fa89898360045b60200201518460055b60200201516107df565b909550935061060b89898d8d6107df565b909950975061061c898985856107df565b60a083015260808201526106328d8d81816107df565b9097509550610643878785856107df565b909750955061065487878b8b610850565b909750955061066585856002610ada565b909350915061067687878585610850565b90975095506106878b8b89896107df565b6020830152815261069a85858989610850565b909b5099506106ab8d8d8d8d6107df565b909b5099506106c5898983600260200201518460036105f0565b909d509b506106d68b8b8f8f610850565b606083015260408201525b9c9b505050505050505050505050565b600080600080600080610702610c6e565b61070c8989610b0d565b909350915061071d8d8d85856107df565b602083015281526107308b8b85856107df565b60608301819052604083018290528251602090930151929f929e50909c509a5098505050505050505050565b610764610c50565b87156107d45760018816156107a5578051602082015160408301516060840151608085015160a08601516107a29594939291908d8d8d8d8d8d610466565b90505b6107b3878787878787610892565b949b509299509097509550935091506107cd600289610d5e565b9750610764565b979650505050505050565b60008061081d600080516020610da8833981519152858809600080516020610da8833981519152858809600080516020610da8833981519152610b98565b600080516020610da883398151915280868809600080516020610da8833981519152868a09089150915094509492505050565b60008061086c8685600080516020610da8833981519152610b98565b6108858685600080516020610da8833981519152610b98565b9150915094509492505050565b6000806000806000806108a3610c50565b6108af8d8d6003610ada565b602083018190528183526108c591908f8f6107df565b602083015281526108d88b8b8b8b6107df565b90995097506108e98d8d8d8d6107df565b606083015260408201819052610909908260035b60200201518b8b6107df565b60608301526040820152805161092c908260015b602002015183518460016105f0565b6040830151919e509c5061094a908260035b60200201516008610ada565b60a083015260808201526109618d8d8360046105bb565b909d509b50610972898981816107df565b60a083015260808201526040810151606082015161099291906004610ada565b60608301819052604083018290526109ac91908f8f610850565b6060830152604082018190526109c49082600361091d565b606083015260408201526109da8b8b6008610ada565b602083018190528183526109f091908d8d6107df565b60208301819052818352610a0791908360046105e7565b602083015280825260408201516060830151610a25928460016105a3565b60608301526040820152610a3b8d8d6002610ada565b6020830152808252610a4f908260016108fd565b60208301528152610a6389898360046105e7565b60a083015260808201819052610a7b9082600561093e565b826004602002018360056020020191909152528060006020020151816001602002015182600260200201518360036020020151846004602002015185600560200201519650965096509650965096505096509650965096509650969050565b600080600080516020610da8833981519152838609600080516020610da883398151915284860991509150935093915050565b60008080610b4e600080516020610da883398151915280878809600080516020610da883398151915287880908600080516020610da8833981519152610bbc565b9050600080516020610da8833981519152818609600080516020610da8833981519152828609610b8c90600080516020610da8833981519152610d80565b92509250509250929050565b60008180610ba857610ba8610d48565b610bb28484610d80565b8508949350505050565b60008060405160208152602080820152602060408201528460608201526002840360808201528360a082015260208160c08360056107d05a03fa90519250905080610c495760405162461bcd60e51b815260206004820152601a60248201527f6572726f722077697468206d6f64756c617220696e766572736500000000000060448201526064016101f1565b5092915050565b6040518060c001604052806006906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b600080600080600080600080610100898b031215610ca957600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b600080600080600060a08688031215610cf957600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b602080825260129082015271706f696e74206e6f7420696e20637572766560701b604082015260600190565b634e487b7160e01b600052601260045260246000fd5b600082610d7b57634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610da157634e487b7160e01b600052601160045260246000fd5b9291505056fe30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47a264697066735822122024dcb3a9296b82f91b23679c198173b7089b6e2bf33b84c731f25089bfd8b7e964736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var MerkleArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"Merkle\",\n \"sourceName\": \"contracts/common/Merkle.sol\",\n \"abi\": [],\n \"bytecode\": \"0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220eeab68a149534820e1fc8be8e5a499f3c286d335c0406923df5f8dbafe7db56b64736f6c63430008130033\",\n \"deployedBytecode\": \"0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220eeab68a149534820e1fc8be8e5a499f3c286d335c0406923df5f8dbafe7db56b64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var CheckpointManagerArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"CheckpointManager\",\n \"sourceName\": \"contracts/root/CheckpointManager.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DOMAIN\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"bls\",\n \"outputs\": [\n {\n \"internalType\": \"contract IBLS\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"bn256G2\",\n \"outputs\": [\n {\n \"internalType\": \"contract IBN256G2\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"chainId\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"checkpointBlockNumbers\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"checkpoints\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"eventRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentCheckpointBlockNumber\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentEpoch\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"currentValidatorSet\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentValidatorSetHash\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentValidatorSetLength\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getCheckpointBlock\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"leaf\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"getEventMembershipByBlockNumber\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"leaf\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"getEventMembershipByEpoch\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getEventRootByBlock\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IBLS\",\n \"name\": \"newBls\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"contract IBN256G2\",\n \"name\": \"newBn256G2\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"chainId_\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Validator[]\",\n \"name\": \"newValidatorSet\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"blockHash\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockRound\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"currentValidatorSetHash\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.CheckpointMetadata\",\n \"name\": \"checkpointMetadata\",\n \"type\": \"tuple\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epoch\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"eventRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Checkpoint\",\n \"name\": \"checkpoint\",\n \"type\": \"tuple\"\n },\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"_address\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"votingPower\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct ICheckpointManager.Validator[]\",\n \"name\": \"newValidatorSet\",\n \"type\": \"tuple[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"bitmap\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"submit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalVotingPower\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506116f2806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806376671808116100a2578063babd4ee411610071578063babd4ee4146102c8578063d4c8e3e8146102db578063e416d677146102ee578063e9193d2b146102f7578063f896f1a51461030a57600080fd5b8063766718081461024157806395b0b0271461024a5780639a8a059214610275578063b8a242521461027e57600080fd5b806361a02208116100e957806361a022081461019b578063671b3793146101be5780636969a25c146101c7578063729e7c6e1461021957806373cb1a111461022c57600080fd5b80631d1d4f261461011b57806322fd1818146101375780633569ed931461016157806352a9674b14610174575b600080fd5b61012460035481565b6040519081526020015b60405180910390f35b61014a610145366004610fdb565b610313565b60408051921515835260208301919091520161012e565b61012461016f366004610fdb565b610364565b6101247fbee7fa562a38908559e4a988e62d6c08b84ef05f2ebd5d2bb2b855dc19d19fe281565b6101ae6101a9366004610ff4565b610398565b604051901515815260200161012e565b61012460055481565b6101fa6101d5366004610fdb565b600960205260009081526040902080546005909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161012e565b6101ae610227366004610ff4565b610410565b61023f61023a3660046110e8565b610469565b005b61012460025481565b60065461025d906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b61012460015481565b6102ad61028c366004610fdb565b60086020526000908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161012e565b61023f6102d6366004611173565b6105bb565b60075461025d906001600160a01b031681565b61012460045481565b610124610305366004610fdb565b610820565b610124600b5481565b60008080610322600a85610841565b600a54909150810361033a5750600093849350915050565b6001600a828154811061034f5761034f61124c565b90600052602060002001549250925050915091565b6000600881610374600a85610841565b61037f906001611278565b8152602001908152602001600020600201549050919050565b6000806103a487610364565b9050806103f85760405162461bcd60e51b815260206004820152601e60248201527f4e4f5f4556454e545f524f4f545f464f525f424c4f434b5f4e554d424552000060448201526064015b60405180910390fd5b61040586868387876108f0565b979650505050505050565b600085815260086020526040812060020154806103f85760405162461bcd60e51b815260206004820152601760248201527609c9ebe8aac8a9ca8bea49e9ea8be8c9ea4be8aa09e869604b1b60448201526064016103ef565b600054610100900460ff16158080156104895750600054600160ff909116105b806104a35750303b1580156104a3575060005460ff166001145b6105065760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103ef565b6000805460ff191660011790558015610529576000805461ff0019166101001790555b6001849055600680546001600160a01b038089166001600160a01b0319928316179092556007805492881692909116919091179055600382905561056d8383610a45565b80156105b3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b8660400135600b54146106105760405162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f56414c494441544f525f5345545f4841534800000000000060448201526064016103ef565b6000600154876020013589600001358a602001358a600001358b604001358d604001358b8b60405160200161064692919061128b565b604051602081830303815290604052805190602001206040516020016106739897969594939291906112ee565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529082905260065463a850a90960e01b835290925061073f916001600160a01b039091169063a850a909906106f7907fbee7fa562a38908559e4a988e62d6c08b84ef05f2ebd5d2bb2b855dc19d19fe2908690600401611324565b6040805180830381865afa158015610713573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610737919061137a565b878585610b4b565b60025461074c8189610e55565b8735600081815260086020908152604091829020838155908b01356001820155908a01356002909101558110156107cf57600a8054600181018255600091825260208a01357fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890910155600280549091906107c690611408565b90915550610803565b600a805460208a013591906107e690600190611421565b815481106107f6576107f661124c565b6000918252602090912001555b60208801356004556108158686610a45565b505050505050505050565b600a818154811061083057600080fd5b600091825260209091200154905081565b81546000908103610854575060006108ea565b82546000905b808210156108a157600061086e8383610f32565b6000878152602090209091508590820154111561088d5780915061089b565b610898816001611278565b92505b5061085a565b6000821180156108cd5750836108ca866108bc600186611421565b600091825260209091200190565b54145b156108e6576108dd600183611421565b925050506108ea565b5090505b92915050565b6000816108fe816002611518565b86106109415760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b60448201526064016103ef565b8661097d5760405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa622a0a360a11b60448201526064016103ef565b8660005b82811015610a3757600086868381811061099d5761099d61124c565b9050602002013590506002896109b3919061153a565b6000036109eb576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a18565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b610a2360028a61154e565b98505080610a3090611408565b9050610981565b509094149695505050505050565b60038190556040518190610a5f908490839060200161128b565b60408051601f198184030181529190528051602090910120600b556000805b82811015610b42576000858583818110610a9a57610a9a61124c565b905060c0020160a00135905060008111610aea5760405162461bcd60e51b8152602060048201526011602482015270564f54494e475f504f5745525f5a45524f60781b60448201526064016103ef565b610af48184611278565b9250858583818110610b0857610b0861124c565b905060c00201600960008481526020019081526020016000208181610b2d9190611579565b9050505080610b3b90611408565b9050610a7e565b50600555505050565b600354610b56610fbd565b6000805b83811015610cda57610b6d868683610f54565b15610cd25781600003610bc1576000818152600960205260409081902081516080810190925260010160048282826020028201915b815481526020019060010190808311610ba25750505050509250610cb3565b60008181526009602052604080822081516080810190925260010160048282826020028201915b815481526020019060010190808311610be857505060075488516020808b01516040808d01516060808f01518b51958c0151848d0151928d01519451630cbe96a560e41b81529c9d506001600160a01b039098169b63cbe96a509b50610c5f9a5096985093969195939493919290916004016112ee565b608060405180830381865afa158015610c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca091906115d8565b6060880152604087015260208601528452505b600081815260096020526040902060050154610ccf9083611278565b91505b600101610b5a565b5080600003610d1d5760405162461bcd60e51b815260206004820152600f60248201526e4249544d41505f49535f454d50545960881b60448201526064016103ef565b60036005546002610d2e9190611562565b610d38919061154e565b8111610d825760405162461bcd60e51b815260206004820152601960248201527824a729aaa32324a1a4a2a72a2fab27aa24a723afa827aba2a960391b60448201526064016103ef565b60065460405163ebbdac9160e01b815260009182916001600160a01b039091169063ebbdac9190610dbb908b9088908e9060040161160e565b6040805180830381865afa158015610dd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfb9190611689565b91509150818015610e095750805b6108155760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c454400000060448201526064016103ef565b600082815260086020908152604091829020825160608101845281548082526001830154938201939093526002909101549281019290925282351480610ea757508051610ea3906001611278565b8235145b610ee35760405162461bcd60e51b815260206004820152600d60248201526c0929cac82989288be8aa09e869609b1b60448201526064016103ef565b8060200151826020013511610f2d5760405162461bcd60e51b815260206004820152601060248201526f115354151657d0d21150d2d413d2539560821b60448201526064016103ef565b505050565b6000610f41600284841861154e565b610f4d90848416611278565b9392505050565b600080610f6260088461154e565b90506000610f7160088561153a565b9050848210610f8557600092505050610f4d565b6000600160ff83161b878785818110610fa057610fa061124c565b9050013560f81c60f81b60f81c60ff161611925050509392505050565b60405180608001604052806004906020820280368337509192915050565b600060208284031215610fed57600080fd5b5035919050565b60008060008060006080868803121561100c57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8082111561103957600080fd5b818801915088601f83011261104d57600080fd5b81358181111561105c57600080fd5b8960208260051b850101111561107157600080fd5b9699959850939650602001949392505050565b6001600160a01b038116811461109957600080fd5b50565b60008083601f8401126110ae57600080fd5b50813567ffffffffffffffff8111156110c657600080fd5b60208301915083602060c0830285010111156110e157600080fd5b9250929050565b60008060008060006080868803121561110057600080fd5b853561110b81611084565b9450602086013561111b81611084565b935060408601359250606086013567ffffffffffffffff81111561113e57600080fd5b61114a8882890161109c565b969995985093965092949392505050565b60006060828403121561116d57600080fd5b50919050565b6000806000806000806000610140888a03121561118f57600080fd5b611199898961115b565b96506111a88960608a0161115b565b95506101008801898111156111bc57600080fd5b60c0890195503567ffffffffffffffff808211156111d957600080fd5b6111e58b838c0161109c565b90965094506101208a01359150808211156111ff57600080fd5b818a0191508a601f83011261121357600080fd5b81358181111561122257600080fd5b8b602082850101111561123457600080fd5b60208301945080935050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156108ea576108ea611262565b60208082528181018390526000908460408401835b868110156112e35782356112b381611084565b6001600160a01b0316825260808385018584013760a0838101359083015260c092830192909101906001016112a0565b509695505050505050565b978852602088019690965260408701949094526060860192909252608085015260a084015260c083015260e08201526101000190565b82815260006020604081840152835180604085015260005b818110156113585785810183015185820160600152820161133c565b506000606082860101526060601f19601f830116850101925050509392505050565b60006040828403121561138c57600080fd5b82601f83011261139b57600080fd5b6040516040810181811067ffffffffffffffff821117156113cc57634e487b7160e01b600052604160045260246000fd5b80604052508060408401858111156113e357600080fd5b845b818110156113fd5780518352602092830192016113e5565b509195945050505050565b60006001820161141a5761141a611262565b5060010190565b818103818111156108ea576108ea611262565b600181815b8085111561146f57816000190482111561145557611455611262565b8085161561146257918102915b93841c9390800290611439565b509250929050565b600082611486575060016108ea565b81611493575060006108ea565b81600181146114a957600281146114b3576114cf565b60019150506108ea565b60ff8411156114c4576114c4611262565b50506001821b6108ea565b5060208310610133831016604e8410600b84101617156114f2575081810a6108ea565b6114fc8383611434565b806000190482111561151057611510611262565b029392505050565b6000610f4d8383611477565b634e487b7160e01b600052601260045260246000fd5b60008261154957611549611524565b500690565b60008261155d5761155d611524565b500490565b80820281158282048414176108ea576108ea611262565b813561158481611084565b81546001600160a01b0319166001600160a01b0391909116178155602082810160005b60048110156115c7578135600182860181019190915591830191016115a7565b50505060a082013560058201555050565b600080600080608085870312156115ee57600080fd5b505082516020840151604085015160609095015191969095509092509050565b61010081016040858337604082018460005b600481101561163f578151835260209283019290910190600101611620565b50505060c082018360005b600281101561166957815183526020928301929091019060010161164a565b505050949350505050565b8051801515811461168457600080fd5b919050565b6000806040838503121561169c57600080fd5b6116a583611674565b91506116b360208401611674565b9050925092905056fea2646970667358221220d095a39e3b93e017f00f9714cc6e9b2280742361a1a5f6c69775bcc0c3c154e964736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101165760003560e01c806376671808116100a2578063babd4ee411610071578063babd4ee4146102c8578063d4c8e3e8146102db578063e416d677146102ee578063e9193d2b146102f7578063f896f1a51461030a57600080fd5b8063766718081461024157806395b0b0271461024a5780639a8a059214610275578063b8a242521461027e57600080fd5b806361a02208116100e957806361a022081461019b578063671b3793146101be5780636969a25c146101c7578063729e7c6e1461021957806373cb1a111461022c57600080fd5b80631d1d4f261461011b57806322fd1818146101375780633569ed931461016157806352a9674b14610174575b600080fd5b61012460035481565b6040519081526020015b60405180910390f35b61014a610145366004610fdb565b610313565b60408051921515835260208301919091520161012e565b61012461016f366004610fdb565b610364565b6101247fbee7fa562a38908559e4a988e62d6c08b84ef05f2ebd5d2bb2b855dc19d19fe281565b6101ae6101a9366004610ff4565b610398565b604051901515815260200161012e565b61012460055481565b6101fa6101d5366004610fdb565b600960205260009081526040902080546005909101546001600160a01b039091169082565b604080516001600160a01b03909316835260208301919091520161012e565b6101ae610227366004610ff4565b610410565b61023f61023a3660046110e8565b610469565b005b61012460025481565b60065461025d906001600160a01b031681565b6040516001600160a01b03909116815260200161012e565b61012460015481565b6102ad61028c366004610fdb565b60086020526000908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161012e565b61023f6102d6366004611173565b6105bb565b60075461025d906001600160a01b031681565b61012460045481565b610124610305366004610fdb565b610820565b610124600b5481565b60008080610322600a85610841565b600a54909150810361033a5750600093849350915050565b6001600a828154811061034f5761034f61124c565b90600052602060002001549250925050915091565b6000600881610374600a85610841565b61037f906001611278565b8152602001908152602001600020600201549050919050565b6000806103a487610364565b9050806103f85760405162461bcd60e51b815260206004820152601e60248201527f4e4f5f4556454e545f524f4f545f464f525f424c4f434b5f4e554d424552000060448201526064015b60405180910390fd5b61040586868387876108f0565b979650505050505050565b600085815260086020526040812060020154806103f85760405162461bcd60e51b815260206004820152601760248201527609c9ebe8aac8a9ca8bea49e9ea8be8c9ea4be8aa09e869604b1b60448201526064016103ef565b600054610100900460ff16158080156104895750600054600160ff909116105b806104a35750303b1580156104a3575060005460ff166001145b6105065760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103ef565b6000805460ff191660011790558015610529576000805461ff0019166101001790555b6001849055600680546001600160a01b038089166001600160a01b0319928316179092556007805492881692909116919091179055600382905561056d8383610a45565b80156105b3576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b8660400135600b54146106105760405162461bcd60e51b815260206004820152601a60248201527f494e56414c49445f56414c494441544f525f5345545f4841534800000000000060448201526064016103ef565b6000600154876020013589600001358a602001358a600001358b604001358d604001358b8b60405160200161064692919061128b565b604051602081830303815290604052805190602001206040516020016106739897969594939291906112ee565b60408051601f198184030181528282528051602091820120908301520160408051601f198184030181529082905260065463a850a90960e01b835290925061073f916001600160a01b039091169063a850a909906106f7907fbee7fa562a38908559e4a988e62d6c08b84ef05f2ebd5d2bb2b855dc19d19fe2908690600401611324565b6040805180830381865afa158015610713573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610737919061137a565b878585610b4b565b60025461074c8189610e55565b8735600081815260086020908152604091829020838155908b01356001820155908a01356002909101558110156107cf57600a8054600181018255600091825260208a01357fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a890910155600280549091906107c690611408565b90915550610803565b600a805460208a013591906107e690600190611421565b815481106107f6576107f661124c565b6000918252602090912001555b60208801356004556108158686610a45565b505050505050505050565b600a818154811061083057600080fd5b600091825260209091200154905081565b81546000908103610854575060006108ea565b82546000905b808210156108a157600061086e8383610f32565b6000878152602090209091508590820154111561088d5780915061089b565b610898816001611278565b92505b5061085a565b6000821180156108cd5750836108ca866108bc600186611421565b600091825260209091200190565b54145b156108e6576108dd600183611421565b925050506108ea565b5090505b92915050565b6000816108fe816002611518565b86106109415760405162461bcd60e51b81526020600482015260126024820152710929cac82989288be988a828cbe929c888ab60731b60448201526064016103ef565b8661097d5760405162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa622a0a360a11b60448201526064016103ef565b8660005b82811015610a3757600086868381811061099d5761099d61124c565b9050602002013590506002896109b3919061153a565b6000036109eb576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a18565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b610a2360028a61154e565b98505080610a3090611408565b9050610981565b509094149695505050505050565b60038190556040518190610a5f908490839060200161128b565b60408051601f198184030181529190528051602090910120600b556000805b82811015610b42576000858583818110610a9a57610a9a61124c565b905060c0020160a00135905060008111610aea5760405162461bcd60e51b8152602060048201526011602482015270564f54494e475f504f5745525f5a45524f60781b60448201526064016103ef565b610af48184611278565b9250858583818110610b0857610b0861124c565b905060c00201600960008481526020019081526020016000208181610b2d9190611579565b9050505080610b3b90611408565b9050610a7e565b50600555505050565b600354610b56610fbd565b6000805b83811015610cda57610b6d868683610f54565b15610cd25781600003610bc1576000818152600960205260409081902081516080810190925260010160048282826020028201915b815481526020019060010190808311610ba25750505050509250610cb3565b60008181526009602052604080822081516080810190925260010160048282826020028201915b815481526020019060010190808311610be857505060075488516020808b01516040808d01516060808f01518b51958c0151848d0151928d01519451630cbe96a560e41b81529c9d506001600160a01b039098169b63cbe96a509b50610c5f9a5096985093969195939493919290916004016112ee565b608060405180830381865afa158015610c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca091906115d8565b6060880152604087015260208601528452505b600081815260096020526040902060050154610ccf9083611278565b91505b600101610b5a565b5080600003610d1d5760405162461bcd60e51b815260206004820152600f60248201526e4249544d41505f49535f454d50545960881b60448201526064016103ef565b60036005546002610d2e9190611562565b610d38919061154e565b8111610d825760405162461bcd60e51b815260206004820152601960248201527824a729aaa32324a1a4a2a72a2fab27aa24a723afa827aba2a960391b60448201526064016103ef565b60065460405163ebbdac9160e01b815260009182916001600160a01b039091169063ebbdac9190610dbb908b9088908e9060040161160e565b6040805180830381865afa158015610dd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfb9190611689565b91509150818015610e095750805b6108155760405162461bcd60e51b815260206004820152601d60248201527f5349474e41545552455f564552494649434154494f4e5f4641494c454400000060448201526064016103ef565b600082815260086020908152604091829020825160608101845281548082526001830154938201939093526002909101549281019290925282351480610ea757508051610ea3906001611278565b8235145b610ee35760405162461bcd60e51b815260206004820152600d60248201526c0929cac82989288be8aa09e869609b1b60448201526064016103ef565b8060200151826020013511610f2d5760405162461bcd60e51b815260206004820152601060248201526f115354151657d0d21150d2d413d2539560821b60448201526064016103ef565b505050565b6000610f41600284841861154e565b610f4d90848416611278565b9392505050565b600080610f6260088461154e565b90506000610f7160088561153a565b9050848210610f8557600092505050610f4d565b6000600160ff83161b878785818110610fa057610fa061124c565b9050013560f81c60f81b60f81c60ff161611925050509392505050565b60405180608001604052806004906020820280368337509192915050565b600060208284031215610fed57600080fd5b5035919050565b60008060008060006080868803121561100c57600080fd5b853594506020860135935060408601359250606086013567ffffffffffffffff8082111561103957600080fd5b818801915088601f83011261104d57600080fd5b81358181111561105c57600080fd5b8960208260051b850101111561107157600080fd5b9699959850939650602001949392505050565b6001600160a01b038116811461109957600080fd5b50565b60008083601f8401126110ae57600080fd5b50813567ffffffffffffffff8111156110c657600080fd5b60208301915083602060c0830285010111156110e157600080fd5b9250929050565b60008060008060006080868803121561110057600080fd5b853561110b81611084565b9450602086013561111b81611084565b935060408601359250606086013567ffffffffffffffff81111561113e57600080fd5b61114a8882890161109c565b969995985093965092949392505050565b60006060828403121561116d57600080fd5b50919050565b6000806000806000806000610140888a03121561118f57600080fd5b611199898961115b565b96506111a88960608a0161115b565b95506101008801898111156111bc57600080fd5b60c0890195503567ffffffffffffffff808211156111d957600080fd5b6111e58b838c0161109c565b90965094506101208a01359150808211156111ff57600080fd5b818a0191508a601f83011261121357600080fd5b81358181111561122257600080fd5b8b602082850101111561123457600080fd5b60208301945080935050505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b808201808211156108ea576108ea611262565b60208082528181018390526000908460408401835b868110156112e35782356112b381611084565b6001600160a01b0316825260808385018584013760a0838101359083015260c092830192909101906001016112a0565b509695505050505050565b978852602088019690965260408701949094526060860192909252608085015260a084015260c083015260e08201526101000190565b82815260006020604081840152835180604085015260005b818110156113585785810183015185820160600152820161133c565b506000606082860101526060601f19601f830116850101925050509392505050565b60006040828403121561138c57600080fd5b82601f83011261139b57600080fd5b6040516040810181811067ffffffffffffffff821117156113cc57634e487b7160e01b600052604160045260246000fd5b80604052508060408401858111156113e357600080fd5b845b818110156113fd5780518352602092830192016113e5565b509195945050505050565b60006001820161141a5761141a611262565b5060010190565b818103818111156108ea576108ea611262565b600181815b8085111561146f57816000190482111561145557611455611262565b8085161561146257918102915b93841c9390800290611439565b509250929050565b600082611486575060016108ea565b81611493575060006108ea565b81600181146114a957600281146114b3576114cf565b60019150506108ea565b60ff8411156114c4576114c4611262565b50506001821b6108ea565b5060208310610133831016604e8410600b84101617156114f2575081810a6108ea565b6114fc8383611434565b806000190482111561151057611510611262565b029392505050565b6000610f4d8383611477565b634e487b7160e01b600052601260045260246000fd5b60008261154957611549611524565b500690565b60008261155d5761155d611524565b500490565b80820281158282048414176108ea576108ea611262565b813561158481611084565b81546001600160a01b0319166001600160a01b0391909116178155602082810160005b60048110156115c7578135600182860181019190915591830191016115a7565b50505060a082013560058201555050565b600080600080608085870312156115ee57600080fd5b505082516020840151604085015160609095015191969095509092509050565b61010081016040858337604082018460005b600481101561163f578151835260209283019290910190600101611620565b50505060c082018360005b600281101561166957815183526020928301929091019060010161164a565b505050949350505050565b8051801515811461168457600080fd5b919050565b6000806040838503121561169c57600080fd5b6116a583611674565b91506116b360208401611674565b9050925092905056fea2646970667358221220d095a39e3b93e017f00f9714cc6e9b2280742361a1a5f6c69775bcc0c3c154e964736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ExitHelperArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ExitHelper\",\n \"sourceName\": \"contracts/root/ExitHelper.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bool\",\n \"name\": \"success\",\n \"type\": \"bool\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"returnData\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"ExitProcessed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"unhashedLeaf\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"internalType\": \"struct IExitHelper.BatchExitInput[]\",\n \"name\": \"inputs\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"batchExit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"checkpointManager\",\n \"outputs\": [\n {\n \"internalType\": \"contract ICheckpointManager\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"blockNumber\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"leafIndex\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"unhashedLeaf\",\n \"type\": \"bytes\"\n },\n {\n \"internalType\": \"bytes32[]\",\n \"name\": \"proof\",\n \"type\": \"bytes32[]\"\n }\n ],\n \"name\": \"exit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract ICheckpointManager\",\n \"name\": \"newCheckpointManager\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"processedExits\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610b62806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806350607b351461005c578063aa209cc314610071578063bd88ea7914610084578063c0857ba0146100bc578063c4d66de8146100e7575b600080fd5b61006f61006a3660046106c9565b6100fa565b005b61006f61007f36600461070b565b610200565b6100a76100923660046107bc565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6002546100cf906001600160a01b031681565b6040516001600160a01b0390911681526020016100b3565b61006f6100f53660046107ed565b610240565b6002546001600160a01b031661012b5760405162461bcd60e51b815260040161012290610811565b60405180910390fd5b8060005b818110156101fa576101f284848381811061014c5761014c610848565b905060200281019061015e919061085e565b3585858481811061017157610171610848565b9050602002810190610183919061085e565b6020013586868581811061019957610199610848565b90506020028101906101ab919061085e565b6101b990604081019061087e565b8888878181106101cb576101cb610848565b90506020028101906101dd919061085e565b6101eb9060608101906108c5565b60016103d2565b60010161012f565b50505050565b6002546001600160a01b03166102285760405162461bcd60e51b815260040161012290610811565b61023886868686868660006103d2565b505050505050565b600054610100900460ff16158080156102605750600054600160ff909116105b8061027a5750303b15801561027a575060005460ff166001145b6102dd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610122565b6000805460ff191660011790558015610300576000805461ff0019166101001790555b6001600160a01b0382161580159061032157506001600160a01b0382163b15155b61036d5760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a20494e56414c49445f4144445245535300000000006044820152606401610122565b600280546001600160a01b0319166001600160a01b03841617905580156103ce576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60008080806103e3888a018a610925565b935093509350935084156104165760008481526001602052604090205460ff16156104115750505050610674565b610480565b60008481526001602052604090205460ff16156104805760405162461bcd60e51b815260206004820152602260248201527f4578697448656c7065723a20455849545f414c52454144595f50524f43455353604482015261115160f21b6064820152608401610122565b6002546040516001600160a01b03909116906361a02208908d906104a7908d908d90610a05565b6040519081900381206001600160e01b031960e085901b1682526104d492918f908d908d90600401610a15565b602060405180830381865afa1580156104f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105159190610a62565b61055d5760405162461bcd60e51b815260206004820152601960248201527822bc34ba2432b63832b91d1024a72b20a624a22fa82927a7a360391b6044820152606401610122565b6000848152600160208190526040808320805460ff19169092179091555181906001600160a01b0385169061059a90889088908790602401610ad4565b60408051601f198184030181529181526020820180516001600160e01b031663f43cda8b60e01b179052516105cf9190610b07565b6000604051808303816000865af19150503d806000811461060c576040519150601f19603f3d011682016040523d82523d6000602084013e610611565b606091505b509150915081610632576000868152600160205260409020805460ff191690555b811515867f8bbfa0c9bee3785c03700d2a909592286efb83fc7e7002be5764424b9842f7ec836040516106659190610b19565b60405180910390a35050505050505b50505050505050565b60008083601f84011261068f57600080fd5b50813567ffffffffffffffff8111156106a757600080fd5b6020830191508360208260051b85010111156106c257600080fd5b9250929050565b600080602083850312156106dc57600080fd5b823567ffffffffffffffff8111156106f357600080fd5b6106ff8582860161067d565b90969095509350505050565b6000806000806000806080878903121561072457600080fd5b8635955060208701359450604087013567ffffffffffffffff8082111561074a57600080fd5b818901915089601f83011261075e57600080fd5b81358181111561076d57600080fd5b8a602082850101111561077f57600080fd5b60208301965080955050606089013591508082111561079d57600080fd5b506107aa89828a0161067d565b979a9699509497509295939492505050565b6000602082840312156107ce57600080fd5b5035919050565b6001600160a01b03811681146107ea57600080fd5b50565b6000602082840312156107ff57600080fd5b813561080a816107d5565b9392505050565b6020808252601b908201527f4578697448656c7065723a204e4f545f494e495449414c495a45440000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261087457600080fd5b9190910192915050565b6000808335601e1984360301811261089557600080fd5b83018035915067ffffffffffffffff8211156108b057600080fd5b6020019150368190038213156106c257600080fd5b6000808335601e198436030181126108dc57600080fd5b83018035915067ffffffffffffffff8211156108f757600080fd5b6020019150600581901b36038213156106c257600080fd5b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561093b57600080fd5b84359350602085013561094d816107d5565b9250604085013561095d816107d5565b9150606085013567ffffffffffffffff8082111561097a57600080fd5b818701915087601f83011261098e57600080fd5b8135818111156109a0576109a061090f565b604051601f8201601f19908116603f011681019083821181831017156109c8576109c861090f565b816040528281528a60208487010111156109e157600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b85815284602082015283604082015260806060820152816080820152600060018060fb1b03831115610a4657600080fd5b8260051b808560a08501379190910160a0019695505050505050565b600060208284031215610a7457600080fd5b8151801515811461080a57600080fd5b60005b83811015610a9f578181015183820152602001610a87565b50506000910152565b60008151808452610ac0816020860160208601610a84565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090610afe90830184610aa8565b95945050505050565b60008251610874818460208701610a84565b60208152600061080a6020830184610aa856fea2646970667358221220110b70554f8d1ab0b9a239e02f7c81f25da1730583ae343da1033e8e7157258a64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100575760003560e01c806350607b351461005c578063aa209cc314610071578063bd88ea7914610084578063c0857ba0146100bc578063c4d66de8146100e7575b600080fd5b61006f61006a3660046106c9565b6100fa565b005b61006f61007f36600461070b565b610200565b6100a76100923660046107bc565b60016020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b6002546100cf906001600160a01b031681565b6040516001600160a01b0390911681526020016100b3565b61006f6100f53660046107ed565b610240565b6002546001600160a01b031661012b5760405162461bcd60e51b815260040161012290610811565b60405180910390fd5b8060005b818110156101fa576101f284848381811061014c5761014c610848565b905060200281019061015e919061085e565b3585858481811061017157610171610848565b9050602002810190610183919061085e565b6020013586868581811061019957610199610848565b90506020028101906101ab919061085e565b6101b990604081019061087e565b8888878181106101cb576101cb610848565b90506020028101906101dd919061085e565b6101eb9060608101906108c5565b60016103d2565b60010161012f565b50505050565b6002546001600160a01b03166102285760405162461bcd60e51b815260040161012290610811565b61023886868686868660006103d2565b505050505050565b600054610100900460ff16158080156102605750600054600160ff909116105b8061027a5750303b15801561027a575060005460ff166001145b6102dd5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610122565b6000805460ff191660011790558015610300576000805461ff0019166101001790555b6001600160a01b0382161580159061032157506001600160a01b0382163b15155b61036d5760405162461bcd60e51b815260206004820152601b60248201527f4578697448656c7065723a20494e56414c49445f4144445245535300000000006044820152606401610122565b600280546001600160a01b0319166001600160a01b03841617905580156103ce576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b60008080806103e3888a018a610925565b935093509350935084156104165760008481526001602052604090205460ff16156104115750505050610674565b610480565b60008481526001602052604090205460ff16156104805760405162461bcd60e51b815260206004820152602260248201527f4578697448656c7065723a20455849545f414c52454144595f50524f43455353604482015261115160f21b6064820152608401610122565b6002546040516001600160a01b03909116906361a02208908d906104a7908d908d90610a05565b6040519081900381206001600160e01b031960e085901b1682526104d492918f908d908d90600401610a15565b602060405180830381865afa1580156104f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105159190610a62565b61055d5760405162461bcd60e51b815260206004820152601960248201527822bc34ba2432b63832b91d1024a72b20a624a22fa82927a7a360391b6044820152606401610122565b6000848152600160208190526040808320805460ff19169092179091555181906001600160a01b0385169061059a90889088908790602401610ad4565b60408051601f198184030181529181526020820180516001600160e01b031663f43cda8b60e01b179052516105cf9190610b07565b6000604051808303816000865af19150503d806000811461060c576040519150601f19603f3d011682016040523d82523d6000602084013e610611565b606091505b509150915081610632576000868152600160205260409020805460ff191690555b811515867f8bbfa0c9bee3785c03700d2a909592286efb83fc7e7002be5764424b9842f7ec836040516106659190610b19565b60405180910390a35050505050505b50505050505050565b60008083601f84011261068f57600080fd5b50813567ffffffffffffffff8111156106a757600080fd5b6020830191508360208260051b85010111156106c257600080fd5b9250929050565b600080602083850312156106dc57600080fd5b823567ffffffffffffffff8111156106f357600080fd5b6106ff8582860161067d565b90969095509350505050565b6000806000806000806080878903121561072457600080fd5b8635955060208701359450604087013567ffffffffffffffff8082111561074a57600080fd5b818901915089601f83011261075e57600080fd5b81358181111561076d57600080fd5b8a602082850101111561077f57600080fd5b60208301965080955050606089013591508082111561079d57600080fd5b506107aa89828a0161067d565b979a9699509497509295939492505050565b6000602082840312156107ce57600080fd5b5035919050565b6001600160a01b03811681146107ea57600080fd5b50565b6000602082840312156107ff57600080fd5b813561080a816107d5565b9392505050565b6020808252601b908201527f4578697448656c7065723a204e4f545f494e495449414c495a45440000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60008235607e1983360301811261087457600080fd5b9190910192915050565b6000808335601e1984360301811261089557600080fd5b83018035915067ffffffffffffffff8211156108b057600080fd5b6020019150368190038213156106c257600080fd5b6000808335601e198436030181126108dc57600080fd5b83018035915067ffffffffffffffff8211156108f757600080fd5b6020019150600581901b36038213156106c257600080fd5b634e487b7160e01b600052604160045260246000fd5b6000806000806080858703121561093b57600080fd5b84359350602085013561094d816107d5565b9250604085013561095d816107d5565b9150606085013567ffffffffffffffff8082111561097a57600080fd5b818701915087601f83011261098e57600080fd5b8135818111156109a0576109a061090f565b604051601f8201601f19908116603f011681019083821181831017156109c8576109c861090f565b816040528281528a60208487010111156109e157600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b85815284602082015283604082015260806060820152816080820152600060018060fb1b03831115610a4657600080fd5b8260051b808560a08501379190910160a0019695505050505050565b600060208284031215610a7457600080fd5b8151801515811461080a57600080fd5b60005b83811015610a9f578181015183820152602001610a87565b50506000910152565b60008151808452610ac0816020860160208601610a84565b601f01601f19169290920160200192915050565b8381526001600160a01b0383166020820152606060408201819052600090610afe90830184610aa8565b95945050505050565b60008251610874818460208701610a84565b60208152600061080a6020830184610aa856fea2646970667358221220110b70554f8d1ab0b9a239e02f7c81f25da1730583ae343da1033e8e7157258a64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var StateSenderArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"StateSender\",\n \"sourceName\": \"contracts/root/StateSender.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"StateSynced\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAX_LENGTH\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"counter\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"syncState\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610297806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806316f198311461004657806361bc221a1461005b578063a6f9885c14610076575b600080fd5b61005961005436600461017a565b61007f565b005b61006460005481565b60405190815260200160405180910390f35b61006461080081565b6001600160a01b0383166100cd5760405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b60448201526064015b60405180910390fd5b6108008111156101145760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b60448201526064016100c4565b826001600160a01b0316336001600160a01b031660008081546101369061020b565b9190508190557fd1d7f6609674cc5871fdb4b0bcd4f0a214118411de9e38983866514f22659165858560405161016d929190610232565b60405180910390a4505050565b60008060006040848603121561018f57600080fd5b83356001600160a01b03811681146101a657600080fd5b9250602084013567ffffffffffffffff808211156101c357600080fd5b818601915086601f8301126101d757600080fd5b8135818111156101e657600080fd5b8760208285010111156101f857600080fd5b6020830194508093505050509250925092565b60006001820161022b57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122031b7ec2bc87f0234fe89e0f741bc18f51baa2be5cc844033ea10f35e4b86094c64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100415760003560e01c806316f198311461004657806361bc221a1461005b578063a6f9885c14610076575b600080fd5b61005961005436600461017a565b61007f565b005b61006460005481565b60405190815260200160405180910390f35b61006461080081565b6001600160a01b0383166100cd5760405162461bcd60e51b815260206004820152601060248201526f24a72b20a624a22fa922a1a2a4ab22a960811b60448201526064015b60405180910390fd5b6108008111156101145760405162461bcd60e51b815260206004820152601260248201527108ab0868a8a88a6be9a82b0be988a9c8ea8960731b60448201526064016100c4565b826001600160a01b0316336001600160a01b031660008081546101369061020b565b9190508190557fd1d7f6609674cc5871fdb4b0bcd4f0a214118411de9e38983866514f22659165858560405161016d929190610232565b60405180910390a4505050565b60008060006040848603121561018f57600080fd5b83356001600160a01b03811681146101a657600080fd5b9250602084013567ffffffffffffffff808211156101c357600080fd5b818601915086601f8301126101d757600080fd5b8135818111156101e657600080fd5b8760208285010111156101f857600080fd5b6020830194508093505050509250925092565b60006001820161022b57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152816020820152818360408301376000818301604090810191909152601f909201601f1916010191905056fea264697066735822122031b7ec2bc87f0234fe89e0f741bc18f51baa2be5cc844033ea10f35e4b86094c64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var MockERC20Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"MockERC20\",\n \"sourceName\": \"contracts/mocks/MockERC20.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Paused\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"previousAdminRole\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"newAdminRole\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"RoleAdminChanged\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RoleGranted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RoleRevoked\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Unpaused\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEFAULT_ADMIN_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MINTER_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"PAUSER_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burnFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"getRoleAdmin\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"index\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getRoleMember\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"getRoleMemberCount\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"grantRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"hasRole\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pause\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"paused\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"renounceRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"revokeRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"unpause\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x60806040523480156200001157600080fd5b50604080518082018252600480825263151154d560e21b60208084018290528451808601909552918452908301529081816005620000508382620002ca565b5060066200005f8282620002ca565b50506007805460ff191690555062000079600033620000d9565b620000a57f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633620000d9565b620000d17f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33620000d9565b505062000396565b620000e58282620000e9565b5050565b620000f5828262000114565b60008281526001602052604090206200010f9082620001b4565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000e5576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001703390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620001cb836001600160a01b038416620001d4565b90505b92915050565b60008181526001830160205260408120546200021d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620001ce565b506000620001ce565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200025157607f821691505b6020821081036200027257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200010f57600081815260208120601f850160051c81016020861015620002a15750805b601f850160051c820191505b81811015620002c257828155600101620002ad565b505050505050565b81516001600160401b03811115620002e657620002e662000226565b620002fe81620002f784546200023c565b8462000278565b602080601f8311600181146200033657600084156200031d5750858301515b600019600386901b1c1916600185901b178555620002c2565b600085815260208120601f198616915b82811015620003675788860151825594840194600190910190840162000346565b5085821015620003865787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6117fa80620003a66000396000f3fe608060405234801561001057600080fd5b50600436106101845760003560e01c806370a08231116100d9578063a457c2d711610087578063a457c2d714610336578063a9059cbb14610349578063ca15c8731461035c578063d53913931461036f578063d547741f14610396578063dd62ed3e146103a9578063e63ab1e9146103bc57600080fd5b806370a08231146102a457806379cc6790146102cd5780638456cb59146102e05780639010d07c146102e857806391d148541461031357806395d89b4114610326578063a217fddf1461032e57600080fd5b8063313ce56711610136578063313ce5671461023657806336568abe1461024557806339509351146102585780633f4ba83a1461026b57806340c10f191461027357806342966c68146102865780635c975abb1461029957600080fd5b806301ffc9a71461018957806306fdde03146101b1578063095ea7b3146101c657806318160ddd146101d957806323b872dd146101eb578063248a9ca3146101fe5780632f2ff15d14610221575b600080fd5b61019c610197366004611460565b6103d1565b60405190151581526020015b60405180910390f35b6101b96103fc565b6040516101a891906114ae565b61019c6101d43660046114fd565b61048e565b6004545b6040519081526020016101a8565b61019c6101f9366004611527565b6104a6565b6101dd61020c366004611563565b60009081526020819052604090206001015490565b61023461022f36600461157c565b6104ca565b005b604051601281526020016101a8565b61023461025336600461157c565b6104f4565b61019c6102663660046114fd565b610577565b610234610599565b6102346102813660046114fd565b610617565b610234610294366004611563565b6106a4565b60075460ff1661019c565b6101dd6102b23660046115a8565b6001600160a01b031660009081526002602052604090205490565b6102346102db3660046114fd565b6106b1565b6102346106c6565b6102fb6102f63660046115c3565b610740565b6040516001600160a01b0390911681526020016101a8565b61019c61032136600461157c565b61075f565b6101b9610788565b6101dd600081565b61019c6103443660046114fd565b610797565b61019c6103573660046114fd565b610812565b6101dd61036a366004611563565b610820565b6101dd7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102346103a436600461157c565b610837565b6101dd6103b73660046115e5565b61085c565b6101dd60008051602061178583398151915281565b60006001600160e01b03198216635a05180f60e01b14806103f657506103f682610887565b92915050565b60606005805461040b9061160f565b80601f01602080910402602001604051908101604052809291908181526020018280546104379061160f565b80156104845780601f1061045957610100808354040283529160200191610484565b820191906000526020600020905b81548152906001019060200180831161046757829003601f168201915b5050505050905090565b60003361049c8185856108bc565b5060019392505050565b6000336104b48582856109e0565b6104bf858585610a5a565b506001949350505050565b6000828152602081905260409020600101546104e581610bfe565b6104ef8383610c08565b505050565b6001600160a01b03811633146105695760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6105738282610c2a565b5050565b60003361049c81858561058a838361085c565b610594919061165f565b6108bc565b6105b16000805160206117858339815191523361075f565b61060d5760405162461bcd60e51b8152602060048201526039602482015260008051602061176583398151915260448201527876652070617573657220726f6c6520746f20756e706175736560381b6064820152608401610560565b610615610c4c565b565b6106417f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63361075f565b61069a5760405162461bcd60e51b815260206004820152603660248201526000805160206117658339815191526044820152751d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60521b6064820152608401610560565b6105738282610c9e565b6106ae3382610d59565b50565b6106bc8233836109e0565b6105738282610d59565b6106de6000805160206117858339815191523361075f565b6107385760405162461bcd60e51b8152602060048201526037602482015260008051602061176583398151915260448201527676652070617573657220726f6c6520746f20706175736560481b6064820152608401610560565b610615610e87565b60008281526001602052604081206107589083610ec4565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606006805461040b9061160f565b600033816107a5828661085c565b9050838110156108055760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610560565b6104bf82868684036108bc565b60003361049c818585610a5a565b60008181526001602052604081206103f690610ed0565b60008281526020819052604090206001015461085281610bfe565b6104ef8383610c2a565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b60006001600160e01b03198216637965db0b60e01b14806103f657506301ffc9a760e01b6001600160e01b03198316146103f6565b6001600160a01b03831661091e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610560565b6001600160a01b03821661097f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610560565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006109ec848461085c565b90506000198114610a545781811015610a475760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610560565b610a5484848484036108bc565b50505050565b6001600160a01b038316610abe5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610560565b6001600160a01b038216610b205760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610560565b610b2b838383610eda565b6001600160a01b03831660009081526002602052604090205481811015610ba35760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610560565b6001600160a01b0380851660008181526002602052604080822086860390559286168082529083902080548601905591516000805160206117a583398151915290610bf19086815260200190565b60405180910390a3610a54565b6106ae8133610ee5565b610c128282610f3e565b60008281526001602052604090206104ef9082610fc2565b610c348282610fd7565b60008281526001602052604090206104ef908261103c565b610c54611051565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216610cf45760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610560565b610d0060008383610eda565b8060046000828254610d12919061165f565b90915550506001600160a01b0382166000818152600260209081526040808320805486019055518481526000805160206117a5833981519152910160405180910390a35050565b6001600160a01b038216610db95760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610560565b610dc582600083610eda565b6001600160a01b03821660009081526002602052604090205481811015610e395760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610560565b6001600160a01b03831660008181526002602090815260408083208686039055600480548790039055518581529192916000805160206117a5833981519152910160405180910390a3505050565b610e8f61109a565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610c813390565b600061075883836110e0565b60006103f6825490565b6104ef83838361110a565b610eef828261075f565b61057357610efc81611170565b610f07836020611182565b604051602001610f18929190611672565b60408051601f198184030181529082905262461bcd60e51b8252610560916004016114ae565b610f48828261075f565b610573576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055610f7e3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610758836001600160a01b03841661131e565b610fe1828261075f565b15610573576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610758836001600160a01b03841661136d565b60075460ff166106155760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610560565b60075460ff16156106155760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610560565b60008260000182815481106110f7576110f76116e1565b9060005260206000200154905092915050565b60075460ff16156104ef5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610560565b60606103f66001600160a01b03831660145b606060006111918360026116f7565b61119c90600261165f565b67ffffffffffffffff8111156111b4576111b461170e565b6040519080825280601f01601f1916602001820160405280156111de576020820181803683370190505b509050600360fc1b816000815181106111f9576111f96116e1565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611228576112286116e1565b60200101906001600160f81b031916908160001a905350600061124c8460026116f7565b61125790600161165f565b90505b60018111156112cf576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061128b5761128b6116e1565b1a60f81b8282815181106112a1576112a16116e1565b60200101906001600160f81b031916908160001a90535060049490941c936112c881611724565b905061125a565b5083156107585760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610560565b6000818152600183016020526040812054611365575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556103f6565b5060006103f6565b6000818152600183016020526040812054801561145657600061139160018361173b565b85549091506000906113a59060019061173b565b905081811461140a5760008660000182815481106113c5576113c56116e1565b90600052602060002001549050808760000184815481106113e8576113e86116e1565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061141b5761141b61174e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506103f6565b60009150506103f6565b60006020828403121561147257600080fd5b81356001600160e01b03198116811461075857600080fd5b60005b838110156114a557818101518382015260200161148d565b50506000910152565b60208152600082518060208401526114cd81604085016020870161148a565b601f01601f19169190910160400192915050565b80356001600160a01b03811681146114f857600080fd5b919050565b6000806040838503121561151057600080fd5b611519836114e1565b946020939093013593505050565b60008060006060848603121561153c57600080fd5b611545846114e1565b9250611553602085016114e1565b9150604084013590509250925092565b60006020828403121561157557600080fd5b5035919050565b6000806040838503121561158f57600080fd5b8235915061159f602084016114e1565b90509250929050565b6000602082840312156115ba57600080fd5b610758826114e1565b600080604083850312156115d657600080fd5b50508035926020909101359150565b600080604083850312156115f857600080fd5b611601836114e1565b915061159f602084016114e1565b600181811c9082168061162357607f821691505b60208210810361164357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103f6576103f6611649565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516116a481601785016020880161148a565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516116d581602884016020880161148a565b01602801949350505050565b634e487b7160e01b600052603260045260246000fd5b80820281158282048414176103f6576103f6611649565b634e487b7160e01b600052604160045260246000fd5b60008161173357611733611649565b506000190190565b818103818111156103f6576103f6611649565b634e487b7160e01b600052603160045260246000fdfe45524332305072657365744d696e7465725061757365723a206d75737420686165d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220d5a22b9391b8f37e5b49e43cc1eabfcea8be6d7b5aa0a84dc5daa1b7a05730f364736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101845760003560e01c806370a08231116100d9578063a457c2d711610087578063a457c2d714610336578063a9059cbb14610349578063ca15c8731461035c578063d53913931461036f578063d547741f14610396578063dd62ed3e146103a9578063e63ab1e9146103bc57600080fd5b806370a08231146102a457806379cc6790146102cd5780638456cb59146102e05780639010d07c146102e857806391d148541461031357806395d89b4114610326578063a217fddf1461032e57600080fd5b8063313ce56711610136578063313ce5671461023657806336568abe1461024557806339509351146102585780633f4ba83a1461026b57806340c10f191461027357806342966c68146102865780635c975abb1461029957600080fd5b806301ffc9a71461018957806306fdde03146101b1578063095ea7b3146101c657806318160ddd146101d957806323b872dd146101eb578063248a9ca3146101fe5780632f2ff15d14610221575b600080fd5b61019c610197366004611460565b6103d1565b60405190151581526020015b60405180910390f35b6101b96103fc565b6040516101a891906114ae565b61019c6101d43660046114fd565b61048e565b6004545b6040519081526020016101a8565b61019c6101f9366004611527565b6104a6565b6101dd61020c366004611563565b60009081526020819052604090206001015490565b61023461022f36600461157c565b6104ca565b005b604051601281526020016101a8565b61023461025336600461157c565b6104f4565b61019c6102663660046114fd565b610577565b610234610599565b6102346102813660046114fd565b610617565b610234610294366004611563565b6106a4565b60075460ff1661019c565b6101dd6102b23660046115a8565b6001600160a01b031660009081526002602052604090205490565b6102346102db3660046114fd565b6106b1565b6102346106c6565b6102fb6102f63660046115c3565b610740565b6040516001600160a01b0390911681526020016101a8565b61019c61032136600461157c565b61075f565b6101b9610788565b6101dd600081565b61019c6103443660046114fd565b610797565b61019c6103573660046114fd565b610812565b6101dd61036a366004611563565b610820565b6101dd7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102346103a436600461157c565b610837565b6101dd6103b73660046115e5565b61085c565b6101dd60008051602061178583398151915281565b60006001600160e01b03198216635a05180f60e01b14806103f657506103f682610887565b92915050565b60606005805461040b9061160f565b80601f01602080910402602001604051908101604052809291908181526020018280546104379061160f565b80156104845780601f1061045957610100808354040283529160200191610484565b820191906000526020600020905b81548152906001019060200180831161046757829003601f168201915b5050505050905090565b60003361049c8185856108bc565b5060019392505050565b6000336104b48582856109e0565b6104bf858585610a5a565b506001949350505050565b6000828152602081905260409020600101546104e581610bfe565b6104ef8383610c08565b505050565b6001600160a01b03811633146105695760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b6105738282610c2a565b5050565b60003361049c81858561058a838361085c565b610594919061165f565b6108bc565b6105b16000805160206117858339815191523361075f565b61060d5760405162461bcd60e51b8152602060048201526039602482015260008051602061176583398151915260448201527876652070617573657220726f6c6520746f20756e706175736560381b6064820152608401610560565b610615610c4c565b565b6106417f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63361075f565b61069a5760405162461bcd60e51b815260206004820152603660248201526000805160206117658339815191526044820152751d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60521b6064820152608401610560565b6105738282610c9e565b6106ae3382610d59565b50565b6106bc8233836109e0565b6105738282610d59565b6106de6000805160206117858339815191523361075f565b6107385760405162461bcd60e51b8152602060048201526037602482015260008051602061176583398151915260448201527676652070617573657220726f6c6520746f20706175736560481b6064820152608401610560565b610615610e87565b60008281526001602052604081206107589083610ec4565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606006805461040b9061160f565b600033816107a5828661085c565b9050838110156108055760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610560565b6104bf82868684036108bc565b60003361049c818585610a5a565b60008181526001602052604081206103f690610ed0565b60008281526020819052604090206001015461085281610bfe565b6104ef8383610c2a565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205490565b60006001600160e01b03198216637965db0b60e01b14806103f657506301ffc9a760e01b6001600160e01b03198316146103f6565b6001600160a01b03831661091e5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610560565b6001600160a01b03821661097f5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610560565b6001600160a01b0383811660008181526003602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b60006109ec848461085c565b90506000198114610a545781811015610a475760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610560565b610a5484848484036108bc565b50505050565b6001600160a01b038316610abe5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610560565b6001600160a01b038216610b205760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610560565b610b2b838383610eda565b6001600160a01b03831660009081526002602052604090205481811015610ba35760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610560565b6001600160a01b0380851660008181526002602052604080822086860390559286168082529083902080548601905591516000805160206117a583398151915290610bf19086815260200190565b60405180910390a3610a54565b6106ae8133610ee5565b610c128282610f3e565b60008281526001602052604090206104ef9082610fc2565b610c348282610fd7565b60008281526001602052604090206104ef908261103c565b610c54611051565b6007805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038216610cf45760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610560565b610d0060008383610eda565b8060046000828254610d12919061165f565b90915550506001600160a01b0382166000818152600260209081526040808320805486019055518481526000805160206117a5833981519152910160405180910390a35050565b6001600160a01b038216610db95760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610560565b610dc582600083610eda565b6001600160a01b03821660009081526002602052604090205481811015610e395760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610560565b6001600160a01b03831660008181526002602090815260408083208686039055600480548790039055518581529192916000805160206117a5833981519152910160405180910390a3505050565b610e8f61109a565b6007805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610c813390565b600061075883836110e0565b60006103f6825490565b6104ef83838361110a565b610eef828261075f565b61057357610efc81611170565b610f07836020611182565b604051602001610f18929190611672565b60408051601f198184030181529082905262461bcd60e51b8252610560916004016114ae565b610f48828261075f565b610573576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055610f7e3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610758836001600160a01b03841661131e565b610fe1828261075f565b15610573576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610758836001600160a01b03841661136d565b60075460ff166106155760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610560565b60075460ff16156106155760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610560565b60008260000182815481106110f7576110f76116e1565b9060005260206000200154905092915050565b60075460ff16156104ef5760405162461bcd60e51b815260206004820152602a60248201527f45524332305061757361626c653a20746f6b656e207472616e736665722077686044820152691a5b19481c185d5cd95960b21b6064820152608401610560565b60606103f66001600160a01b03831660145b606060006111918360026116f7565b61119c90600261165f565b67ffffffffffffffff8111156111b4576111b461170e565b6040519080825280601f01601f1916602001820160405280156111de576020820181803683370190505b509050600360fc1b816000815181106111f9576111f96116e1565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611228576112286116e1565b60200101906001600160f81b031916908160001a905350600061124c8460026116f7565b61125790600161165f565b90505b60018111156112cf576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061128b5761128b6116e1565b1a60f81b8282815181106112a1576112a16116e1565b60200101906001600160f81b031916908160001a90535060049490941c936112c881611724565b905061125a565b5083156107585760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610560565b6000818152600183016020526040812054611365575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556103f6565b5060006103f6565b6000818152600183016020526040812054801561145657600061139160018361173b565b85549091506000906113a59060019061173b565b905081811461140a5760008660000182815481106113c5576113c56116e1565b90600052602060002001549050808760000184815481106113e8576113e86116e1565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061141b5761141b61174e565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506103f6565b60009150506103f6565b60006020828403121561147257600080fd5b81356001600160e01b03198116811461075857600080fd5b60005b838110156114a557818101518382015260200161148d565b50506000910152565b60208152600082518060208401526114cd81604085016020870161148a565b601f01601f19169190910160400192915050565b80356001600160a01b03811681146114f857600080fd5b919050565b6000806040838503121561151057600080fd5b611519836114e1565b946020939093013593505050565b60008060006060848603121561153c57600080fd5b611545846114e1565b9250611553602085016114e1565b9150604084013590509250925092565b60006020828403121561157557600080fd5b5035919050565b6000806040838503121561158f57600080fd5b8235915061159f602084016114e1565b90509250929050565b6000602082840312156115ba57600080fd5b610758826114e1565b600080604083850312156115d657600080fd5b50508035926020909101359150565b600080604083850312156115f857600080fd5b611601836114e1565b915061159f602084016114e1565b600181811c9082168061162357607f821691505b60208210810361164357634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156103f6576103f6611649565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516116a481601785016020880161148a565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516116d581602884016020880161148a565b01602801949350505050565b634e487b7160e01b600052603260045260246000fd5b80820281158282048414176103f6576103f6611649565b634e487b7160e01b600052604160045260246000fd5b60008161173357611733611649565b506000190190565b818103818111156103f6576103f6611649565b634e487b7160e01b600052603160045260246000fdfe45524332305072657365744d696e7465725061757365723a206d75737420686165d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220d5a22b9391b8f37e5b49e43cc1eabfcea8be6d7b5aa0a84dc5daa1b7a05730f364736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RootERC20PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootERC20Predicate\",\n \"sourceName\": \"contracts/root/RootERC20Predicate.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ERC20Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ERC20Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"exitHelper\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newExitHelper\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"nativeTokenRootAddress\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC20Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onL2StateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506113c7806100206000396000f3fe608060405234801561001057600080fd5b50600436106100bf5760003560e01c8063cb10f94c1161007c578063cb10f94c1461018d578063d41f1771146101a6578063d57184e4146101cd578063f213159c146101e0578063f43cda8b146101f3578063f4a120f714610206578063f64512551461021957600080fd5b80631459457a146100c457806347e7ef24146100d95780637efab4f5146100ec57806395c7041c14610132578063b176806514610145578063b68ad1e41461017a575b600080fd5b6100d76100d2366004610f4b565b610240565b005b6100d76100e7366004610fbc565b6104ae565b6101156100fa366004610fe8565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600154610115906001600160a01b031681565b61016c7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610129565b600354610115906001600160a01b031681565b600054610115906201000090046001600160a01b031681565b61016c7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b600254610115906001600160a01b031681565b6100d76101ee36600461100c565b6104bd565b6100d761020136600461104d565b6104cd565b610115610214366004610fe8565b610654565b61016c7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b600054610100900460ff16158080156102605750600054600160ff909116105b8061027a5750303b15801561027a575060005460ff166001145b6102e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610305576000805461ff0019166101001790555b6001600160a01b0386161580159061032557506001600160a01b03851615155b801561033957506001600160a01b03841615155b801561034d57506001600160a01b03831615155b6103a85760405162461bcd60e51b815260206004820152602660248201527f526f6f7445524332305072656469636174653a204241445f494e495449414c496044820152652d20aa24a7a760d11b60648201526084016102d9565b6000805462010000600160b01b031916620100006001600160a01b038981169190910291909117909155600180546001600160a01b03199081168884161790915560028054821687841617905560038054909116858316179055821615610460576001600160a01b03821660008181526004602052604080822080546001600160a01b03191661101090811790915590519092917f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61791a35b80156104a6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6104b9823383610a15565b5050565b6104c8838383610a15565b505050565b6001546001600160a01b031633146105335760405162461bcd60e51b8152602060048201526024808201527f526f6f7445524332305072656469636174653a204f4e4c595f455849545f4845604482015263262822a960e11b60648201526084016102d9565b6002546001600160a01b038481169116146105a15760405162461bcd60e51b815260206004820152602860248201527f526f6f7445524332305072656469636174653a204f4e4c595f4348494c445f50604482015267524544494341544560c01b60648201526084016102d9565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696105d06020600084866110d6565b6105d991611100565b036105f8576105f36105ee82602081866110d6565b610b8c565b61064e565b60405162461bcd60e51b815260206004820152602560248201527f526f6f7445524332305072656469636174653a20494e56414c49445f5349474e604482015264415455524560d81b60648201526084016102d9565b50505050565b60006001600160a01b0382166106b65760405162461bcd60e51b815260206004820152602160248201527f526f6f7445524332305072656469636174653a20494e56414c49445f544f4b456044820152602760f91b60648201526084016102d9565b6001600160a01b0382811660009081526004602052604090205416156107295760405162461bcd60e51b815260206004820152602260248201527f526f6f7445524332305072656469636174653a20414c52454144595f4d415050604482015261115160f21b60648201526084016102d9565b6002546003546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b03928316926000926107d792911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b03858116600081815260046020819052604080832080546001600160a01b031916878716179055825481516306fdde0360e01b81529151969750620100009004909416946316f198319488947f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad948c9491936306fdde039380840193908290030181865afa158015610874573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261089c9190810190611159565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108da573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109029190810190611159565b8a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610940573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096491906111fb565b60405160200161097895949392919061124a565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109a492919061129c565b600060405180830381600087803b1580156109be57600080fd5b505af11580156109d2573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61790600090a39392505050565b6001600160a01b038084166000908152600460205260409020541680610a4157610a3e84610654565b90505b6001600160a01b038116610a5757610a576112c0565b610a6c6001600160a01b038516333085610c44565b600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b0388811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352620100009094048416936316f1983193610afd9391169160c40161129c565b600060405180830381600087803b158015610b1757600080fd5b505af1158015610b2b573d6000803e3d6000fd5b50505050826001600160a01b0316816001600160a01b0316856001600160a01b03167f8be9001bb612c7123a1861dc0d9d94e683261f6cbbd7c7438b708975bc4908a33386604051610b7e9291906112d6565b60405180910390a450505050565b6000808080610b9d858701876112ef565b6001600160a01b0380851660009081526004602052604090205494985092965090945092501680610bd057610bd06112c0565b610be46001600160a01b0386168484610caf565b826001600160a01b0316816001600160a01b0316866001600160a01b03167f9c4f744b2e971d7058a9d8f43977e0e17bf7d57a48659f0e18541b7ee3d022e48786604051610c339291906112d6565b60405180910390a450505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905261064e9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610cce565b6104c88363a9059cbb60e01b8484604051602401610c789291906112d6565b6000610d23826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610da39092919063ffffffff16565b9050805160001480610d44575080806020019051810190610d449190611340565b6104c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102d9565b6060610db28484600085610dba565b949350505050565b606082471015610e1b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102d9565b600080866001600160a01b03168587604051610e379190611362565b60006040518083038185875af1925050503d8060008114610e74576040519150601f19603f3d011682016040523d82523d6000602084013e610e79565b606091505b5091509150610e8a87838387610e95565b979650505050505050565b60608315610f04578251600003610efd576001600160a01b0385163b610efd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d9565b5081610db2565b610db28383815115610f195781518083602001fd5b8060405162461bcd60e51b81526004016102d9919061137e565b6001600160a01b0381168114610f4857600080fd5b50565b600080600080600060a08688031215610f6357600080fd5b8535610f6e81610f33565b94506020860135610f7e81610f33565b93506040860135610f8e81610f33565b92506060860135610f9e81610f33565b91506080860135610fae81610f33565b809150509295509295909350565b60008060408385031215610fcf57600080fd5b8235610fda81610f33565b946020939093013593505050565b600060208284031215610ffa57600080fd5b813561100581610f33565b9392505050565b60008060006060848603121561102157600080fd5b833561102c81610f33565b9250602084013561103c81610f33565b929592945050506040919091013590565b6000806000806060858703121561106357600080fd5b84359350602085013561107581610f33565b9250604085013567ffffffffffffffff8082111561109257600080fd5b818701915087601f8301126110a657600080fd5b8135818111156110b557600080fd5b8860208285010111156110c757600080fd5b95989497505060200194505050565b600080858511156110e657600080fd5b838611156110f357600080fd5b5050820193919092039150565b8035602083101561111957600019602084900360031b1b165b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015611150578181015183820152602001611138565b50506000910152565b60006020828403121561116b57600080fd5b815167ffffffffffffffff8082111561118357600080fd5b818401915084601f83011261119757600080fd5b8151818111156111a9576111a961111f565b604051601f8201601f19908116603f011681019083821181831017156111d1576111d161111f565b816040528281528760208487010111156111ea57600080fd5b610e8a836020830160208801611135565b60006020828403121561120d57600080fd5b815160ff8116811461100557600080fd5b60008151808452611236816020860160208601611135565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260a0604082018190526000906112749083018661121e565b8281036060840152611286818661121e565b91505060ff831660808301529695505050505050565b6001600160a01b0383168152604060208201819052600090610db29083018461121e565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b6000806000806080858703121561130557600080fd5b843561131081610f33565b9350602085013561132081610f33565b9250604085013561133081610f33565b9396929550929360600135925050565b60006020828403121561135257600080fd5b8151801515811461100557600080fd5b60008251611374818460208701611135565b9190910192915050565b602081526000611005602083018461121e56fea26469706673582212208273d626c27034ddec9bc7a16685788a61724d2c7c1fc56e7299933565b205fa64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100bf5760003560e01c8063cb10f94c1161007c578063cb10f94c1461018d578063d41f1771146101a6578063d57184e4146101cd578063f213159c146101e0578063f43cda8b146101f3578063f4a120f714610206578063f64512551461021957600080fd5b80631459457a146100c457806347e7ef24146100d95780637efab4f5146100ec57806395c7041c14610132578063b176806514610145578063b68ad1e41461017a575b600080fd5b6100d76100d2366004610f4b565b610240565b005b6100d76100e7366004610fbc565b6104ae565b6101156100fa366004610fe8565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600154610115906001600160a01b031681565b61016c7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610129565b600354610115906001600160a01b031681565b600054610115906201000090046001600160a01b031681565b61016c7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b600254610115906001600160a01b031681565b6100d76101ee36600461100c565b6104bd565b6100d761020136600461104d565b6104cd565b610115610214366004610fe8565b610654565b61016c7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b600054610100900460ff16158080156102605750600054600160ff909116105b8061027a5750303b15801561027a575060005460ff166001145b6102e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff191660011790558015610305576000805461ff0019166101001790555b6001600160a01b0386161580159061032557506001600160a01b03851615155b801561033957506001600160a01b03841615155b801561034d57506001600160a01b03831615155b6103a85760405162461bcd60e51b815260206004820152602660248201527f526f6f7445524332305072656469636174653a204241445f494e495449414c496044820152652d20aa24a7a760d11b60648201526084016102d9565b6000805462010000600160b01b031916620100006001600160a01b038981169190910291909117909155600180546001600160a01b03199081168884161790915560028054821687841617905560038054909116858316179055821615610460576001600160a01b03821660008181526004602052604080822080546001600160a01b03191661101090811790915590519092917f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61791a35b80156104a6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6104b9823383610a15565b5050565b6104c8838383610a15565b505050565b6001546001600160a01b031633146105335760405162461bcd60e51b8152602060048201526024808201527f526f6f7445524332305072656469636174653a204f4e4c595f455849545f4845604482015263262822a960e11b60648201526084016102d9565b6002546001600160a01b038481169116146105a15760405162461bcd60e51b815260206004820152602860248201527f526f6f7445524332305072656469636174653a204f4e4c595f4348494c445f50604482015267524544494341544560c01b60648201526084016102d9565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e9828696105d06020600084866110d6565b6105d991611100565b036105f8576105f36105ee82602081866110d6565b610b8c565b61064e565b60405162461bcd60e51b815260206004820152602560248201527f526f6f7445524332305072656469636174653a20494e56414c49445f5349474e604482015264415455524560d81b60648201526084016102d9565b50505050565b60006001600160a01b0382166106b65760405162461bcd60e51b815260206004820152602160248201527f526f6f7445524332305072656469636174653a20494e56414c49445f544f4b456044820152602760f91b60648201526084016102d9565b6001600160a01b0382811660009081526004602052604090205416156107295760405162461bcd60e51b815260206004820152602260248201527f526f6f7445524332305072656469636174653a20414c52454144595f4d415050604482015261115160f21b60648201526084016102d9565b6002546003546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b03928316926000926107d792911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b03858116600081815260046020819052604080832080546001600160a01b031916878716179055825481516306fdde0360e01b81529151969750620100009004909416946316f198319488947f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad948c9491936306fdde039380840193908290030181865afa158015610874573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261089c9190810190611159565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108da573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109029190810190611159565b8a6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610940573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096491906111fb565b60405160200161097895949392919061124a565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109a492919061129c565b600060405180830381600087803b1580156109be57600080fd5b505af11580156109d2573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61790600090a39392505050565b6001600160a01b038084166000908152600460205260409020541680610a4157610a3e84610654565b90505b6001600160a01b038116610a5757610a576112c0565b610a6c6001600160a01b038516333085610c44565b600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b0388811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352620100009094048416936316f1983193610afd9391169160c40161129c565b600060405180830381600087803b158015610b1757600080fd5b505af1158015610b2b573d6000803e3d6000fd5b50505050826001600160a01b0316816001600160a01b0316856001600160a01b03167f8be9001bb612c7123a1861dc0d9d94e683261f6cbbd7c7438b708975bc4908a33386604051610b7e9291906112d6565b60405180910390a450505050565b6000808080610b9d858701876112ef565b6001600160a01b0380851660009081526004602052604090205494985092965090945092501680610bd057610bd06112c0565b610be46001600160a01b0386168484610caf565b826001600160a01b0316816001600160a01b0316866001600160a01b03167f9c4f744b2e971d7058a9d8f43977e0e17bf7d57a48659f0e18541b7ee3d022e48786604051610c339291906112d6565b60405180910390a450505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905261064e9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610cce565b6104c88363a9059cbb60e01b8484604051602401610c789291906112d6565b6000610d23826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610da39092919063ffffffff16565b9050805160001480610d44575080806020019051810190610d449190611340565b6104c85760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102d9565b6060610db28484600085610dba565b949350505050565b606082471015610e1b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102d9565b600080866001600160a01b03168587604051610e379190611362565b60006040518083038185875af1925050503d8060008114610e74576040519150601f19603f3d011682016040523d82523d6000602084013e610e79565b606091505b5091509150610e8a87838387610e95565b979650505050505050565b60608315610f04578251600003610efd576001600160a01b0385163b610efd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d9565b5081610db2565b610db28383815115610f195781518083602001fd5b8060405162461bcd60e51b81526004016102d9919061137e565b6001600160a01b0381168114610f4857600080fd5b50565b600080600080600060a08688031215610f6357600080fd5b8535610f6e81610f33565b94506020860135610f7e81610f33565b93506040860135610f8e81610f33565b92506060860135610f9e81610f33565b91506080860135610fae81610f33565b809150509295509295909350565b60008060408385031215610fcf57600080fd5b8235610fda81610f33565b946020939093013593505050565b600060208284031215610ffa57600080fd5b813561100581610f33565b9392505050565b60008060006060848603121561102157600080fd5b833561102c81610f33565b9250602084013561103c81610f33565b929592945050506040919091013590565b6000806000806060858703121561106357600080fd5b84359350602085013561107581610f33565b9250604085013567ffffffffffffffff8082111561109257600080fd5b818701915087601f8301126110a657600080fd5b8135818111156110b557600080fd5b8860208285010111156110c757600080fd5b95989497505060200194505050565b600080858511156110e657600080fd5b838611156110f357600080fd5b5050820193919092039150565b8035602083101561111957600019602084900360031b1b165b92915050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015611150578181015183820152602001611138565b50506000910152565b60006020828403121561116b57600080fd5b815167ffffffffffffffff8082111561118357600080fd5b818401915084601f83011261119757600080fd5b8151818111156111a9576111a961111f565b604051601f8201601f19908116603f011681019083821181831017156111d1576111d161111f565b816040528281528760208487010111156111ea57600080fd5b610e8a836020830160208801611135565b60006020828403121561120d57600080fd5b815160ff8116811461100557600080fd5b60008151808452611236816020860160208601611135565b601f01601f19169290920160200192915050565b8581526001600160a01b038516602082015260a0604082018190526000906112749083018661121e565b8281036060840152611286818661121e565b91505060ff831660808301529695505050505050565b6001600160a01b0383168152604060208201819052600090610db29083018461121e565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b6000806000806080858703121561130557600080fd5b843561131081610f33565b9350602085013561132081610f33565b9250604085013561133081610f33565b9396929550929360600135925050565b60006020828403121561135257600080fd5b8151801515811461100557600080fd5b60008251611374818460208701611135565b9190910192915050565b602081526000611005602083018461121e56fea26469706673582212208273d626c27034ddec9bc7a16685788a61724d2c7c1fc56e7299933565b205fa64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildMintableERC20PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildMintableERC20Predicate\",\n \"sourceName\": \"contracts/root/ChildMintableERC20Predicate.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"MintableERC20Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"MintableERC20Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"exitHelper\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newExitHelper\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onL2StateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506113c8806100206000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063cb10f94c11610071578063cb10f94c14610182578063d41f17711461019b578063f3fef3a3146101c2578063f43cda8b146101d5578063f6451255146101e8578063f8c8765e1461020f57600080fd5b806371cf93b7146100b95780637efab4f5146100e957806395c7041c14610112578063b176806514610125578063b68ad1e41461015a578063c3b35a7e1461016d575b600080fd5b6002546100cc906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cc6100f7366004610ecf565b6004602052600090815260409020546001600160a01b031681565b6001546100cc906001600160a01b031681565b61014c7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b6040519081526020016100e0565b6003546100cc906001600160a01b031681565b61018061017b366004610ef3565b610222565b005b6000546100cc906201000090046001600160a01b031681565b61014c7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101806101d0366004610f34565b610232565b6101806101e3366004610f60565b610241565b61014c7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61018061021d366004610fe9565b610432565b61022d83838361054b565b505050565b61023d82338361054b565b5050565b6001546001600160a01b031633146102b95760405162461bcd60e51b815260206004820152603060248201527f4368696c644d696e7461626c6545524332305072656469636174653a204f4e4c60448201526f2cafa9aa20aa22afa922a1a2a4ab22a960811b60648201526084015b60405180910390fd5b6002546001600160a01b0384811691161461032f5760405162461bcd60e51b815260206004820152603060248201527f4368696c644d696e7461626c6545524332305072656469636174653a204f4e4c60448201526f595f524f4f545f50524544494341544560801b60648201526084016102b0565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82161035e602060008486611045565b6103679161106f565b036103865761038161037c8260208186611045565b6108e0565b61042c565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6103b5602060008486611045565b6103be9161106f565b036103cd576103818282610b9c565b60405162461bcd60e51b815260206004820152602e60248201527f4368696c644d696e7461626c6545524332305072656469636174653a20494e5660448201526d414c49445f5349474e415455524560901b60648201526084016102b0565b50505050565b600054610100900460ff16158080156104525750600054600160ff909116105b8061046c5750303b15801561046c575060005460ff166001145b6104cf5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016102b0565b6000805460ff1916600117905580156104f2576000805461ff0019166101001790555b6104fe85858585610d13565b8015610544576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b826001600160a01b03163b6000036105b75760405162461bcd60e51b815260206004820152602960248201527f4368696c644d696e7461626c6545524332305072656469636174653a204e4f5460448201526817d0d3d395149050d560ba1b60648201526084016102b0565b6000836001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b919061108d565b6001600160a01b0381811660009081526004602052604090205491925085811691161461065a5760405162461bcd60e51b81526004016102b0906110aa565b6001600160a01b038116610670576106706110f5565b306001600160a01b0316846001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106dc919061108d565b6001600160a01b0316146106f2576106f26110f5565b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac90610720903390869060040161110b565b6020604051808303816000875af115801561073f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107639190611124565b6107c05760405162461bcd60e51b815260206004820152602860248201527f4368696c644d696e7461626c6545524332305072656469636174653a204255526044820152671397d1905253115160c21b60648201526084016102b0565b600054600254604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352620100009094048416936316f19831936108519391169160c40161118c565b600060405180830381600087803b15801561086b57600080fd5b505af115801561087f573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316826001600160a01b03167f1da92ba31d15f9af529a2efe7acebc6c0a4ac8e9cd86a84f199a474e505d77a633866040516108d292919061110b565b60405180910390a450505050565b60008080806108f1858701876111b8565b6001600160a01b03808516600090815260046020526040902054949850929650909450925016806109345760405162461bcd60e51b81526004016102b0906110aa565b806001600160a01b03163b60000361094e5761094e6110f5565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b2919061108d565b9050856001600160a01b0316816001600160a01b0316146109d5576109d56110f5565b6001600160a01b0381166109eb576109eb6110f5565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a57919061108d565b6001600160a01b031614610a6d57610a6d6110f5565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610a9b908790879060040161110b565b6020604051808303816000875af1158015610aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ade9190611124565b610b3b5760405162461bcd60e51b815260206004820152602860248201527f4368696c644d696e7461626c6545524332305072656469636174653a204d494e6044820152671517d1905253115160c21b60648201526084016102b0565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fcf47ccd68b2113d6309d8d504a67c10963dc0bfbf2416e4726a316511cca27b58887604051610b8a92919061110b565b60405180910390a45050505050505050565b6000808080610bad858701876112ac565b92975090955093509150506001600160a01b038416610bce57610bce6110f5565b6001600160a01b038481166000908152600460205260409020541615610bf657610bf66110f5565b6003546040516bffffffffffffffffffffffff19606087901b166020820152600091610c46916001600160a01b039091169060340160405160208183030381529060405280519060200120610e1a565b6001600160a01b0386811660009081526004602081905260409182902080546001600160a01b03191693851693841790559051637b69774360e11b8152929350909163f6d2ee8691610ca091899189918991899101611347565b600060405180830381600087803b158015610cba57600080fd5b505af1158015610cce573d6000803e3d6000fd5b50506040516001600160a01b038085169350881691507f0a1eaf9aa124c3f84c9dd77f7016af0f16f67639abb913af1697387db01f5ca590600090a350505050505050565b6001600160a01b03841615801590610d3357506001600160a01b03831615155b8015610d4757506001600160a01b03821615155b8015610d5b57506001600160a01b03811615155b610dbf5760405162461bcd60e51b815260206004820152602f60248201527f4368696c644d696e7461626c6545524332305072656469636174653a2042414460448201526e2fa4a724aa24a0a624ad20aa24a7a760891b60648201526084016102b0565b600080546001600160a01b03958616620100000262010000600160b01b0319909116179055600180549385166001600160a01b0319948516179055600280549285169284169290921790915560038054919093169116179055565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116610eb15760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016102b0565b92915050565b6001600160a01b0381168114610ecc57600080fd5b50565b600060208284031215610ee157600080fd5b8135610eec81610eb7565b9392505050565b600080600060608486031215610f0857600080fd5b8335610f1381610eb7565b92506020840135610f2381610eb7565b929592945050506040919091013590565b60008060408385031215610f4757600080fd5b8235610f5281610eb7565b946020939093013593505050565b60008060008060608587031215610f7657600080fd5b843593506020850135610f8881610eb7565b9250604085013567ffffffffffffffff80821115610fa557600080fd5b818701915087601f830112610fb957600080fd5b813581811115610fc857600080fd5b886020828501011115610fda57600080fd5b95989497505060200194505050565b60008060008060808587031215610fff57600080fd5b843561100a81610eb7565b9350602085013561101a81610eb7565b9250604085013561102a81610eb7565b9150606085013561103a81610eb7565b939692955090935050565b6000808585111561105557600080fd5b8386111561106257600080fd5b5050820193919092039150565b80356020831015610eb157600019602084900360031b1b1692915050565b60006020828403121561109f57600080fd5b8151610eec81610eb7565b6020808252602b908201527f4368696c644d696e7461626c6545524332305072656469636174653a20554e4d60408201526a20a82822a22faa27a5a2a760a91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b60006020828403121561113657600080fd5b81518015158114610eec57600080fd5b6000815180845260005b8181101561116c57602081850181015186830182015201611150565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190526000906111b090830184611146565b949350505050565b600080600080608085870312156111ce57600080fd5b84356111d981610eb7565b935060208501356111e981610eb7565b925060408501356111f981610eb7565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261123057600080fd5b813567ffffffffffffffff8082111561124b5761124b611209565b604051601f8301601f19908116603f0116810190828211818310171561127357611273611209565b8160405283815286602085880101111561128c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156112c457600080fd5b8535945060208601356112d681610eb7565b9350604086013567ffffffffffffffff808211156112f357600080fd5b6112ff89838a0161121f565b9450606088013591508082111561131557600080fd5b506113228882890161121f565b925050608086013560ff8116811461133957600080fd5b809150509295509295909350565b6001600160a01b038516815260806020820181905260009061136b90830186611146565b828103604084015261137d8186611146565b91505060ff831660608301529594505050505056fea2646970667358221220984c3094e8562bd0956d9fdc403002d008ee01ac2423018d1e0c059931ee689764736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100b45760003560e01c8063cb10f94c11610071578063cb10f94c14610182578063d41f17711461019b578063f3fef3a3146101c2578063f43cda8b146101d5578063f6451255146101e8578063f8c8765e1461020f57600080fd5b806371cf93b7146100b95780637efab4f5146100e957806395c7041c14610112578063b176806514610125578063b68ad1e41461015a578063c3b35a7e1461016d575b600080fd5b6002546100cc906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100cc6100f7366004610ecf565b6004602052600090815260409020546001600160a01b031681565b6001546100cc906001600160a01b031681565b61014c7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b6040519081526020016100e0565b6003546100cc906001600160a01b031681565b61018061017b366004610ef3565b610222565b005b6000546100cc906201000090046001600160a01b031681565b61014c7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101806101d0366004610f34565b610232565b6101806101e3366004610f60565b610241565b61014c7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61018061021d366004610fe9565b610432565b61022d83838361054b565b505050565b61023d82338361054b565b5050565b6001546001600160a01b031633146102b95760405162461bcd60e51b815260206004820152603060248201527f4368696c644d696e7461626c6545524332305072656469636174653a204f4e4c60448201526f2cafa9aa20aa22afa922a1a2a4ab22a960811b60648201526084015b60405180910390fd5b6002546001600160a01b0384811691161461032f5760405162461bcd60e51b815260206004820152603060248201527f4368696c644d696e7461626c6545524332305072656469636174653a204f4e4c60448201526f595f524f4f545f50524544494341544560801b60648201526084016102b0565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82161035e602060008486611045565b6103679161106f565b036103865761038161037c8260208186611045565b6108e0565b61042c565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad6103b5602060008486611045565b6103be9161106f565b036103cd576103818282610b9c565b60405162461bcd60e51b815260206004820152602e60248201527f4368696c644d696e7461626c6545524332305072656469636174653a20494e5660448201526d414c49445f5349474e415455524560901b60648201526084016102b0565b50505050565b600054610100900460ff16158080156104525750600054600160ff909116105b8061046c5750303b15801561046c575060005460ff166001145b6104cf5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016102b0565b6000805460ff1916600117905580156104f2576000805461ff0019166101001790555b6104fe85858585610d13565b8015610544576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b826001600160a01b03163b6000036105b75760405162461bcd60e51b815260206004820152602960248201527f4368696c644d696e7461626c6545524332305072656469636174653a204e4f5460448201526817d0d3d395149050d560ba1b60648201526084016102b0565b6000836001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061b919061108d565b6001600160a01b0381811660009081526004602052604090205491925085811691161461065a5760405162461bcd60e51b81526004016102b0906110aa565b6001600160a01b038116610670576106706110f5565b306001600160a01b0316846001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106dc919061108d565b6001600160a01b0316146106f2576106f26110f5565b604051632770a7eb60e21b81526001600160a01b03851690639dc29fac90610720903390869060040161110b565b6020604051808303816000875af115801561073f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107639190611124565b6107c05760405162461bcd60e51b815260206004820152602860248201527f4368696c644d696e7461626c6545524332305072656469636174653a204255526044820152671397d1905253115160c21b60648201526084016102b0565b600054600254604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152878116608083015260a08083018890528351808403909101815260c08301938490526316f1983160e01b909352620100009094048416936316f19831936108519391169160c40161118c565b600060405180830381600087803b15801561086b57600080fd5b505af115801561087f573d6000803e3d6000fd5b50505050826001600160a01b0316846001600160a01b0316826001600160a01b03167f1da92ba31d15f9af529a2efe7acebc6c0a4ac8e9cd86a84f199a474e505d77a633866040516108d292919061110b565b60405180910390a450505050565b60008080806108f1858701876111b8565b6001600160a01b03808516600090815260046020526040902054949850929650909450925016806109345760405162461bcd60e51b81526004016102b0906110aa565b806001600160a01b03163b60000361094e5761094e6110f5565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b2919061108d565b9050856001600160a01b0316816001600160a01b0316146109d5576109d56110f5565b6001600160a01b0381166109eb576109eb6110f5565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a57919061108d565b6001600160a01b031614610a6d57610a6d6110f5565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610a9b908790879060040161110b565b6020604051808303816000875af1158015610aba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ade9190611124565b610b3b5760405162461bcd60e51b815260206004820152602860248201527f4368696c644d696e7461626c6545524332305072656469636174653a204d494e6044820152671517d1905253115160c21b60648201526084016102b0565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fcf47ccd68b2113d6309d8d504a67c10963dc0bfbf2416e4726a316511cca27b58887604051610b8a92919061110b565b60405180910390a45050505050505050565b6000808080610bad858701876112ac565b92975090955093509150506001600160a01b038416610bce57610bce6110f5565b6001600160a01b038481166000908152600460205260409020541615610bf657610bf66110f5565b6003546040516bffffffffffffffffffffffff19606087901b166020820152600091610c46916001600160a01b039091169060340160405160208183030381529060405280519060200120610e1a565b6001600160a01b0386811660009081526004602081905260409182902080546001600160a01b03191693851693841790559051637b69774360e11b8152929350909163f6d2ee8691610ca091899189918991899101611347565b600060405180830381600087803b158015610cba57600080fd5b505af1158015610cce573d6000803e3d6000fd5b50506040516001600160a01b038085169350881691507f0a1eaf9aa124c3f84c9dd77f7016af0f16f67639abb913af1697387db01f5ca590600090a350505050505050565b6001600160a01b03841615801590610d3357506001600160a01b03831615155b8015610d4757506001600160a01b03821615155b8015610d5b57506001600160a01b03811615155b610dbf5760405162461bcd60e51b815260206004820152602f60248201527f4368696c644d696e7461626c6545524332305072656469636174653a2042414460448201526e2fa4a724aa24a0a624ad20aa24a7a760891b60648201526084016102b0565b600080546001600160a01b03958616620100000262010000600160b01b0319909116179055600180549385166001600160a01b0319948516179055600280549285169284169290921790915560038054919093169116179055565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b038116610eb15760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b60448201526064016102b0565b92915050565b6001600160a01b0381168114610ecc57600080fd5b50565b600060208284031215610ee157600080fd5b8135610eec81610eb7565b9392505050565b600080600060608486031215610f0857600080fd5b8335610f1381610eb7565b92506020840135610f2381610eb7565b929592945050506040919091013590565b60008060408385031215610f4757600080fd5b8235610f5281610eb7565b946020939093013593505050565b60008060008060608587031215610f7657600080fd5b843593506020850135610f8881610eb7565b9250604085013567ffffffffffffffff80821115610fa557600080fd5b818701915087601f830112610fb957600080fd5b813581811115610fc857600080fd5b886020828501011115610fda57600080fd5b95989497505060200194505050565b60008060008060808587031215610fff57600080fd5b843561100a81610eb7565b9350602085013561101a81610eb7565b9250604085013561102a81610eb7565b9150606085013561103a81610eb7565b939692955090935050565b6000808585111561105557600080fd5b8386111561106257600080fd5b5050820193919092039150565b80356020831015610eb157600019602084900360031b1b1692915050565b60006020828403121561109f57600080fd5b8151610eec81610eb7565b6020808252602b908201527f4368696c644d696e7461626c6545524332305072656469636174653a20554e4d60408201526a20a82822a22faa27a5a2a760a91b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b6001600160a01b03929092168252602082015260400190565b60006020828403121561113657600080fd5b81518015158114610eec57600080fd5b6000815180845260005b8181101561116c57602081850181015186830182015201611150565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190526000906111b090830184611146565b949350505050565b600080600080608085870312156111ce57600080fd5b84356111d981610eb7565b935060208501356111e981610eb7565b925060408501356111f981610eb7565b9396929550929360600135925050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261123057600080fd5b813567ffffffffffffffff8082111561124b5761124b611209565b604051601f8301601f19908116603f0116810190828211818310171561127357611273611209565b8160405283815286602085880101111561128c57600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600060a086880312156112c457600080fd5b8535945060208601356112d681610eb7565b9350604086013567ffffffffffffffff808211156112f357600080fd5b6112ff89838a0161121f565b9450606088013591508082111561131557600080fd5b506113228882890161121f565b925050608086013560ff8116811461133957600080fd5b809150509295509295909350565b6001600160a01b038516815260806020820181905260009061136b90830186611146565b828103604084015261137d8186611146565b91505060ff831660608301529594505050505056fea2646970667358221220984c3094e8562bd0956d9fdc403002d008ee01ac2423018d1e0c059931ee689764736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var MockERC721Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"MockERC721\",\n \"sourceName\": \"contracts/mocks/MockERC721.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"approved\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bool\",\n \"name\": \"approved\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"ApprovalForAll\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Paused\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"previousAdminRole\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"newAdminRole\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"RoleAdminChanged\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RoleGranted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RoleRevoked\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Unpaused\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEFAULT_ADMIN_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MINTER_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"PAUSER_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getApproved\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"getRoleAdmin\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"index\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getRoleMember\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"getRoleMemberCount\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"grantRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"hasRole\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"isApprovedForAll\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ownerOf\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pause\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"paused\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"renounceRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"revokeRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"safeTransferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"safeTransferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"approved\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setApprovalForAll\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"index\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"tokenByIndex\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"index\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"tokenOfOwnerByIndex\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"tokenURI\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"unpause\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x60806040523480156200001157600080fd5b5060405180604001604052806004815260200163151154d560e21b81525060405180604001604052806004815260200163151154d560e21b815250604051806040016040528060058152602001646c6f72656d60d81b815250828281600290816200007d919062000307565b5060036200008c828262000307565b5050600c805460ff1916905550600e620000a7828262000307565b50620000b560003362000116565b620000e17f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a63362000116565b6200010d7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a3362000116565b505050620003d3565b62000122828262000126565b5050565b62000132828262000151565b60008281526001602052604090206200014c9082620001f1565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1662000122576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001ad3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b600062000208836001600160a01b03841662000211565b90505b92915050565b60008181526001830160205260408120546200025a575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556200020b565b5060006200020b565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200028e57607f821691505b602082108103620002af57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200014c57600081815260208120601f850160051c81016020861015620002de5750805b601f850160051c820191505b81811015620002ff57828155600101620002ea565b505050505050565b81516001600160401b0381111562000323576200032362000263565b6200033b8162000334845462000279565b84620002b5565b602080601f8311600181146200037357600084156200035a5750858301515b600019600386901b1c1916600185901b178555620002ff565b600085815260208120601f198616915b82811015620003a45788860151825594840194600190910190840162000383565b5085821015620003c35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b61244180620003e36000396000f3fe608060405234801561001057600080fd5b50600436106101a55760003560e01c80636352211e116100ef578063a22cb46511610092578063a22cb4651461036b578063b88d4fde1461037e578063c87b56dd14610391578063ca15c873146103a4578063d5391393146103b7578063d547741f146103de578063e63ab1e9146103f1578063e985e9c51461040657600080fd5b80636352211e146102f45780636a6278421461030757806370a082311461031a5780638456cb591461032d5780639010d07c1461033557806391d148541461034857806395d89b411461035b578063a217fddf1461036357600080fd5b80632f2ff15d116101575780632f2ff15d1461026f5780632f745c591461028257806336568abe146102955780633f4ba83a146102a857806342842e0e146102b057806342966c68146102c35780634f6ccce7146102d65780635c975abb146102e957600080fd5b806301ffc9a7146101aa57806306fdde03146101d2578063081812fc146101e7578063095ea7b31461021257806318160ddd1461022757806323b872dd14610239578063248a9ca31461024c575b600080fd5b6101bd6101b8366004611dba565b610419565b60405190151581526020015b60405180910390f35b6101da61042a565b6040516101c99190611e27565b6101fa6101f5366004611e3a565b6104bc565b6040516001600160a01b0390911681526020016101c9565b610225610220366004611e6f565b6104e3565b005b600a545b6040519081526020016101c9565b610225610247366004611e99565b6105fd565b61022b61025a366004611e3a565b60009081526020819052604090206001015490565b61022561027d366004611ed5565b61062f565b61022b610290366004611e6f565b610654565b6102256102a3366004611ed5565b6106ea565b610225610768565b6102256102be366004611e99565b6107ec565b6102256102d1366004611e3a565b610807565b61022b6102e4366004611e3a565b610838565b600c5460ff166101bd565b6101fa610302366004611e3a565b6108cb565b610225610315366004611f01565b610900565b61022b610328366004611f01565b6109aa565b610225610a30565b6101fa610343366004611f1c565b610ab0565b6101bd610356366004611ed5565b610acf565b6101da610af8565b61022b600081565b610225610379366004611f3e565b610b07565b61022561038c366004611f90565b610b12565b6101da61039f366004611e3a565b610b4a565b61022b6103b2366004611e3a565b610bb0565b61022b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102256103ec366004611ed5565b610bc7565b61022b6000805160206123ac83398151915281565b6101bd61041436600461206c565b610bec565b600061042482610c1a565b92915050565b60606002805461043990612096565b80601f016020809104026020016040519081016040528092919081815260200182805461046590612096565b80156104b25780601f10610487576101008083540402835291602001916104b2565b820191906000526020600020905b81548152906001019060200180831161049557829003601f168201915b5050505050905090565b60006104c782610c3f565b506000908152600660205260409020546001600160a01b031690565b60006104ee826108cb565b9050806001600160a01b0316836001600160a01b0316036105605760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b038216148061057c575061057c8133610bec565b6105ee5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610557565b6105f88383610c64565b505050565b610608335b82610cd2565b6106245760405162461bcd60e51b8152600401610557906120d0565b6105f8838383610d31565b60008281526020819052604090206001015461064a81610e90565b6105f88383610e9a565b600061065f836109aa565b82106106c15760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610557565b506001600160a01b03919091166000908152600860209081526040808320938352929052205490565b6001600160a01b038116331461075a5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610557565b6107648282610ebc565b5050565b6107806000805160206123ac83398151915233610acf565b6107e2576040805162461bcd60e51b81526020600482015260248101919091526000805160206123ec83398151915260448201527f6d75737420686176652070617573657220726f6c6520746f20756e70617573656064820152608401610557565b6107ea610ede565b565b6105f883838360405180602001604052806000815250610b12565b61081033610602565b61082c5760405162461bcd60e51b8152600401610557906120d0565b61083581610f30565b50565b6000610843600a5490565b82106108a65760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610557565b600a82815481106108b9576108b961211d565b90600052602060002001549050919050565b6000818152600460205260408120546001600160a01b0316806104245760405162461bcd60e51b815260040161055790612133565b61092a7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610acf565b61098a5760405162461bcd60e51b815260206004820152603d60248201526000805160206123ec83398151915260448201527f6d7573742068617665206d696e74657220726f6c6520746f206d696e740000006064820152608401610557565b61099c81610997600d5490565b610fc1565b610835600d80546001019055565b60006001600160a01b038216610a145760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610557565b506001600160a01b031660009081526005602052604090205490565b610a486000805160206123ac83398151915233610acf565b610aa85760405162461bcd60e51b815260206004820152603e60248201526000805160206123ec83398151915260448201527f6d75737420686176652070617573657220726f6c6520746f20706175736500006064820152608401610557565b6107ea6110ca565b6000828152600160205260408120610ac89083611107565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606003805461043990612096565b610764338383611113565b610b1c3383610cd2565b610b385760405162461bcd60e51b8152600401610557906120d0565b610b44848484846111dd565b50505050565b6060610b5582610c3f565b6000610b5f611210565b90506000815111610b7f5760405180602001604052806000815250610ac8565b80610b898461121f565b604051602001610b9a929190612165565b6040516020818303038152906040529392505050565b6000818152600160205260408120610424906112b2565b600082815260208190526040902060010154610be281610e90565b6105f88383610ebc565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b60006001600160e01b0319821663780e9d6360e01b14806104245750610424826112bc565b610c48816112fc565b6108355760405162461bcd60e51b815260040161055790612133565b600081815260066020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610c99826108cb565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080610cde836108cb565b9050806001600160a01b0316846001600160a01b03161480610d055750610d058185610bec565b80610d295750836001600160a01b0316610d1e846104bc565b6001600160a01b0316145b949350505050565b826001600160a01b0316610d44826108cb565b6001600160a01b031614610d6a5760405162461bcd60e51b815260040161055790612194565b6001600160a01b038216610dcc5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610557565b610dd98383836001611319565b826001600160a01b0316610dec826108cb565b6001600160a01b031614610e125760405162461bcd60e51b815260040161055790612194565b600081815260066020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260058552838620805460001901905590871680865283862080546001019055868652600490945282852080549092168417909155905184936000805160206123cc83398151915291a4505050565b6108358133611325565b610ea4828261137e565b60008281526001602052604090206105f89082611402565b610ec68282611417565b60008281526001602052604090206105f8908261147c565b610ee6611491565b600c805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000610f3b826108cb565b9050610f4b816000846001611319565b610f54826108cb565b600083815260066020908152604080832080546001600160a01b03199081169091556001600160a01b0385168085526005845282852080546000190190558785526004909352818420805490911690555192935084926000805160206123cc833981519152908390a45050565b6001600160a01b0382166110175760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610557565b611020816112fc565b1561103d5760405162461bcd60e51b8152600401610557906121d9565b61104b600083836001611319565b611054816112fc565b156110715760405162461bcd60e51b8152600401610557906121d9565b6001600160a01b038216600081815260056020908152604080832080546001019055848352600490915280822080546001600160a01b0319168417905551839291906000805160206123cc833981519152908290a45050565b6110d26114da565b600c805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f133390565b6000610ac88383611520565b816001600160a01b0316836001600160a01b0316036111705760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606401610557565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6111e8848484610d31565b6111f48484848461154a565b610b445760405162461bcd60e51b815260040161055790612210565b6060600e805461043990612096565b6060600061122c8361164b565b600101905060008167ffffffffffffffff81111561124c5761124c611f7a565b6040519080825280601f01601f191660200182016040528015611276576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461128057509392505050565b6000610424825490565b60006001600160e01b031982166380ac58cd60e01b14806112ed57506001600160e01b03198216635b5e139f60e01b145b80610424575061042482611723565b6000908152600460205260409020546001600160a01b0316151590565b610b4484848484611748565b61132f8282610acf565b6107645761133c816117bb565b6113478360206117cd565b604051602001611358929190612262565b60408051601f198184030181529082905262461bcd60e51b825261055791600401611e27565b6113888282610acf565b610764576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556113be3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610ac8836001600160a01b038416611969565b6114218282610acf565b15610764576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610ac8836001600160a01b0384166119b8565b600c5460ff166107ea5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610557565b600c5460ff16156107ea5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610557565b60008260000182815481106115375761153761211d565b9060005260206000200154905092915050565b60006001600160a01b0384163b1561164057604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061158e9033908990889088906004016122d1565b6020604051808303816000875af19250505080156115c9575060408051601f3d908101601f191682019092526115c69181019061230e565b60015b611626573d8080156115f7576040519150601f19603f3d011682016040523d82523d6000602084013e6115fc565b606091505b50805160000361161e5760405162461bcd60e51b815260040161055790612210565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610d29565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061168a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106116b6576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106116d457662386f26fc10000830492506010015b6305f5e10083106116ec576305f5e100830492506008015b612710831061170057612710830492506004015b60648310611712576064830492506002015b600a83106104245760010192915050565b60006001600160e01b03198216635a05180f60e01b1480610424575061042482611aab565b61175484848484611ae0565b600c5460ff1615610b445760405162461bcd60e51b815260206004820152602b60248201527f4552433732315061757361626c653a20746f6b656e207472616e73666572207760448201526a1a1a5b19481c185d5cd95960aa1b6064820152608401610557565b60606104246001600160a01b03831660145b606060006117dc836002612341565b6117e7906002612358565b67ffffffffffffffff8111156117ff576117ff611f7a565b6040519080825280601f01601f191660200182016040528015611829576020820181803683370190505b509050600360fc1b816000815181106118445761184461211d565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106118735761187361211d565b60200101906001600160f81b031916908160001a9053506000611897846002612341565b6118a2906001612358565b90505b600181111561191a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106118d6576118d661211d565b1a60f81b8282815181106118ec576118ec61211d565b60200101906001600160f81b031916908160001a90535060049490941c936119138161236b565b90506118a5565b508315610ac85760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610557565b60008181526001830160205260408120546119b057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610424565b506000610424565b60008181526001830160205260408120548015611aa15760006119dc600183612382565b85549091506000906119f090600190612382565b9050818114611a55576000866000018281548110611a1057611a1061211d565b9060005260206000200154905080876000018481548110611a3357611a3361211d565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611a6657611a66612395565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610424565b6000915050610424565b60006001600160e01b03198216637965db0b60e01b148061042457506301ffc9a760e01b6001600160e01b0319831614610424565b6001811115611b4f5760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610557565b816001600160a01b038516611bab57611ba681600a80546000838152600b60205260408120829055600182018355919091527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80155565b611bce565b836001600160a01b0316856001600160a01b031614611bce57611bce8582611c14565b6001600160a01b038416611bea57611be581611cb1565b611c0d565b846001600160a01b0316846001600160a01b031614611c0d57611c0d8482611d60565b5050505050565b60006001611c21846109aa565b611c2b9190612382565b600083815260096020526040902054909150808214611c7e576001600160a01b03841660009081526008602090815260408083208584528252808320548484528184208190558352600990915290208190555b5060009182526009602090815260408084208490556001600160a01b039094168352600881528383209183525290812055565b600a54600090611cc390600190612382565b6000838152600b6020526040812054600a8054939450909284908110611ceb57611ceb61211d565b9060005260206000200154905080600a8381548110611d0c57611d0c61211d565b6000918252602080832090910192909255828152600b9091526040808220849055858252812055600a805480611d4457611d44612395565b6001900381819060005260206000200160009055905550505050565b6000611d6b836109aa565b6001600160a01b039093166000908152600860209081526040808320868452825280832085905593825260099052919091209190915550565b6001600160e01b03198116811461083557600080fd5b600060208284031215611dcc57600080fd5b8135610ac881611da4565b60005b83811015611df2578181015183820152602001611dda565b50506000910152565b60008151808452611e13816020860160208601611dd7565b601f01601f19169290920160200192915050565b602081526000610ac86020830184611dfb565b600060208284031215611e4c57600080fd5b5035919050565b80356001600160a01b0381168114611e6a57600080fd5b919050565b60008060408385031215611e8257600080fd5b611e8b83611e53565b946020939093013593505050565b600080600060608486031215611eae57600080fd5b611eb784611e53565b9250611ec560208501611e53565b9150604084013590509250925092565b60008060408385031215611ee857600080fd5b82359150611ef860208401611e53565b90509250929050565b600060208284031215611f1357600080fd5b610ac882611e53565b60008060408385031215611f2f57600080fd5b50508035926020909101359150565b60008060408385031215611f5157600080fd5b611f5a83611e53565b915060208301358015158114611f6f57600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611fa657600080fd5b611faf85611e53565b9350611fbd60208601611e53565b925060408501359150606085013567ffffffffffffffff80821115611fe157600080fd5b818701915087601f830112611ff557600080fd5b81358181111561200757612007611f7a565b604051601f8201601f19908116603f0116810190838211818310171561202f5761202f611f7a565b816040528281528a602084870101111561204857600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561207f57600080fd5b61208883611e53565b9150611ef860208401611e53565b600181811c908216806120aa57607f821691505b6020821081036120ca57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b602080825260189082015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604082015260600190565b60008351612177818460208801611dd7565b83519083019061218b818360208801611dd7565b01949350505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b815260008351612294816017850160208801611dd7565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516122c5816028840160208801611dd7565b01602801949350505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061230490830184611dfb565b9695505050505050565b60006020828403121561232057600080fd5b8151610ac881611da4565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176104245761042461232b565b808201808211156104245761042461232b565b60008161237a5761237a61232b565b506000190190565b818103818111156104245761042461232b565b634e487b7160e01b600052603160045260246000fdfe65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4552433732315072657365744d696e7465725061757365724175746f49643a20a2646970667358221220f586c29d0cbd3e2cee9bd99a648a34864226f46f9a05471902f3728b4f230c2864736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101a55760003560e01c80636352211e116100ef578063a22cb46511610092578063a22cb4651461036b578063b88d4fde1461037e578063c87b56dd14610391578063ca15c873146103a4578063d5391393146103b7578063d547741f146103de578063e63ab1e9146103f1578063e985e9c51461040657600080fd5b80636352211e146102f45780636a6278421461030757806370a082311461031a5780638456cb591461032d5780639010d07c1461033557806391d148541461034857806395d89b411461035b578063a217fddf1461036357600080fd5b80632f2ff15d116101575780632f2ff15d1461026f5780632f745c591461028257806336568abe146102955780633f4ba83a146102a857806342842e0e146102b057806342966c68146102c35780634f6ccce7146102d65780635c975abb146102e957600080fd5b806301ffc9a7146101aa57806306fdde03146101d2578063081812fc146101e7578063095ea7b31461021257806318160ddd1461022757806323b872dd14610239578063248a9ca31461024c575b600080fd5b6101bd6101b8366004611dba565b610419565b60405190151581526020015b60405180910390f35b6101da61042a565b6040516101c99190611e27565b6101fa6101f5366004611e3a565b6104bc565b6040516001600160a01b0390911681526020016101c9565b610225610220366004611e6f565b6104e3565b005b600a545b6040519081526020016101c9565b610225610247366004611e99565b6105fd565b61022b61025a366004611e3a565b60009081526020819052604090206001015490565b61022561027d366004611ed5565b61062f565b61022b610290366004611e6f565b610654565b6102256102a3366004611ed5565b6106ea565b610225610768565b6102256102be366004611e99565b6107ec565b6102256102d1366004611e3a565b610807565b61022b6102e4366004611e3a565b610838565b600c5460ff166101bd565b6101fa610302366004611e3a565b6108cb565b610225610315366004611f01565b610900565b61022b610328366004611f01565b6109aa565b610225610a30565b6101fa610343366004611f1c565b610ab0565b6101bd610356366004611ed5565b610acf565b6101da610af8565b61022b600081565b610225610379366004611f3e565b610b07565b61022561038c366004611f90565b610b12565b6101da61039f366004611e3a565b610b4a565b61022b6103b2366004611e3a565b610bb0565b61022b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b6102256103ec366004611ed5565b610bc7565b61022b6000805160206123ac83398151915281565b6101bd61041436600461206c565b610bec565b600061042482610c1a565b92915050565b60606002805461043990612096565b80601f016020809104026020016040519081016040528092919081815260200182805461046590612096565b80156104b25780601f10610487576101008083540402835291602001916104b2565b820191906000526020600020905b81548152906001019060200180831161049557829003601f168201915b5050505050905090565b60006104c782610c3f565b506000908152600660205260409020546001600160a01b031690565b60006104ee826108cb565b9050806001600160a01b0316836001600160a01b0316036105605760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b038216148061057c575061057c8133610bec565b6105ee5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610557565b6105f88383610c64565b505050565b610608335b82610cd2565b6106245760405162461bcd60e51b8152600401610557906120d0565b6105f8838383610d31565b60008281526020819052604090206001015461064a81610e90565b6105f88383610e9a565b600061065f836109aa565b82106106c15760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610557565b506001600160a01b03919091166000908152600860209081526040808320938352929052205490565b6001600160a01b038116331461075a5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610557565b6107648282610ebc565b5050565b6107806000805160206123ac83398151915233610acf565b6107e2576040805162461bcd60e51b81526020600482015260248101919091526000805160206123ec83398151915260448201527f6d75737420686176652070617573657220726f6c6520746f20756e70617573656064820152608401610557565b6107ea610ede565b565b6105f883838360405180602001604052806000815250610b12565b61081033610602565b61082c5760405162461bcd60e51b8152600401610557906120d0565b61083581610f30565b50565b6000610843600a5490565b82106108a65760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610557565b600a82815481106108b9576108b961211d565b90600052602060002001549050919050565b6000818152600460205260408120546001600160a01b0316806104245760405162461bcd60e51b815260040161055790612133565b61092a7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633610acf565b61098a5760405162461bcd60e51b815260206004820152603d60248201526000805160206123ec83398151915260448201527f6d7573742068617665206d696e74657220726f6c6520746f206d696e740000006064820152608401610557565b61099c81610997600d5490565b610fc1565b610835600d80546001019055565b60006001600160a01b038216610a145760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610557565b506001600160a01b031660009081526005602052604090205490565b610a486000805160206123ac83398151915233610acf565b610aa85760405162461bcd60e51b815260206004820152603e60248201526000805160206123ec83398151915260448201527f6d75737420686176652070617573657220726f6c6520746f20706175736500006064820152608401610557565b6107ea6110ca565b6000828152600160205260408120610ac89083611107565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b60606003805461043990612096565b610764338383611113565b610b1c3383610cd2565b610b385760405162461bcd60e51b8152600401610557906120d0565b610b44848484846111dd565b50505050565b6060610b5582610c3f565b6000610b5f611210565b90506000815111610b7f5760405180602001604052806000815250610ac8565b80610b898461121f565b604051602001610b9a929190612165565b6040516020818303038152906040529392505050565b6000818152600160205260408120610424906112b2565b600082815260208190526040902060010154610be281610e90565b6105f88383610ebc565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b60006001600160e01b0319821663780e9d6360e01b14806104245750610424826112bc565b610c48816112fc565b6108355760405162461bcd60e51b815260040161055790612133565b600081815260066020526040902080546001600160a01b0319166001600160a01b0384169081179091558190610c99826108cb565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080610cde836108cb565b9050806001600160a01b0316846001600160a01b03161480610d055750610d058185610bec565b80610d295750836001600160a01b0316610d1e846104bc565b6001600160a01b0316145b949350505050565b826001600160a01b0316610d44826108cb565b6001600160a01b031614610d6a5760405162461bcd60e51b815260040161055790612194565b6001600160a01b038216610dcc5760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610557565b610dd98383836001611319565b826001600160a01b0316610dec826108cb565b6001600160a01b031614610e125760405162461bcd60e51b815260040161055790612194565b600081815260066020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260058552838620805460001901905590871680865283862080546001019055868652600490945282852080549092168417909155905184936000805160206123cc83398151915291a4505050565b6108358133611325565b610ea4828261137e565b60008281526001602052604090206105f89082611402565b610ec68282611417565b60008281526001602052604090206105f8908261147c565b610ee6611491565b600c805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6000610f3b826108cb565b9050610f4b816000846001611319565b610f54826108cb565b600083815260066020908152604080832080546001600160a01b03199081169091556001600160a01b0385168085526005845282852080546000190190558785526004909352818420805490911690555192935084926000805160206123cc833981519152908390a45050565b6001600160a01b0382166110175760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610557565b611020816112fc565b1561103d5760405162461bcd60e51b8152600401610557906121d9565b61104b600083836001611319565b611054816112fc565b156110715760405162461bcd60e51b8152600401610557906121d9565b6001600160a01b038216600081815260056020908152604080832080546001019055848352600490915280822080546001600160a01b0319168417905551839291906000805160206123cc833981519152908290a45050565b6110d26114da565b600c805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f133390565b6000610ac88383611520565b816001600160a01b0316836001600160a01b0316036111705760405162461bcd60e51b815260206004820152601960248201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b6044820152606401610557565b6001600160a01b03838116600081815260076020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6111e8848484610d31565b6111f48484848461154a565b610b445760405162461bcd60e51b815260040161055790612210565b6060600e805461043990612096565b6060600061122c8361164b565b600101905060008167ffffffffffffffff81111561124c5761124c611f7a565b6040519080825280601f01601f191660200182016040528015611276576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a850494508461128057509392505050565b6000610424825490565b60006001600160e01b031982166380ac58cd60e01b14806112ed57506001600160e01b03198216635b5e139f60e01b145b80610424575061042482611723565b6000908152600460205260409020546001600160a01b0316151590565b610b4484848484611748565b61132f8282610acf565b6107645761133c816117bb565b6113478360206117cd565b604051602001611358929190612262565b60408051601f198184030181529082905262461bcd60e51b825261055791600401611e27565b6113888282610acf565b610764576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556113be3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000610ac8836001600160a01b038416611969565b6114218282610acf565b15610764576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6000610ac8836001600160a01b0384166119b8565b600c5460ff166107ea5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610557565b600c5460ff16156107ea5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610557565b60008260000182815481106115375761153761211d565b9060005260206000200154905092915050565b60006001600160a01b0384163b1561164057604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061158e9033908990889088906004016122d1565b6020604051808303816000875af19250505080156115c9575060408051601f3d908101601f191682019092526115c69181019061230e565b60015b611626573d8080156115f7576040519150601f19603f3d011682016040523d82523d6000602084013e6115fc565b606091505b50805160000361161e5760405162461bcd60e51b815260040161055790612210565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610d29565b506001949350505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b831061168a5772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef810000000083106116b6576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106116d457662386f26fc10000830492506010015b6305f5e10083106116ec576305f5e100830492506008015b612710831061170057612710830492506004015b60648310611712576064830492506002015b600a83106104245760010192915050565b60006001600160e01b03198216635a05180f60e01b1480610424575061042482611aab565b61175484848484611ae0565b600c5460ff1615610b445760405162461bcd60e51b815260206004820152602b60248201527f4552433732315061757361626c653a20746f6b656e207472616e73666572207760448201526a1a1a5b19481c185d5cd95960aa1b6064820152608401610557565b60606104246001600160a01b03831660145b606060006117dc836002612341565b6117e7906002612358565b67ffffffffffffffff8111156117ff576117ff611f7a565b6040519080825280601f01601f191660200182016040528015611829576020820181803683370190505b509050600360fc1b816000815181106118445761184461211d565b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106118735761187361211d565b60200101906001600160f81b031916908160001a9053506000611897846002612341565b6118a2906001612358565b90505b600181111561191a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106118d6576118d661211d565b1a60f81b8282815181106118ec576118ec61211d565b60200101906001600160f81b031916908160001a90535060049490941c936119138161236b565b90506118a5565b508315610ac85760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610557565b60008181526001830160205260408120546119b057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610424565b506000610424565b60008181526001830160205260408120548015611aa15760006119dc600183612382565b85549091506000906119f090600190612382565b9050818114611a55576000866000018281548110611a1057611a1061211d565b9060005260206000200154905080876000018481548110611a3357611a3361211d565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611a6657611a66612395565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610424565b6000915050610424565b60006001600160e01b03198216637965db0b60e01b148061042457506301ffc9a760e01b6001600160e01b0319831614610424565b6001811115611b4f5760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e7365637574697665207472604482015274185b9cd9995c9cc81b9bdd081cdd5c1c1bdc9d1959605a1b6064820152608401610557565b816001600160a01b038516611bab57611ba681600a80546000838152600b60205260408120829055600182018355919091527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80155565b611bce565b836001600160a01b0316856001600160a01b031614611bce57611bce8582611c14565b6001600160a01b038416611bea57611be581611cb1565b611c0d565b846001600160a01b0316846001600160a01b031614611c0d57611c0d8482611d60565b5050505050565b60006001611c21846109aa565b611c2b9190612382565b600083815260096020526040902054909150808214611c7e576001600160a01b03841660009081526008602090815260408083208584528252808320548484528184208190558352600990915290208190555b5060009182526009602090815260408084208490556001600160a01b039094168352600881528383209183525290812055565b600a54600090611cc390600190612382565b6000838152600b6020526040812054600a8054939450909284908110611ceb57611ceb61211d565b9060005260206000200154905080600a8381548110611d0c57611d0c61211d565b6000918252602080832090910192909255828152600b9091526040808220849055858252812055600a805480611d4457611d44612395565b6001900381819060005260206000200160009055905550505050565b6000611d6b836109aa565b6001600160a01b039093166000908152600860209081526040808320868452825280832085905593825260099052919091209190915550565b6001600160e01b03198116811461083557600080fd5b600060208284031215611dcc57600080fd5b8135610ac881611da4565b60005b83811015611df2578181015183820152602001611dda565b50506000910152565b60008151808452611e13816020860160208601611dd7565b601f01601f19169290920160200192915050565b602081526000610ac86020830184611dfb565b600060208284031215611e4c57600080fd5b5035919050565b80356001600160a01b0381168114611e6a57600080fd5b919050565b60008060408385031215611e8257600080fd5b611e8b83611e53565b946020939093013593505050565b600080600060608486031215611eae57600080fd5b611eb784611e53565b9250611ec560208501611e53565b9150604084013590509250925092565b60008060408385031215611ee857600080fd5b82359150611ef860208401611e53565b90509250929050565b600060208284031215611f1357600080fd5b610ac882611e53565b60008060408385031215611f2f57600080fd5b50508035926020909101359150565b60008060408385031215611f5157600080fd5b611f5a83611e53565b915060208301358015158114611f6f57600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215611fa657600080fd5b611faf85611e53565b9350611fbd60208601611e53565b925060408501359150606085013567ffffffffffffffff80821115611fe157600080fd5b818701915087601f830112611ff557600080fd5b81358181111561200757612007611f7a565b604051601f8201601f19908116603f0116810190838211818310171561202f5761202f611f7a565b816040528281528a602084870101111561204857600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b6000806040838503121561207f57600080fd5b61208883611e53565b9150611ef860208401611e53565b600181811c908216806120aa57607f821691505b6020821081036120ca57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b602080825260189082015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604082015260600190565b60008351612177818460208801611dd7565b83519083019061218b818360208801611dd7565b01949350505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b6020808252601c908201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b815260008351612294816017850160208801611dd7565b7001034b99036b4b9b9b4b733903937b6329607d1b60179184019182015283516122c5816028840160208801611dd7565b01602801949350505050565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061230490830184611dfb565b9695505050505050565b60006020828403121561232057600080fd5b8151610ac881611da4565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176104245761042461232b565b808201808211156104245761042461232b565b60008161237a5761237a61232b565b506000190190565b818103818111156104245761042461232b565b634e487b7160e01b600052603160045260246000fdfe65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4552433732315072657365744d696e7465725061757365724175746f49643a20a2646970667358221220f586c29d0cbd3e2cee9bd99a648a34864226f46f9a05471902f3728b4f230c2864736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RootERC721PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootERC721Predicate\",\n \"sourceName\": \"contracts/root/RootERC721Predicate.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ERC721Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"ERC721DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ERC721Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"ERC721WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC721Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"depositBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"exitHelper\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newExitHelper\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC721Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC721Metadata\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC721Received\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onL2StateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b5061196b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100fb5760003560e01c8063cb10f94c116100a2578063f43cda8b11610071578063f43cda8b146102a1578063f4a120f7146102b4578063f6451255146102c7578063f8c8765e146102ee578063ff6f870c1461030157600080fd5b8063cb10f94c14610227578063d41f177114610240578063d7c9e3ec14610267578063f213159c1461028e57600080fd5b8063150b7a021461010057806347e7ef241461013c5780634fdca69d146101515780637efab4f51461017c57806395c7041c146101a5578063b1768065146101b8578063b68ad1e4146101ed578063c5ac2b1c14610200575b600080fd5b61011e61010e36600461112d565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020015b60405180910390f35b61014f61014a3660046111db565b610314565b005b600254610164906001600160a01b031681565b6040516001600160a01b039091168152602001610133565b61016461018a366004611207565b6004602052600090815260409020546001600160a01b031681565b600154610164906001600160a01b031681565b6101df7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610133565b600354610164906001600160a01b031681565b6101df7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b600054610164906201000090046001600160a01b031681565b6101df7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101df7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61014f61029c36600461122b565b610323565b61014f6102af36600461126c565b610333565b6101646102c2366004611207565b61050a565b6101df7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61014f6102fc3660046112f4565b61086a565b61014f61030f36600461139b565b610a78565b61031f823383610ae0565b5050565b61032e838383610ae0565b505050565b6001546001600160a01b031633146103a05760405162461bcd60e51b815260206004820152602560248201527f526f6f744552433732315072656469636174653a204f4e4c595f455849545f4860448201526422a62822a960d91b60648201526084015b60405180910390fd5b6002546001600160a01b0384811691161461040f5760405162461bcd60e51b815260206004820152602960248201527f526f6f744552433732315072656469636174653a204f4e4c595f4348494c445f60448201526850524544494341544560b81b6064820152608401610397565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286961043e60206000848661141d565b61044791611447565b036104665761046161045c826020818661141d565b610c66565b610504565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed261049560206000848661141d565b61049e91611447565b036104ad576104618282610d64565b60405162461bcd60e51b815260206004820152602660248201527f526f6f744552433732315072656469636174653a20494e56414c49445f5349476044820152654e415455524560d01b6064820152608401610397565b50505050565b60006001600160a01b03821661056d5760405162461bcd60e51b815260206004820152602260248201527f526f6f744552433732315072656469636174653a20494e56414c49445f544f4b60448201526122a760f11b6064820152608401610397565b6001600160a01b0382811660009081526004602052604090205416156105e15760405162461bcd60e51b815260206004820152602360248201527f526f6f744552433732315072656469636174653a20414c52454144595f4d415060448201526214115160ea1b6064820152608401610397565b6002546003546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b039283169260009261068f92911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b03858116600081815260046020819052604080832080546001600160a01b031916878716179055825481516306fdde0360e01b81529151969750620100009004909416946316f198319488947f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad948c9491936306fdde039380840193908290030181865afa15801561072c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610754919081019061148a565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610792573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107ba919081019061148a565b6040516020016107cd949392919061152c565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016107f9929190611573565b600060405180830381600087803b15801561081357600080fd5b505af1158015610827573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61790600090a39392505050565b600054610100900460ff161580801561088a5750600054600160ff909116105b806108a45750303b1580156108a4575060005460ff166001145b6109075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610397565b6000805460ff19166001179055801561092a576000805461ff0019166101001790555b6001600160a01b0385161580159061094a57506001600160a01b03841615155b801561095e57506001600160a01b03831615155b801561097257506001600160a01b03821615155b6109ce5760405162461bcd60e51b815260206004820152602760248201527f526f6f744552433732315072656469636174653a204241445f494e495449414c60448201526624ad20aa24a7a760c91b6064820152608401610397565b6000805462010000600160b01b031916620100006001600160a01b038881169190910291909117909155600180546001600160a01b031990811687841617909155600280548216868416179055600380549091169184169190911790558015610a71576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b828114610ad35760405162461bcd60e51b815260206004820152602360248201527f526f6f744552433732315072656469636174653a20494e56414c49445f4c454e60448201526208ea8960eb1b6064820152608401610397565b610a718585858585610ea5565b6000610aeb84611061565b604051632142170760e11b81529091506001600160a01b038516906342842e0e90610b1e9033903090879060040161159f565b600060405180830381600087803b158015610b3857600080fd5b505af1158015610b4c573d6000803e3d6000fd5b5050600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038a811682840152336060830152898116608083015260a08083018a90528351808403909101815260c08301938490526316f1983160e01b90935262010000909404841695506316f198319450610be2939092169160c401611573565b600060405180830381600087803b158015610bfc57600080fd5b505af1158015610c10573d6000803e3d6000fd5b505060408051338152602081018690526001600160a01b03808816945085811693508816917f40e242710be14b7d61d3b93e9d56b40df89cc4dbad8bb88da38c8e0c23809ba7910160405180910390a450505050565b6000808080610c77858701876115c3565b6001600160a01b0380851660009081526004602052604090205494985092965090945092501680610caa57610caa611614565b604051632142170760e11b81526001600160a01b038616906342842e0e90610cda9030908790879060040161159f565b600060405180830381600087803b158015610cf457600080fd5b505af1158015610d08573d6000803e3d6000fd5b5050604080516001600160a01b03888116825260208201879052808816945085811693508916917f8194f168e6e9e449d05a46936e071a710c0f22634eaadeb5b85a86540123931991015b60405180910390a450505050505050565b6000808080610d75858701876116b3565b6001600160a01b03808516600090815260046020526040902054949950929750909550935016905080610daa57610daa611614565b60005b8251811015610e5557856001600160a01b03166342842e0e30868481518110610dd857610dd86117a5565b6020026020010151868581518110610df257610df26117a5565b60200260200101516040518463ffffffff1660e01b8152600401610e189392919061159f565b600060405180830381600087803b158015610e3257600080fd5b505af1158015610e46573d6000803e3d6000fd5b50505050806001019050610dad565b50836001600160a01b0316816001600160a01b0316866001600160a01b03167f1b7b9713fdef5dfadf92f6d6e998eb1fc4763cee62a194a095d76349f7dce20c8686604051610d539291906117bb565b6000610eb086611061565b905060005b82811015610f4257866001600160a01b03166342842e0e3330878786818110610ee057610ee06117a5565b905060200201356040518463ffffffff1660e01b8152600401610f059392919061159f565b600060405180830381600087803b158015610f1f57600080fd5b505af1158015610f33573d6000803e3d6000fd5b50505050806001019050610eb5565b506000546002546040516001600160a01b03620100009093048316926316f19831921690610fa0907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908b9033908c908c908c908c906020016118ba565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610fcc929190611573565b600060405180830381600087803b158015610fe657600080fd5b505af1158015610ffa573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316876001600160a01b03167f02c575a943105cda454293b7ac636c87c94ff1bfcfac968aa5423e6b9b312ee988888888604051611051949392919061190e565b60405180910390a4505050505050565b6001600160a01b03808216600090815260046020526040902054168061108d5761108a8261050a565b90505b6001600160a01b0381166110a3576110a3611614565b919050565b6001600160a01b03811681146110bd57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156110fe576110fe6110c0565b604052919050565b60006001600160401b0382111561111f5761111f6110c0565b50601f01601f191660200190565b6000806000806080858703121561114357600080fd5b843561114e816110a8565b9350602085013561115e816110a8565b92506040850135915060608501356001600160401b0381111561118057600080fd5b8501601f8101871361119157600080fd5b80356111a461119f82611106565b6110d6565b8181528860208385010111156111b957600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080604083850312156111ee57600080fd5b82356111f9816110a8565b946020939093013593505050565b60006020828403121561121957600080fd5b8135611224816110a8565b9392505050565b60008060006060848603121561124057600080fd5b833561124b816110a8565b9250602084013561125b816110a8565b929592945050506040919091013590565b6000806000806060858703121561128257600080fd5b843593506020850135611294816110a8565b925060408501356001600160401b03808211156112b057600080fd5b818701915087601f8301126112c457600080fd5b8135818111156112d357600080fd5b8860208285010111156112e557600080fd5b95989497505060200194505050565b6000806000806080858703121561130a57600080fd5b8435611315816110a8565b93506020850135611325816110a8565b92506040850135611335816110a8565b91506060850135611345816110a8565b939692955090935050565b60008083601f84011261136257600080fd5b5081356001600160401b0381111561137957600080fd5b6020830191508360208260051b850101111561139457600080fd5b9250929050565b6000806000806000606086880312156113b357600080fd5b85356113be816110a8565b945060208601356001600160401b03808211156113da57600080fd5b6113e689838a01611350565b909650945060408801359150808211156113ff57600080fd5b5061140c88828901611350565b969995985093965092949392505050565b6000808585111561142d57600080fd5b8386111561143a57600080fd5b5050820193919092039150565b8035602083101561146057600019602084900360031b1b165b92915050565b60005b83811015611481578181015183820152602001611469565b50506000910152565b60006020828403121561149c57600080fd5b81516001600160401b038111156114b257600080fd5b8201601f810184136114c357600080fd5b80516114d161119f82611106565b8181528560208385010111156114e657600080fd5b6114f7826020830160208601611466565b95945050505050565b60008151808452611518816020860160208601611466565b601f01601f19169290920160200192915050565b8481526001600160a01b038416602082015260806040820181905260009061155690830185611500565b82810360608401526115688185611500565b979650505050505050565b6001600160a01b038316815260406020820181905260009061159790830184611500565b949350505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600080600080608085870312156115d957600080fd5b84356115e4816110a8565b935060208501356115f4816110a8565b92506040850135611604816110a8565b9396929550929360600135925050565b634e487b7160e01b600052600160045260246000fd5b60006001600160401b03821115611643576116436110c0565b5060051b60200190565b600082601f83011261165e57600080fd5b8135602061166e61119f8361162a565b82815260059290921b8401810191818101908684111561168d57600080fd5b8286015b848110156116a85780358352918301918301611691565b509695505050505050565b600080600080600060a086880312156116cb57600080fd5b853594506020808701356116de816110a8565b945060408701356116ee816110a8565b935060608701356001600160401b038082111561170a57600080fd5b818901915089601f83011261171e57600080fd5b813561172c61119f8261162a565b81815260059190911b8301840190848101908c83111561174b57600080fd5b938501935b82851015611772578435611763816110a8565b82529385019390850190611750565b96505050608089013592508083111561178a57600080fd5b50506117988882890161164d565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b828110156117fd5781516001600160a01b0316845292840192908401906001016117d8565b5050508381038285015284518082528583019183019060005b8181101561183257835183529284019291840191600101611816565b5090979650505050505050565b8183526000602080850194508260005b8581101561187d578135611862816110a8565b6001600160a01b03168752958201959082019060010161184f565b509495945050505050565b81835260006001600160fb1b038311156118a157600080fd5b8260051b80836020870137939093016020019392505050565b8781526001600160a01b0387811660208301528616604082015260a0606082018190526000906118ed908301868861183f565b8281036080840152611900818587611888565b9a9950505050505050505050565b60408152600061192260408301868861183f565b828103602084015261156881858761188856fea2646970667358221220bfd1948d5c4cd21e4982d8b20eeb9cb5a362f336cd5a6789511e6ae9d664a37e64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100fb5760003560e01c8063cb10f94c116100a2578063f43cda8b11610071578063f43cda8b146102a1578063f4a120f7146102b4578063f6451255146102c7578063f8c8765e146102ee578063ff6f870c1461030157600080fd5b8063cb10f94c14610227578063d41f177114610240578063d7c9e3ec14610267578063f213159c1461028e57600080fd5b8063150b7a021461010057806347e7ef241461013c5780634fdca69d146101515780637efab4f51461017c57806395c7041c146101a5578063b1768065146101b8578063b68ad1e4146101ed578063c5ac2b1c14610200575b600080fd5b61011e61010e36600461112d565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020015b60405180910390f35b61014f61014a3660046111db565b610314565b005b600254610164906001600160a01b031681565b6040516001600160a01b039091168152602001610133565b61016461018a366004611207565b6004602052600090815260409020546001600160a01b031681565b600154610164906001600160a01b031681565b6101df7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610133565b600354610164906001600160a01b031681565b6101df7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b600054610164906201000090046001600160a01b031681565b6101df7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101df7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61014f61029c36600461122b565b610323565b61014f6102af36600461126c565b610333565b6101646102c2366004611207565b61050a565b6101df7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61014f6102fc3660046112f4565b61086a565b61014f61030f36600461139b565b610a78565b61031f823383610ae0565b5050565b61032e838383610ae0565b505050565b6001546001600160a01b031633146103a05760405162461bcd60e51b815260206004820152602560248201527f526f6f744552433732315072656469636174653a204f4e4c595f455849545f4860448201526422a62822a960d91b60648201526084015b60405180910390fd5b6002546001600160a01b0384811691161461040f5760405162461bcd60e51b815260206004820152602960248201527f526f6f744552433732315072656469636174653a204f4e4c595f4348494c445f60448201526850524544494341544560b81b6064820152608401610397565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286961043e60206000848661141d565b61044791611447565b036104665761046161045c826020818661141d565b610c66565b610504565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed261049560206000848661141d565b61049e91611447565b036104ad576104618282610d64565b60405162461bcd60e51b815260206004820152602660248201527f526f6f744552433732315072656469636174653a20494e56414c49445f5349476044820152654e415455524560d01b6064820152608401610397565b50505050565b60006001600160a01b03821661056d5760405162461bcd60e51b815260206004820152602260248201527f526f6f744552433732315072656469636174653a20494e56414c49445f544f4b60448201526122a760f11b6064820152608401610397565b6001600160a01b0382811660009081526004602052604090205416156105e15760405162461bcd60e51b815260206004820152602360248201527f526f6f744552433732315072656469636174653a20414c52454144595f4d415060448201526214115160ea1b6064820152608401610397565b6002546003546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b039283169260009261068f92911690603401604051602081830303815290604052805190602001208460405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b03858116600081815260046020819052604080832080546001600160a01b031916878716179055825481516306fdde0360e01b81529151969750620100009004909416946316f198319488947f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad948c9491936306fdde039380840193908290030181865afa15801561072c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610754919081019061148a565b896001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015610792573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107ba919081019061148a565b6040516020016107cd949392919061152c565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016107f9929190611573565b600060405180830381600087803b15801561081357600080fd5b505af1158015610827573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61790600090a39392505050565b600054610100900460ff161580801561088a5750600054600160ff909116105b806108a45750303b1580156108a4575060005460ff166001145b6109075760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610397565b6000805460ff19166001179055801561092a576000805461ff0019166101001790555b6001600160a01b0385161580159061094a57506001600160a01b03841615155b801561095e57506001600160a01b03831615155b801561097257506001600160a01b03821615155b6109ce5760405162461bcd60e51b815260206004820152602760248201527f526f6f744552433732315072656469636174653a204241445f494e495449414c60448201526624ad20aa24a7a760c91b6064820152608401610397565b6000805462010000600160b01b031916620100006001600160a01b038881169190910291909117909155600180546001600160a01b031990811687841617909155600280548216868416179055600380549091169184169190911790558015610a71576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b828114610ad35760405162461bcd60e51b815260206004820152602360248201527f526f6f744552433732315072656469636174653a20494e56414c49445f4c454e60448201526208ea8960eb1b6064820152608401610397565b610a718585858585610ea5565b6000610aeb84611061565b604051632142170760e11b81529091506001600160a01b038516906342842e0e90610b1e9033903090879060040161159f565b600060405180830381600087803b158015610b3857600080fd5b505af1158015610b4c573d6000803e3d6000fd5b5050600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038a811682840152336060830152898116608083015260a08083018a90528351808403909101815260c08301938490526316f1983160e01b90935262010000909404841695506316f198319450610be2939092169160c401611573565b600060405180830381600087803b158015610bfc57600080fd5b505af1158015610c10573d6000803e3d6000fd5b505060408051338152602081018690526001600160a01b03808816945085811693508816917f40e242710be14b7d61d3b93e9d56b40df89cc4dbad8bb88da38c8e0c23809ba7910160405180910390a450505050565b6000808080610c77858701876115c3565b6001600160a01b0380851660009081526004602052604090205494985092965090945092501680610caa57610caa611614565b604051632142170760e11b81526001600160a01b038616906342842e0e90610cda9030908790879060040161159f565b600060405180830381600087803b158015610cf457600080fd5b505af1158015610d08573d6000803e3d6000fd5b5050604080516001600160a01b03888116825260208201879052808816945085811693508916917f8194f168e6e9e449d05a46936e071a710c0f22634eaadeb5b85a86540123931991015b60405180910390a450505050505050565b6000808080610d75858701876116b3565b6001600160a01b03808516600090815260046020526040902054949950929750909550935016905080610daa57610daa611614565b60005b8251811015610e5557856001600160a01b03166342842e0e30868481518110610dd857610dd86117a5565b6020026020010151868581518110610df257610df26117a5565b60200260200101516040518463ffffffff1660e01b8152600401610e189392919061159f565b600060405180830381600087803b158015610e3257600080fd5b505af1158015610e46573d6000803e3d6000fd5b50505050806001019050610dad565b50836001600160a01b0316816001600160a01b0316866001600160a01b03167f1b7b9713fdef5dfadf92f6d6e998eb1fc4763cee62a194a095d76349f7dce20c8686604051610d539291906117bb565b6000610eb086611061565b905060005b82811015610f4257866001600160a01b03166342842e0e3330878786818110610ee057610ee06117a5565b905060200201356040518463ffffffff1660e01b8152600401610f059392919061159f565b600060405180830381600087803b158015610f1f57600080fd5b505af1158015610f33573d6000803e3d6000fd5b50505050806001019050610eb5565b506000546002546040516001600160a01b03620100009093048316926316f19831921690610fa0907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908b9033908c908c908c908c906020016118ba565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610fcc929190611573565b600060405180830381600087803b158015610fe657600080fd5b505af1158015610ffa573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316876001600160a01b03167f02c575a943105cda454293b7ac636c87c94ff1bfcfac968aa5423e6b9b312ee988888888604051611051949392919061190e565b60405180910390a4505050505050565b6001600160a01b03808216600090815260046020526040902054168061108d5761108a8261050a565b90505b6001600160a01b0381166110a3576110a3611614565b919050565b6001600160a01b03811681146110bd57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156110fe576110fe6110c0565b604052919050565b60006001600160401b0382111561111f5761111f6110c0565b50601f01601f191660200190565b6000806000806080858703121561114357600080fd5b843561114e816110a8565b9350602085013561115e816110a8565b92506040850135915060608501356001600160401b0381111561118057600080fd5b8501601f8101871361119157600080fd5b80356111a461119f82611106565b6110d6565b8181528860208385010111156111b957600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080604083850312156111ee57600080fd5b82356111f9816110a8565b946020939093013593505050565b60006020828403121561121957600080fd5b8135611224816110a8565b9392505050565b60008060006060848603121561124057600080fd5b833561124b816110a8565b9250602084013561125b816110a8565b929592945050506040919091013590565b6000806000806060858703121561128257600080fd5b843593506020850135611294816110a8565b925060408501356001600160401b03808211156112b057600080fd5b818701915087601f8301126112c457600080fd5b8135818111156112d357600080fd5b8860208285010111156112e557600080fd5b95989497505060200194505050565b6000806000806080858703121561130a57600080fd5b8435611315816110a8565b93506020850135611325816110a8565b92506040850135611335816110a8565b91506060850135611345816110a8565b939692955090935050565b60008083601f84011261136257600080fd5b5081356001600160401b0381111561137957600080fd5b6020830191508360208260051b850101111561139457600080fd5b9250929050565b6000806000806000606086880312156113b357600080fd5b85356113be816110a8565b945060208601356001600160401b03808211156113da57600080fd5b6113e689838a01611350565b909650945060408801359150808211156113ff57600080fd5b5061140c88828901611350565b969995985093965092949392505050565b6000808585111561142d57600080fd5b8386111561143a57600080fd5b5050820193919092039150565b8035602083101561146057600019602084900360031b1b165b92915050565b60005b83811015611481578181015183820152602001611469565b50506000910152565b60006020828403121561149c57600080fd5b81516001600160401b038111156114b257600080fd5b8201601f810184136114c357600080fd5b80516114d161119f82611106565b8181528560208385010111156114e657600080fd5b6114f7826020830160208601611466565b95945050505050565b60008151808452611518816020860160208601611466565b601f01601f19169290920160200192915050565b8481526001600160a01b038416602082015260806040820181905260009061155690830185611500565b82810360608401526115688185611500565b979650505050505050565b6001600160a01b038316815260406020820181905260009061159790830184611500565b949350505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b600080600080608085870312156115d957600080fd5b84356115e4816110a8565b935060208501356115f4816110a8565b92506040850135611604816110a8565b9396929550929360600135925050565b634e487b7160e01b600052600160045260246000fd5b60006001600160401b03821115611643576116436110c0565b5060051b60200190565b600082601f83011261165e57600080fd5b8135602061166e61119f8361162a565b82815260059290921b8401810191818101908684111561168d57600080fd5b8286015b848110156116a85780358352918301918301611691565b509695505050505050565b600080600080600060a086880312156116cb57600080fd5b853594506020808701356116de816110a8565b945060408701356116ee816110a8565b935060608701356001600160401b038082111561170a57600080fd5b818901915089601f83011261171e57600080fd5b813561172c61119f8261162a565b81815260059190911b8301840190848101908c83111561174b57600080fd5b938501935b82851015611772578435611763816110a8565b82529385019390850190611750565b96505050608089013592508083111561178a57600080fd5b50506117988882890161164d565b9150509295509295909350565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b828110156117fd5781516001600160a01b0316845292840192908401906001016117d8565b5050508381038285015284518082528583019183019060005b8181101561183257835183529284019291840191600101611816565b5090979650505050505050565b8183526000602080850194508260005b8581101561187d578135611862816110a8565b6001600160a01b03168752958201959082019060010161184f565b509495945050505050565b81835260006001600160fb1b038311156118a157600080fd5b8260051b80836020870137939093016020019392505050565b8781526001600160a01b0387811660208301528616604082015260a0606082018190526000906118ed908301868861183f565b8281036080840152611900818587611888565b9a9950505050505050505050565b60408152600061192260408301868861183f565b828103602084015261156881858761188856fea2646970667358221220bfd1948d5c4cd21e4982d8b20eeb9cb5a362f336cd5a6789511e6ae9d664a37e64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildMintableERC721PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildMintableERC721Predicate\",\n \"sourceName\": \"contracts/root/ChildMintableERC721Predicate.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"MintableERC721Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"MintableERC721DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"MintableERC721Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"MintableERC721WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"exitHelper\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newExitHelper\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC721Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onL2StateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC721Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"withdrawBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC721\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611f01806100206000396000f3fe608060405234801561001057600080fd5b50600436106100d55760003560e01c8063cb10f94c11610087578063cb10f94c146101ca578063d41f1771146101e3578063d7c9e3ec1461020a578063f3fef3a314610231578063f43cda8b14610244578063f645125514610257578063f691325c1461027e578063f8c8765e1461029157600080fd5b80636f33e695146100da5780637efab4f5146100ef57806395c7041c14610135578063b176806514610148578063b68ad1e41461017d578063c3b35a7e14610190578063c5ac2b1c146101a3575b600080fd5b6100ed6100e836600461158c565b6102a4565b005b6101186100fd36600461160e565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600154610118906001600160a01b031681565b61016f7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60405190815260200161012c565b600354610118906001600160a01b031681565b6100ed61019e366004611632565b6102b8565b61016f7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b600054610118906201000090046001600160a01b031681565b61016f7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61016f7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b6100ed61023f366004611673565b6102c8565b6100ed61025236600461169f565b6102d7565b61016f7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b600254610118906001600160a01b031681565b6100ed61029f366004611727565b61050f565b6102b18585858585610627565b5050505050565b6102c383838361099a565b505050565b6102d382338361099a565b5050565b6001546001600160a01b0316331461034d5760405162461bcd60e51b815260206004820152602e60248201527f4368696c644d696e7461626c654552433732315072656469636174653a204f4e60448201526d262cafa2ac24aa2fa422a62822a960911b60648201526084015b60405180910390fd5b6002546001600160a01b038481169116146103c45760405162461bcd60e51b815260206004820152603160248201527f4368696c644d696e7461626c654552433732315072656469636174653a204f4e6044820152704c595f524f4f545f50524544494341544560781b6064820152608401610344565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216103f3602060008486611783565b6103fc916117ad565b0361041b576104166104118260208186611783565b610ca9565b610509565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1861044a602060008486611783565b610453916117ad565b03610462576104168282610f1f565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad610491602060008486611783565b61049a916117ad565b036104a9576104168282611185565b60405162461bcd60e51b815260206004820152602f60248201527f4368696c644d696e7461626c654552433732315072656469636174653a20494e60448201526e56414c49445f5349474e415455524560881b6064820152608401610344565b50505050565b600054610100900460ff161580801561052f5750600054600160ff909116105b806105495750303b158015610549575060005460ff166001145b6105ac5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610344565b6000805460ff1916600117905580156105cf576000805461ff0019166101001790555b6105db858585856112f5565b80156102b1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b84610631816113fd565b61064d5760405162461bcd60e51b8152600401610344906117cb565b6000866001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561068d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b19190611815565b6001600160a01b038181166000908152600460205260409020549192508881169116146106f05760405162461bcd60e51b815260040161034490611832565b6001600160a01b0381166107065761070661187e565b306001600160a01b0316876001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190611815565b6001600160a01b0316146107885761078861187e565b8483146107ec5760405162461bcd60e51b815260206004820152602c60248201527f4368696c644d696e7461626c654552433732315072656469636174653a20494e60448201526b0ac82989288be988a9c8ea8960a31b6064820152608401610344565b60405163b2dc5dc360e01b81526001600160a01b0388169063b2dc5dc39061081c903390889088906004016118c6565b6020604051808303816000875af115801561083b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085f91906118f4565b61087b5760405162461bcd60e51b815260040161034490611916565b6000546002546040516001600160a01b03620100009093048316926316f198319216906108d8907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908d908d908d908d906020016119a8565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610904929190611a42565b600060405180830381600087803b15801561091e57600080fd5b505af1158015610932573d6000803e3d6000fd5b50505050336001600160a01b0316876001600160a01b0316826001600160a01b03167f5faed28924bb6c5b0d3eea1cc028b4814f49c39eac622b81ef17035d794ac774898989896040516109899493929190611a6e565b60405180910390a450505050505050565b826109a4816113fd565b6109c05760405162461bcd60e51b8152600401610344906117cb565b6000846001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a249190611815565b6001600160a01b03818116600090815260046020526040902054919250868116911614610a635760405162461bcd60e51b815260040161034490611832565b6001600160a01b038116610a7957610a7961187e565b306001600160a01b0316856001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae59190611815565b6001600160a01b031614610afb57610afb61187e565b604051632770a7eb60e21b81526001600160a01b03861690639dc29fac90610b299033908790600401611aa0565b6020604051808303816000875af1158015610b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6c91906118f4565b610b885760405162461bcd60e51b815260040161034490611916565b600054600254604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152888116608083015260a08083018990528351808403909101815260c08301938490526316f1983160e01b909352620100009094048416936316f1983193610c199391169160c401611a42565b600060405180830381600087803b158015610c3357600080fd5b505af1158015610c47573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b0316826001600160a01b03167f85b3d9b3b871daf1d10c7ba1016854e371ab931adef5569172f0289515a9a6de3387604051610c9a929190611aa0565b60405180910390a45050505050565b6000808080610cba85870187611ab9565b6001600160a01b0380851660009081526004602052604090205494985092965090945092501680610cfd5760405162461bcd60e51b815260040161034490611832565b610d06816113fd565b610d1257610d1261187e565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d769190611815565b9050856001600160a01b0316816001600160a01b031614610d9957610d9961187e565b6001600160a01b038116610daf57610daf61187e565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1b9190611815565b6001600160a01b031614610e3157610e3161187e565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610e5f9087908790600401611aa0565b6020604051808303816000875af1158015610e7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea291906118f4565b610ebe5760405162461bcd60e51b815260040161034490611b0a565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fb26f02b79335e4b2c506d9e5ae02e042b464a7556419bbc42522fc92833aff528887604051610f0d929190611aa0565b60405180910390a45050505050505050565b6000808080610f3085870187611c27565b6001600160a01b03808516600090815260046020526040902054949950929750909550935016905080610f755760405162461bcd60e51b815260040161034490611832565b610f7e816113fd565b610f8a57610f8a61187e565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fee9190611815565b9050856001600160a01b0316816001600160a01b0316146110115761101161187e565b6001600160a01b0381166110275761102761187e565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561106f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110939190611815565b6001600160a01b0316146110a9576110a961187e565b604051637c88e3d960e01b81526001600160a01b03831690637c88e3d9906110d79087908790600401611d19565b6020604051808303816000875af11580156110f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111a91906118f4565b6111365760405162461bcd60e51b815260040161034490611b0a565b846001600160a01b0316826001600160a01b0316876001600160a01b03167f7f51e520a281df2deae2754a9232b5a78c8cfeae79568668a0a97a116e1401b88787604051610f0d929190611d19565b6000808061119584860186611e0c565b91955093509150506001600160a01b0383166111b3576111b361187e565b6001600160a01b0383811660009081526004602052604090205416156111db576111db61187e565b6003546040516bffffffffffffffffffffffff19606086901b16602082015260009161122b916001600160a01b039091169060340160405160208183030381529060405280519060200120611492565b6001600160a01b0385811660009081526004602081905260409182902080546001600160a01b03191693851693841790559051639065714760e01b815292935090916390657147916112839188918891889101611e8b565b600060405180830381600087803b15801561129d57600080fd5b505af11580156112b1573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f0a1eaf9aa124c3f84c9dd77f7016af0f16f67639abb913af1697387db01f5ca590600090a3505050505050565b6001600160a01b0384161580159061131557506001600160a01b03831615155b801561132957506001600160a01b03821615155b801561133d57506001600160a01b03811615155b6113a25760405162461bcd60e51b815260206004820152603060248201527f4368696c644d696e7461626c654552433732315072656469636174653a20424160448201526f222fa4a724aa24a0a624ad20aa24a7a760811b6064820152608401610344565b600080546001600160a01b03958616620100000262010000600160b01b0319909116179055600180549385166001600160a01b0319948516179055600280549285169284169290921790915560038054919093169116179055565b6000816001600160a01b03163b60000361141957506000919050565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611480575060408051601f3d908101601f1916820190925261147d918101906118f4565b60015b61148c57506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b03811661148c5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b6044820152606401610344565b6001600160a01b038116811461153e57600080fd5b50565b60008083601f84011261155357600080fd5b5081356001600160401b0381111561156a57600080fd5b6020830191508360208260051b850101111561158557600080fd5b9250929050565b6000806000806000606086880312156115a457600080fd5b85356115af81611529565b945060208601356001600160401b03808211156115cb57600080fd5b6115d789838a01611541565b909650945060408801359150808211156115f057600080fd5b506115fd88828901611541565b969995985093965092949392505050565b60006020828403121561162057600080fd5b813561162b81611529565b9392505050565b60008060006060848603121561164757600080fd5b833561165281611529565b9250602084013561166281611529565b929592945050506040919091013590565b6000806040838503121561168657600080fd5b823561169181611529565b946020939093013593505050565b600080600080606085870312156116b557600080fd5b8435935060208501356116c781611529565b925060408501356001600160401b03808211156116e357600080fd5b818701915087601f8301126116f757600080fd5b81358181111561170657600080fd5b88602082850101111561171857600080fd5b95989497505060200194505050565b6000806000806080858703121561173d57600080fd5b843561174881611529565b9350602085013561175881611529565b9250604085013561176881611529565b9150606085013561177881611529565b939692955090935050565b6000808585111561179357600080fd5b838611156117a057600080fd5b5050820193919092039150565b8035602083101561148c57600019602084900360031b1b1692915050565b6020808252602a908201527f4368696c644d696e7461626c654552433732315072656469636174653a204e4f6040820152691517d0d3d395149050d560b21b606082015260800190565b60006020828403121561182757600080fd5b815161162b81611529565b6020808252602c908201527f4368696c644d696e7461626c654552433732315072656469636174653a20554e60408201526b26a0a82822a22faa27a5a2a760a11b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b038311156118ad57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b03841681526040602082018190526000906118eb9083018486611894565b95945050505050565b60006020828403121561190657600080fd5b8151801515811461162b57600080fd5b60208082526029908201527f4368696c644d696e7461626c654552433732315072656469636174653a204255604082015268149397d1905253115160ba1b606082015260800190565b8183526000602080850194508260005b8581101561199d57813561198281611529565b6001600160a01b03168752958201959082019060010161196f565b509495945050505050565b8781526001600160a01b0387811660208301528616604082015260a0606082018190526000906119db908301868861195f565b82810360808401526119ee818587611894565b9a9950505050505050505050565b6000815180845260005b81811015611a2257602081850181015186830182015201611a06565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611a66908301846119fc565b949350505050565b604081526000611a8260408301868861195f565b8281036020840152611a95818587611894565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b60008060008060808587031215611acf57600080fd5b8435611ada81611529565b93506020850135611aea81611529565b92506040850135611afa81611529565b9396929550929360600135925050565b60208082526029908201527f4368696c644d696e7461626c654552433732315072656469636174653a204d49604082015268139517d1905253115160ba1b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611b9157611b91611b53565b604052919050565b60006001600160401b03821115611bb257611bb2611b53565b5060051b60200190565b600082601f830112611bcd57600080fd5b81356020611be2611bdd83611b99565b611b69565b82815260059290921b84018101918181019086841115611c0157600080fd5b8286015b84811015611c1c5780358352918301918301611c05565b509695505050505050565b600080600080600060a08688031215611c3f57600080fd5b85359450602080870135611c5281611529565b94506040870135611c6281611529565b935060608701356001600160401b0380821115611c7e57600080fd5b818901915089601f830112611c9257600080fd5b8135611ca0611bdd82611b99565b81815260059190911b8301840190848101908c831115611cbf57600080fd5b938501935b82851015611ce6578435611cd781611529565b82529385019390850190611cc4565b965050506080890135925080831115611cfe57600080fd5b5050611d0c88828901611bbc565b9150509295509295909350565b604080825283519082018190526000906020906060840190828701845b82811015611d5b5781516001600160a01b031684529284019290840190600101611d36565b5050508381038285015284518082528583019183019060005b81811015611d9057835183529284019291840191600101611d74565b5090979650505050505050565b600082601f830112611dae57600080fd5b81356001600160401b03811115611dc757611dc7611b53565b611dda601f8201601f1916602001611b69565b818152846020838601011115611def57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611e2257600080fd5b843593506020850135611e3481611529565b925060408501356001600160401b0380821115611e5057600080fd5b611e5c88838901611d9d565b93506060870135915080821115611e7257600080fd5b50611e7f87828801611d9d565b91505092959194509250565b6001600160a01b0384168152606060208201819052600090611eaf908301856119fc565b8281036040840152611ec181856119fc565b969550505050505056fea2646970667358221220c8b583610f0e8aefa292fd059d42937fb210322169349afab2ad08a7f054e61d64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100d55760003560e01c8063cb10f94c11610087578063cb10f94c146101ca578063d41f1771146101e3578063d7c9e3ec1461020a578063f3fef3a314610231578063f43cda8b14610244578063f645125514610257578063f691325c1461027e578063f8c8765e1461029157600080fd5b80636f33e695146100da5780637efab4f5146100ef57806395c7041c14610135578063b176806514610148578063b68ad1e41461017d578063c3b35a7e14610190578063c5ac2b1c146101a3575b600080fd5b6100ed6100e836600461158c565b6102a4565b005b6101186100fd36600461160e565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600154610118906001600160a01b031681565b61016f7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b60405190815260200161012c565b600354610118906001600160a01b031681565b6100ed61019e366004611632565b6102b8565b61016f7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b600054610118906201000090046001600160a01b031681565b61016f7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b61016f7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b6100ed61023f366004611673565b6102c8565b6100ed61025236600461169f565b6102d7565b61016f7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b600254610118906001600160a01b031681565b6100ed61029f366004611727565b61050f565b6102b18585858585610627565b5050505050565b6102c383838361099a565b505050565b6102d382338361099a565b5050565b6001546001600160a01b0316331461034d5760405162461bcd60e51b815260206004820152602e60248201527f4368696c644d696e7461626c654552433732315072656469636174653a204f4e60448201526d262cafa2ac24aa2fa422a62822a960911b60648201526084015b60405180910390fd5b6002546001600160a01b038481169116146103c45760405162461bcd60e51b815260206004820152603160248201527f4368696c644d696e7461626c654552433732315072656469636174653a204f4e6044820152704c595f524f4f545f50524544494341544560781b6064820152608401610344565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216103f3602060008486611783565b6103fc916117ad565b0361041b576104166104118260208186611783565b610ca9565b610509565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1861044a602060008486611783565b610453916117ad565b03610462576104168282610f1f565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad610491602060008486611783565b61049a916117ad565b036104a9576104168282611185565b60405162461bcd60e51b815260206004820152602f60248201527f4368696c644d696e7461626c654552433732315072656469636174653a20494e60448201526e56414c49445f5349474e415455524560881b6064820152608401610344565b50505050565b600054610100900460ff161580801561052f5750600054600160ff909116105b806105495750303b158015610549575060005460ff166001145b6105ac5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610344565b6000805460ff1916600117905580156105cf576000805461ff0019166101001790555b6105db858585856112f5565b80156102b1576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050565b84610631816113fd565b61064d5760405162461bcd60e51b8152600401610344906117cb565b6000866001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561068d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b19190611815565b6001600160a01b038181166000908152600460205260409020549192508881169116146106f05760405162461bcd60e51b815260040161034490611832565b6001600160a01b0381166107065761070661187e565b306001600160a01b0316876001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561074e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107729190611815565b6001600160a01b0316146107885761078861187e565b8483146107ec5760405162461bcd60e51b815260206004820152602c60248201527f4368696c644d696e7461626c654552433732315072656469636174653a20494e60448201526b0ac82989288be988a9c8ea8960a31b6064820152608401610344565b60405163b2dc5dc360e01b81526001600160a01b0388169063b2dc5dc39061081c903390889088906004016118c6565b6020604051808303816000875af115801561083b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085f91906118f4565b61087b5760405162461bcd60e51b815260040161034490611916565b6000546002546040516001600160a01b03620100009093048316926316f198319216906108d8907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908d908d908d908d906020016119a8565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610904929190611a42565b600060405180830381600087803b15801561091e57600080fd5b505af1158015610932573d6000803e3d6000fd5b50505050336001600160a01b0316876001600160a01b0316826001600160a01b03167f5faed28924bb6c5b0d3eea1cc028b4814f49c39eac622b81ef17035d794ac774898989896040516109899493929190611a6e565b60405180910390a450505050505050565b826109a4816113fd565b6109c05760405162461bcd60e51b8152600401610344906117cb565b6000846001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a249190611815565b6001600160a01b03818116600090815260046020526040902054919250868116911614610a635760405162461bcd60e51b815260040161034490611832565b6001600160a01b038116610a7957610a7961187e565b306001600160a01b0316856001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ae59190611815565b6001600160a01b031614610afb57610afb61187e565b604051632770a7eb60e21b81526001600160a01b03861690639dc29fac90610b299033908790600401611aa0565b6020604051808303816000875af1158015610b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6c91906118f4565b610b885760405162461bcd60e51b815260040161034490611916565b600054600254604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152888116608083015260a08083018990528351808403909101815260c08301938490526316f1983160e01b909352620100009094048416936316f1983193610c199391169160c401611a42565b600060405180830381600087803b158015610c3357600080fd5b505af1158015610c47573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b0316826001600160a01b03167f85b3d9b3b871daf1d10c7ba1016854e371ab931adef5569172f0289515a9a6de3387604051610c9a929190611aa0565b60405180910390a45050505050565b6000808080610cba85870187611ab9565b6001600160a01b0380851660009081526004602052604090205494985092965090945092501680610cfd5760405162461bcd60e51b815260040161034490611832565b610d06816113fd565b610d1257610d1261187e565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d769190611815565b9050856001600160a01b0316816001600160a01b031614610d9957610d9961187e565b6001600160a01b038116610daf57610daf61187e565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1b9190611815565b6001600160a01b031614610e3157610e3161187e565b6040516340c10f1960e01b81526001600160a01b038316906340c10f1990610e5f9087908790600401611aa0565b6020604051808303816000875af1158015610e7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea291906118f4565b610ebe5760405162461bcd60e51b815260040161034490611b0a565b836001600160a01b0316826001600160a01b0316876001600160a01b03167fb26f02b79335e4b2c506d9e5ae02e042b464a7556419bbc42522fc92833aff528887604051610f0d929190611aa0565b60405180910390a45050505050505050565b6000808080610f3085870187611c27565b6001600160a01b03808516600090815260046020526040902054949950929750909550935016905080610f755760405162461bcd60e51b815260040161034490611832565b610f7e816113fd565b610f8a57610f8a61187e565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fee9190611815565b9050856001600160a01b0316816001600160a01b0316146110115761101161187e565b6001600160a01b0381166110275761102761187e565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa15801561106f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110939190611815565b6001600160a01b0316146110a9576110a961187e565b604051637c88e3d960e01b81526001600160a01b03831690637c88e3d9906110d79087908790600401611d19565b6020604051808303816000875af11580156110f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061111a91906118f4565b6111365760405162461bcd60e51b815260040161034490611b0a565b846001600160a01b0316826001600160a01b0316876001600160a01b03167f7f51e520a281df2deae2754a9232b5a78c8cfeae79568668a0a97a116e1401b88787604051610f0d929190611d19565b6000808061119584860186611e0c565b91955093509150506001600160a01b0383166111b3576111b361187e565b6001600160a01b0383811660009081526004602052604090205416156111db576111db61187e565b6003546040516bffffffffffffffffffffffff19606086901b16602082015260009161122b916001600160a01b039091169060340160405160208183030381529060405280519060200120611492565b6001600160a01b0385811660009081526004602081905260409182902080546001600160a01b03191693851693841790559051639065714760e01b815292935090916390657147916112839188918891889101611e8b565b600060405180830381600087803b15801561129d57600080fd5b505af11580156112b1573d6000803e3d6000fd5b50506040516001600160a01b038085169350871691507f0a1eaf9aa124c3f84c9dd77f7016af0f16f67639abb913af1697387db01f5ca590600090a3505050505050565b6001600160a01b0384161580159061131557506001600160a01b03831615155b801561132957506001600160a01b03821615155b801561133d57506001600160a01b03811615155b6113a25760405162461bcd60e51b815260206004820152603060248201527f4368696c644d696e7461626c654552433732315072656469636174653a20424160448201526f222fa4a724aa24a0a624ad20aa24a7a760811b6064820152608401610344565b600080546001600160a01b03958616620100000262010000600160b01b0319909116179055600180549385166001600160a01b0319948516179055600280549285169284169290921790915560038054919093169116179055565b6000816001600160a01b03163b60000361141957506000919050565b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa925050508015611480575060408051601f3d908101601f1916820190925261147d918101906118f4565b60015b61148c57506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b03811661148c5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b6044820152606401610344565b6001600160a01b038116811461153e57600080fd5b50565b60008083601f84011261155357600080fd5b5081356001600160401b0381111561156a57600080fd5b6020830191508360208260051b850101111561158557600080fd5b9250929050565b6000806000806000606086880312156115a457600080fd5b85356115af81611529565b945060208601356001600160401b03808211156115cb57600080fd5b6115d789838a01611541565b909650945060408801359150808211156115f057600080fd5b506115fd88828901611541565b969995985093965092949392505050565b60006020828403121561162057600080fd5b813561162b81611529565b9392505050565b60008060006060848603121561164757600080fd5b833561165281611529565b9250602084013561166281611529565b929592945050506040919091013590565b6000806040838503121561168657600080fd5b823561169181611529565b946020939093013593505050565b600080600080606085870312156116b557600080fd5b8435935060208501356116c781611529565b925060408501356001600160401b03808211156116e357600080fd5b818701915087601f8301126116f757600080fd5b81358181111561170657600080fd5b88602082850101111561171857600080fd5b95989497505060200194505050565b6000806000806080858703121561173d57600080fd5b843561174881611529565b9350602085013561175881611529565b9250604085013561176881611529565b9150606085013561177881611529565b939692955090935050565b6000808585111561179357600080fd5b838611156117a057600080fd5b5050820193919092039150565b8035602083101561148c57600019602084900360031b1b1692915050565b6020808252602a908201527f4368696c644d696e7461626c654552433732315072656469636174653a204e4f6040820152691517d0d3d395149050d560b21b606082015260800190565b60006020828403121561182757600080fd5b815161162b81611529565b6020808252602c908201527f4368696c644d696e7461626c654552433732315072656469636174653a20554e60408201526b26a0a82822a22faa27a5a2a760a11b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b038311156118ad57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b03841681526040602082018190526000906118eb9083018486611894565b95945050505050565b60006020828403121561190657600080fd5b8151801515811461162b57600080fd5b60208082526029908201527f4368696c644d696e7461626c654552433732315072656469636174653a204255604082015268149397d1905253115160ba1b606082015260800190565b8183526000602080850194508260005b8581101561199d57813561198281611529565b6001600160a01b03168752958201959082019060010161196f565b509495945050505050565b8781526001600160a01b0387811660208301528616604082015260a0606082018190526000906119db908301868861195f565b82810360808401526119ee818587611894565b9a9950505050505050505050565b6000815180845260005b81811015611a2257602081850181015186830182015201611a06565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611a66908301846119fc565b949350505050565b604081526000611a8260408301868861195f565b8281036020840152611a95818587611894565b979650505050505050565b6001600160a01b03929092168252602082015260400190565b60008060008060808587031215611acf57600080fd5b8435611ada81611529565b93506020850135611aea81611529565b92506040850135611afa81611529565b9396929550929360600135925050565b60208082526029908201527f4368696c644d696e7461626c654552433732315072656469636174653a204d49604082015268139517d1905253115160ba1b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611b9157611b91611b53565b604052919050565b60006001600160401b03821115611bb257611bb2611b53565b5060051b60200190565b600082601f830112611bcd57600080fd5b81356020611be2611bdd83611b99565b611b69565b82815260059290921b84018101918181019086841115611c0157600080fd5b8286015b84811015611c1c5780358352918301918301611c05565b509695505050505050565b600080600080600060a08688031215611c3f57600080fd5b85359450602080870135611c5281611529565b94506040870135611c6281611529565b935060608701356001600160401b0380821115611c7e57600080fd5b818901915089601f830112611c9257600080fd5b8135611ca0611bdd82611b99565b81815260059190911b8301840190848101908c831115611cbf57600080fd5b938501935b82851015611ce6578435611cd781611529565b82529385019390850190611cc4565b965050506080890135925080831115611cfe57600080fd5b5050611d0c88828901611bbc565b9150509295509295909350565b604080825283519082018190526000906020906060840190828701845b82811015611d5b5781516001600160a01b031684529284019290840190600101611d36565b5050508381038285015284518082528583019183019060005b81811015611d9057835183529284019291840191600101611d74565b5090979650505050505050565b600082601f830112611dae57600080fd5b81356001600160401b03811115611dc757611dc7611b53565b611dda601f8201601f1916602001611b69565b818152846020838601011115611def57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611e2257600080fd5b843593506020850135611e3481611529565b925060408501356001600160401b0380821115611e5057600080fd5b611e5c88838901611d9d565b93506060870135915080821115611e7257600080fd5b50611e7f87828801611d9d565b91505092959194509250565b6001600160a01b0384168152606060208201819052600090611eaf908301856119fc565b8281036040840152611ec181856119fc565b969550505050505056fea2646970667358221220c8b583610f0e8aefa292fd059d42937fb210322169349afab2ad08a7f054e61d64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var MockERC1155Artifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"MockERC1155\",\n \"sourceName\": \"contracts/mocks/MockERC1155.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bool\",\n \"name\": \"approved\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"ApprovalForAll\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Paused\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"previousAdminRole\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"newAdminRole\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"RoleAdminChanged\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RoleGranted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RoleRevoked\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"ids\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"values\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"TransferBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"TransferSingle\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"string\",\n \"name\": \"value\",\n \"type\": \"string\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"URI\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"Unpaused\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEFAULT_ADMIN_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MINTER_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"PAUSER_ROLE\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"accounts\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"ids\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"balanceOfBatch\",\n \"outputs\": [\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"\",\n \"type\": \"uint256[]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"burn\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"ids\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"values\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"burnBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"getRoleAdmin\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"index\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"getRoleMember\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"getRoleMemberCount\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"grantRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"hasRole\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"isApprovedForAll\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"mint\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"ids\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"mintBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pause\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"paused\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"renounceRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"role\",\n \"type\": \"bytes32\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"revokeRole\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"ids\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"safeBatchTransferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"safeTransferFrom\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"operator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"approved\",\n \"type\": \"bool\"\n }\n ],\n \"name\": \"setApprovalForAll\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"unpause\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"uri\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x60806040523480156200001157600080fd5b506040805180820190915260058152646c6f72656d60d81b6020820152806200003a81620000b1565b506005805460ff1916905562000052600033620000c3565b6200007e7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a633620000c3565b620000aa7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a33620000c3565b5062000376565b6004620000bf8282620002aa565b5050565b620000bf8282620000d58282620000f4565b6000828152600160205260409020620000ef908262000194565b505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff16620000bf576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620001503390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620001ab836001600160a01b038416620001b4565b90505b92915050565b6000818152600183016020526040812054620001fd57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620001ae565b506000620001ae565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200023157607f821691505b6020821081036200025257634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620000ef57600081815260208120601f850160051c81016020861015620002815750805b601f850160051c820191505b81811015620002a2578281556001016200028d565b505050505050565b81516001600160401b03811115620002c657620002c662000206565b620002de81620002d784546200021c565b8462000258565b602080601f831160018114620003165760008415620002fd5750858301515b600019600386901b1c1916600185901b178555620002a2565b600085815260208120601f198616915b82811015620003475788860151825594840194600190910190840162000326565b5085821015620003665787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6128a080620003866000396000f3fe608060405234801561001057600080fd5b50600436106101625760003560e01c8063731133e9116100ce578063ca15c87311610087578063ca15c873146102fb578063d53913931461030e578063d547741f14610323578063e63ab1e914610336578063e985e9c51461034b578063f242432a14610387578063f5298aca1461039a57600080fd5b8063731133e9146102875780638456cb591461029a5780639010d07c146102a257806391d14854146102cd578063a217fddf146102e0578063a22cb465146102e857600080fd5b80632f2ff15d116101205780632f2ff15d1461021b57806336568abe1461022e5780633f4ba83a146102415780634e1273f4146102495780635c975abb146102695780636b20c4541461027457600080fd5b8062fdd58e1461016757806301ffc9a71461018d5780630e89341c146101b05780631f7fdffa146101d0578063248a9ca3146101e55780632eb2c2d614610208575b600080fd5b61017a610175366004611bd7565b6103ad565b6040519081526020015b60405180910390f35b6101a061019b366004611c17565b610448565b6040519015158152602001610184565b6101c36101be366004611c34565b610453565b6040516101849190611c9d565b6101e36101de366004611df9565b6104e7565b005b61017a6101f3366004611c34565b60009081526020819052604090206001015490565b6101e3610216366004611e91565b61052d565b6101e3610229366004611f3a565b610579565b6101e361023c366004611f3a565b6105a3565b6101e3610621565b61025c610257366004611f66565b6106a3565b604051610184919061206b565b60055460ff166101a0565b6101e361028236600461207e565b6107cc565b6101e36102953660046120f1565b61080f565b6101e361084f565b6102b56102b0366004612145565b6108cb565b6040516001600160a01b039091168152602001610184565b6101a06102db366004611f3a565b6108ea565b61017a600081565b6101e36102f6366004612167565b610913565b61017a610309366004611c34565b61091e565b61017a60008051602061284b83398151915281565b6101e3610331366004611f3a565b610935565b61017a60008051602061282b83398151915281565b6101a06103593660046121a3565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205460ff1690565b6101e36103953660046121cd565b61095a565b6101e36103a8366004612231565b61099f565b60006001600160a01b03831661041d5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060008181526002602090815260408083206001600160a01b03861684529091529020545b92915050565b6000610442826109e2565b60606004805461046290612264565b80601f016020809104026020016040519081016040528092919081815260200182805461048e90612264565b80156104db5780601f106104b0576101008083540402835291602001916104db565b820191906000526020600020905b8154815290600101906020018083116104be57829003601f168201915b50505050509050919050565b6104ff60008051602061284b833981519152336108ea565b61051b5760405162461bcd60e51b81526004016104149061229e565b61052784848484610a22565b50505050565b6001600160a01b03851633148061054957506105498533610359565b6105655760405162461bcd60e51b8152600401610414906122e4565b6105728585858585610b6b565b5050505050565b60008281526020819052604090206001015461059481610d06565b61059e8383610d13565b505050565b6001600160a01b03811633146106135760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610414565b61061d8282610d35565b5050565b61063960008051602061282b833981519152336108ea565b6106995760405162461bcd60e51b815260206004820152603b60248201526000805160206127eb83398151915260448201527f686176652070617573657220726f6c6520746f20756e706175736500000000006064820152608401610414565b6106a1610d57565b565b606081518351146107085760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610414565b600083516001600160401b0381111561072357610723611cb0565b60405190808252806020026020018201604052801561074c578160200160208202803683370190505b50905060005b84518110156107c45761079785828151811061077057610770612332565b602002602001015185838151811061078a5761078a612332565b60200260200101516103ad565b8282815181106107a9576107a9612332565b60209081029190910101526107bd8161235e565b9050610752565b509392505050565b6001600160a01b0383163314806107e857506107e88333610359565b6108045760405162461bcd60e51b8152600401610414906122e4565b61059e838383610da9565b61082760008051602061284b833981519152336108ea565b6108435760405162461bcd60e51b81526004016104149061229e565b61052784848484610f36565b61086760008051602061282b833981519152336108ea565b6108c35760405162461bcd60e51b815260206004820152603960248201526000805160206127eb833981519152604482015278686176652070617573657220726f6c6520746f20706175736560381b6064820152608401610414565b6106a161100f565b60008281526001602052604081206108e3908361104c565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b61061d338383611058565b600081815260016020526040812061044290611138565b60008281526020819052604090206001015461095081610d06565b61059e8383610d35565b6001600160a01b03851633148061097657506109768533610359565b6109925760405162461bcd60e51b8152600401610414906122e4565b6105728585858585611142565b6001600160a01b0383163314806109bb57506109bb8333610359565b6109d75760405162461bcd60e51b8152600401610414906122e4565b61059e83838361126c565b60006001600160e01b03198216636cdb3d1360e11b1480610a1357506001600160e01b031982166303a24d0760e21b145b80610442575061044282611376565b6001600160a01b038416610a485760405162461bcd60e51b815260040161041490612377565b8151835114610a695760405162461bcd60e51b8152600401610414906123b8565b33610a798160008787878761139b565b60005b8451811015610b1557838181518110610a9757610a97612332565b602002602001015160026000878481518110610ab557610ab5612332565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000206000828254610afd9190612400565b90915550819050610b0d8161235e565b915050610a7c565b50846001600160a01b031660006001600160a01b0316826001600160a01b03166000805160206127cb8339815191528787604051610b54929190612413565b60405180910390a4610572816000878787876113a9565b8151835114610b8c5760405162461bcd60e51b8152600401610414906123b8565b6001600160a01b038416610bb25760405162461bcd60e51b815260040161041490612441565b33610bc181878787878761139b565b60005b8451811015610caa576000858281518110610be157610be1612332565b602002602001015190506000858381518110610bff57610bff612332565b60209081029190910181015160008481526002835260408082206001600160a01b038e168352909352919091205490915081811015610c505760405162461bcd60e51b815260040161041490612486565b60008381526002602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290610c8f908490612400565b9250508190555050505080610ca39061235e565b9050610bc4565b50846001600160a01b0316866001600160a01b0316826001600160a01b03166000805160206127cb8339815191528787604051610ce8929190612413565b60405180910390a4610cfe8187878787876113a9565b505050505050565b610d108133611504565b50565b610d1d828261155d565b600082815260016020526040902061059e90826115e1565b610d3f82826115f6565b600082815260016020526040902061059e908261165b565b610d5f611670565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038316610dcf5760405162461bcd60e51b8152600401610414906124d0565b8051825114610df05760405162461bcd60e51b8152600401610414906123b8565b6000339050610e138185600086866040518060200160405280600081525061139b565b60005b8351811015610edb576000848281518110610e3357610e33612332565b602002602001015190506000848381518110610e5157610e51612332565b60209081029190910181015160008481526002835260408082206001600160a01b038c168352909352919091205490915081811015610ea25760405162461bcd60e51b815260040161041490612513565b60009283526002602090815260408085206001600160a01b038b1686529091529092209103905580610ed38161235e565b915050610e16565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03166000805160206127cb8339815191528686604051610f1a929190612413565b60405180910390a4604080516020810190915260009052610527565b6001600160a01b038416610f5c5760405162461bcd60e51b815260040161041490612377565b336000610f68856116b9565b90506000610f75856116b9565b9050610f868360008985858961139b565b60008681526002602090815260408083206001600160a01b038b16845290915281208054879290610fb8908490612400565b909155505060408051878152602081018790526001600160a01b03808a16926000929187169160008051602061280b833981519152910160405180910390a461100683600089898989611704565b50505050505050565b6110176117bf565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610d8c3390565b60006108e38383611805565b816001600160a01b0316836001600160a01b0316036110cb5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610414565b6001600160a01b03838116600081815260036020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000610442825490565b6001600160a01b0384166111685760405162461bcd60e51b815260040161041490612441565b336000611174856116b9565b90506000611181856116b9565b905061119183898985858961139b565b60008681526002602090815260408083206001600160a01b038c168452909152902054858110156111d45760405162461bcd60e51b815260040161041490612486565b60008781526002602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290611213908490612400565b909155505060408051888152602081018890526001600160a01b03808b16928c8216929188169160008051602061280b833981519152910160405180910390a4611261848a8a8a8a8a611704565b505050505050505050565b6001600160a01b0383166112925760405162461bcd60e51b8152600401610414906124d0565b33600061129e846116b9565b905060006112ab846116b9565b90506112cb8387600085856040518060200160405280600081525061139b565b60008581526002602090815260408083206001600160a01b038a1684529091529020548481101561130e5760405162461bcd60e51b815260040161041490612513565b60008681526002602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a905290929088169160008051602061280b833981519152910160405180910390a4604080516020810190915260009052611006565b60006001600160e01b03198216635a05180f60e01b148061044257506104428261182f565b610cfe868686868686611864565b6001600160a01b0384163b15610cfe5760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906113ed9089908990889088908890600401612557565b6020604051808303816000875af1925050508015611428575060408051601f3d908101601f19168201909252611425918101906125b5565b60015b6114d4576114346125d2565b806308c379a00361146d57506114486125ee565b80611453575061146f565b8060405162461bcd60e51b81526004016104149190611c9d565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610414565b6001600160e01b0319811663bc197c8160e01b146110065760405162461bcd60e51b815260040161041490612677565b61150e82826108ea565b61061d5761151b816118cc565b6115268360206118de565b6040516020016115379291906126bf565b60408051601f198184030181529082905262461bcd60e51b825261041491600401611c9d565b61156782826108ea565b61061d576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561159d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006108e3836001600160a01b038416611a79565b61160082826108ea565b1561061d576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006108e3836001600160a01b038416611ac8565b60055460ff166106a15760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610414565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106116f3576116f3612332565b602090810291909101015292915050565b6001600160a01b0384163b15610cfe5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611748908990899088908890889060040161272e565b6020604051808303816000875af1925050508015611783575060408051601f3d908101601f19168201909252611780918101906125b5565b60015b61178f576114346125d2565b6001600160e01b0319811663f23a6e6160e01b146110065760405162461bcd60e51b815260040161041490612677565b60055460ff16156106a15760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610414565b600082600001828154811061181c5761181c612332565b9060005260206000200154905092915050565b60006001600160e01b03198216637965db0b60e01b148061044257506301ffc9a760e01b6001600160e01b0319831614610442565b60055460ff1615610cfe5760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201526b1dda1a5b19481c185d5cd95960a21b6064820152608401610414565b60606104426001600160a01b03831660145b606060006118ed836002612773565b6118f8906002612400565b6001600160401b0381111561190f5761190f611cb0565b6040519080825280601f01601f191660200182016040528015611939576020820181803683370190505b509050600360fc1b8160008151811061195457611954612332565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061198357611983612332565b60200101906001600160f81b031916908160001a90535060006119a7846002612773565b6119b2906001612400565b90505b6001811115611a2a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106119e6576119e6612332565b1a60f81b8282815181106119fc576119fc612332565b60200101906001600160f81b031916908160001a90535060049490941c93611a238161278a565b90506119b5565b5083156108e35760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610414565b6000818152600183016020526040812054611ac057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610442565b506000610442565b60008181526001830160205260408120548015611bb1576000611aec6001836127a1565b8554909150600090611b00906001906127a1565b9050818114611b65576000866000018281548110611b2057611b20612332565b9060005260206000200154905080876000018481548110611b4357611b43612332565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611b7657611b766127b4565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610442565b6000915050610442565b80356001600160a01b0381168114611bd257600080fd5b919050565b60008060408385031215611bea57600080fd5b611bf383611bbb565b946020939093013593505050565b6001600160e01b031981168114610d1057600080fd5b600060208284031215611c2957600080fd5b81356108e381611c01565b600060208284031215611c4657600080fd5b5035919050565b60005b83811015611c68578181015183820152602001611c50565b50506000910152565b60008151808452611c89816020860160208601611c4d565b601f01601f19169290920160200192915050565b6020815260006108e36020830184611c71565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715611ceb57611ceb611cb0565b6040525050565b60006001600160401b03821115611d0b57611d0b611cb0565b5060051b60200190565b600082601f830112611d2657600080fd5b81356020611d3382611cf2565b604051611d408282611cc6565b83815260059390931b8501820192828101915086841115611d6057600080fd5b8286015b84811015611d7b5780358352918301918301611d64565b509695505050505050565b600082601f830112611d9757600080fd5b81356001600160401b03811115611db057611db0611cb0565b604051611dc7601f8301601f191660200182611cc6565b818152846020838601011115611ddc57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611e0f57600080fd5b611e1885611bbb565b935060208501356001600160401b0380821115611e3457600080fd5b611e4088838901611d15565b94506040870135915080821115611e5657600080fd5b611e6288838901611d15565b93506060870135915080821115611e7857600080fd5b50611e8587828801611d86565b91505092959194509250565b600080600080600060a08688031215611ea957600080fd5b611eb286611bbb565b9450611ec060208701611bbb565b935060408601356001600160401b0380821115611edc57600080fd5b611ee889838a01611d15565b94506060880135915080821115611efe57600080fd5b611f0a89838a01611d15565b93506080880135915080821115611f2057600080fd5b50611f2d88828901611d86565b9150509295509295909350565b60008060408385031215611f4d57600080fd5b82359150611f5d60208401611bbb565b90509250929050565b60008060408385031215611f7957600080fd5b82356001600160401b0380821115611f9057600080fd5b818501915085601f830112611fa457600080fd5b81356020611fb182611cf2565b604051611fbe8282611cc6565b83815260059390931b8501820192828101915089841115611fde57600080fd5b948201945b8386101561200357611ff486611bbb565b82529482019490820190611fe3565b9650508601359250508082111561201957600080fd5b5061202685828601611d15565b9150509250929050565b600081518084526020808501945080840160005b8381101561206057815187529582019590820190600101612044565b509495945050505050565b6020815260006108e36020830184612030565b60008060006060848603121561209357600080fd5b61209c84611bbb565b925060208401356001600160401b03808211156120b857600080fd5b6120c487838801611d15565b935060408601359150808211156120da57600080fd5b506120e786828701611d15565b9150509250925092565b6000806000806080858703121561210757600080fd5b61211085611bbb565b9350602085013592506040850135915060608501356001600160401b0381111561213957600080fd5b611e8587828801611d86565b6000806040838503121561215857600080fd5b50508035926020909101359150565b6000806040838503121561217a57600080fd5b61218383611bbb565b91506020830135801515811461219857600080fd5b809150509250929050565b600080604083850312156121b657600080fd5b6121bf83611bbb565b9150611f5d60208401611bbb565b600080600080600060a086880312156121e557600080fd5b6121ee86611bbb565b94506121fc60208701611bbb565b9350604086013592506060860135915060808601356001600160401b0381111561222557600080fd5b611f2d88828901611d86565b60008060006060848603121561224657600080fd5b61224f84611bbb565b95602085013595506040909401359392505050565b600181811c9082168061227857607f821691505b60208210810361229857634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526038908201526000805160206127eb8339815191526040820152771a185d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60421b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161237057612370612348565b5060010190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b8082018082111561044257610442612348565b6040815260006124266040830185612030565b82810360208401526124388185612030565b95945050505050565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b60208082526023908201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526024908201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604082015263616e636560e01b606082015260800190565b6001600160a01b0386811682528516602082015260a06040820181905260009061258390830186612030565b82810360608401526125958186612030565b905082810360808401526125a98185611c71565b98975050505050505050565b6000602082840312156125c757600080fd5b81516108e381611c01565b600060033d11156125eb5760046000803e5060005160e01c5b90565b600060443d10156125fc5790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561262b57505050505090565b82850191508151818111156126435750505050505090565b843d870101602082850101111561265d5750505050505090565b61266c60208286010187611cc6565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516126f1816017850160208801611c4d565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612722816028840160208801611c4d565b01602801949350505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061276890830184611c71565b979650505050505050565b808202811582820484141761044257610442612348565b60008161279957612799612348565b506000190190565b8181038181111561044257610442612348565b634e487b7160e01b600052603160045260246000fdfe4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb455243313135355072657365744d696e7465725061757365723a206d75737420c3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6265d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a2646970667358221220294efe154e549198ff0c6b7ab7e9846223d9e8fe7ae7de1938f6eb7d0f5e66a664736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101625760003560e01c8063731133e9116100ce578063ca15c87311610087578063ca15c873146102fb578063d53913931461030e578063d547741f14610323578063e63ab1e914610336578063e985e9c51461034b578063f242432a14610387578063f5298aca1461039a57600080fd5b8063731133e9146102875780638456cb591461029a5780639010d07c146102a257806391d14854146102cd578063a217fddf146102e0578063a22cb465146102e857600080fd5b80632f2ff15d116101205780632f2ff15d1461021b57806336568abe1461022e5780633f4ba83a146102415780634e1273f4146102495780635c975abb146102695780636b20c4541461027457600080fd5b8062fdd58e1461016757806301ffc9a71461018d5780630e89341c146101b05780631f7fdffa146101d0578063248a9ca3146101e55780632eb2c2d614610208575b600080fd5b61017a610175366004611bd7565b6103ad565b6040519081526020015b60405180910390f35b6101a061019b366004611c17565b610448565b6040519015158152602001610184565b6101c36101be366004611c34565b610453565b6040516101849190611c9d565b6101e36101de366004611df9565b6104e7565b005b61017a6101f3366004611c34565b60009081526020819052604090206001015490565b6101e3610216366004611e91565b61052d565b6101e3610229366004611f3a565b610579565b6101e361023c366004611f3a565b6105a3565b6101e3610621565b61025c610257366004611f66565b6106a3565b604051610184919061206b565b60055460ff166101a0565b6101e361028236600461207e565b6107cc565b6101e36102953660046120f1565b61080f565b6101e361084f565b6102b56102b0366004612145565b6108cb565b6040516001600160a01b039091168152602001610184565b6101a06102db366004611f3a565b6108ea565b61017a600081565b6101e36102f6366004612167565b610913565b61017a610309366004611c34565b61091e565b61017a60008051602061284b83398151915281565b6101e3610331366004611f3a565b610935565b61017a60008051602061282b83398151915281565b6101a06103593660046121a3565b6001600160a01b03918216600090815260036020908152604080832093909416825291909152205460ff1690565b6101e36103953660046121cd565b61095a565b6101e36103a8366004612231565b61099f565b60006001600160a01b03831661041d5760405162461bcd60e51b815260206004820152602a60248201527f455243313135353a2061646472657373207a65726f206973206e6f742061207660448201526930b634b21037bbb732b960b11b60648201526084015b60405180910390fd5b5060008181526002602090815260408083206001600160a01b03861684529091529020545b92915050565b6000610442826109e2565b60606004805461046290612264565b80601f016020809104026020016040519081016040528092919081815260200182805461048e90612264565b80156104db5780601f106104b0576101008083540402835291602001916104db565b820191906000526020600020905b8154815290600101906020018083116104be57829003601f168201915b50505050509050919050565b6104ff60008051602061284b833981519152336108ea565b61051b5760405162461bcd60e51b81526004016104149061229e565b61052784848484610a22565b50505050565b6001600160a01b03851633148061054957506105498533610359565b6105655760405162461bcd60e51b8152600401610414906122e4565b6105728585858585610b6b565b5050505050565b60008281526020819052604090206001015461059481610d06565b61059e8383610d13565b505050565b6001600160a01b03811633146106135760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608401610414565b61061d8282610d35565b5050565b61063960008051602061282b833981519152336108ea565b6106995760405162461bcd60e51b815260206004820152603b60248201526000805160206127eb83398151915260448201527f686176652070617573657220726f6c6520746f20756e706175736500000000006064820152608401610414565b6106a1610d57565b565b606081518351146107085760405162461bcd60e51b815260206004820152602960248201527f455243313135353a206163636f756e747320616e6420696473206c656e677468604482015268040dad2e6dac2e8c6d60bb1b6064820152608401610414565b600083516001600160401b0381111561072357610723611cb0565b60405190808252806020026020018201604052801561074c578160200160208202803683370190505b50905060005b84518110156107c45761079785828151811061077057610770612332565b602002602001015185838151811061078a5761078a612332565b60200260200101516103ad565b8282815181106107a9576107a9612332565b60209081029190910101526107bd8161235e565b9050610752565b509392505050565b6001600160a01b0383163314806107e857506107e88333610359565b6108045760405162461bcd60e51b8152600401610414906122e4565b61059e838383610da9565b61082760008051602061284b833981519152336108ea565b6108435760405162461bcd60e51b81526004016104149061229e565b61052784848484610f36565b61086760008051602061282b833981519152336108ea565b6108c35760405162461bcd60e51b815260206004820152603960248201526000805160206127eb833981519152604482015278686176652070617573657220726f6c6520746f20706175736560381b6064820152608401610414565b6106a161100f565b60008281526001602052604081206108e3908361104c565b9392505050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b61061d338383611058565b600081815260016020526040812061044290611138565b60008281526020819052604090206001015461095081610d06565b61059e8383610d35565b6001600160a01b03851633148061097657506109768533610359565b6109925760405162461bcd60e51b8152600401610414906122e4565b6105728585858585611142565b6001600160a01b0383163314806109bb57506109bb8333610359565b6109d75760405162461bcd60e51b8152600401610414906122e4565b61059e83838361126c565b60006001600160e01b03198216636cdb3d1360e11b1480610a1357506001600160e01b031982166303a24d0760e21b145b80610442575061044282611376565b6001600160a01b038416610a485760405162461bcd60e51b815260040161041490612377565b8151835114610a695760405162461bcd60e51b8152600401610414906123b8565b33610a798160008787878761139b565b60005b8451811015610b1557838181518110610a9757610a97612332565b602002602001015160026000878481518110610ab557610ab5612332565b602002602001015181526020019081526020016000206000886001600160a01b03166001600160a01b031681526020019081526020016000206000828254610afd9190612400565b90915550819050610b0d8161235e565b915050610a7c565b50846001600160a01b031660006001600160a01b0316826001600160a01b03166000805160206127cb8339815191528787604051610b54929190612413565b60405180910390a4610572816000878787876113a9565b8151835114610b8c5760405162461bcd60e51b8152600401610414906123b8565b6001600160a01b038416610bb25760405162461bcd60e51b815260040161041490612441565b33610bc181878787878761139b565b60005b8451811015610caa576000858281518110610be157610be1612332565b602002602001015190506000858381518110610bff57610bff612332565b60209081029190910181015160008481526002835260408082206001600160a01b038e168352909352919091205490915081811015610c505760405162461bcd60e51b815260040161041490612486565b60008381526002602090815260408083206001600160a01b038e8116855292528083208585039055908b16825281208054849290610c8f908490612400565b9250508190555050505080610ca39061235e565b9050610bc4565b50846001600160a01b0316866001600160a01b0316826001600160a01b03166000805160206127cb8339815191528787604051610ce8929190612413565b60405180910390a4610cfe8187878787876113a9565b505050505050565b610d108133611504565b50565b610d1d828261155d565b600082815260016020526040902061059e90826115e1565b610d3f82826115f6565b600082815260016020526040902061059e908261165b565b610d5f611670565b6005805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6001600160a01b038316610dcf5760405162461bcd60e51b8152600401610414906124d0565b8051825114610df05760405162461bcd60e51b8152600401610414906123b8565b6000339050610e138185600086866040518060200160405280600081525061139b565b60005b8351811015610edb576000848281518110610e3357610e33612332565b602002602001015190506000848381518110610e5157610e51612332565b60209081029190910181015160008481526002835260408082206001600160a01b038c168352909352919091205490915081811015610ea25760405162461bcd60e51b815260040161041490612513565b60009283526002602090815260408085206001600160a01b038b1686529091529092209103905580610ed38161235e565b915050610e16565b5060006001600160a01b0316846001600160a01b0316826001600160a01b03166000805160206127cb8339815191528686604051610f1a929190612413565b60405180910390a4604080516020810190915260009052610527565b6001600160a01b038416610f5c5760405162461bcd60e51b815260040161041490612377565b336000610f68856116b9565b90506000610f75856116b9565b9050610f868360008985858961139b565b60008681526002602090815260408083206001600160a01b038b16845290915281208054879290610fb8908490612400565b909155505060408051878152602081018790526001600160a01b03808a16926000929187169160008051602061280b833981519152910160405180910390a461100683600089898989611704565b50505050505050565b6110176117bf565b6005805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610d8c3390565b60006108e38383611805565b816001600160a01b0316836001600160a01b0316036110cb5760405162461bcd60e51b815260206004820152602960248201527f455243313135353a2073657474696e6720617070726f76616c20737461747573604482015268103337b91039b2b63360b91b6064820152608401610414565b6001600160a01b03838116600081815260036020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000610442825490565b6001600160a01b0384166111685760405162461bcd60e51b815260040161041490612441565b336000611174856116b9565b90506000611181856116b9565b905061119183898985858961139b565b60008681526002602090815260408083206001600160a01b038c168452909152902054858110156111d45760405162461bcd60e51b815260040161041490612486565b60008781526002602090815260408083206001600160a01b038d8116855292528083208985039055908a16825281208054889290611213908490612400565b909155505060408051888152602081018890526001600160a01b03808b16928c8216929188169160008051602061280b833981519152910160405180910390a4611261848a8a8a8a8a611704565b505050505050505050565b6001600160a01b0383166112925760405162461bcd60e51b8152600401610414906124d0565b33600061129e846116b9565b905060006112ab846116b9565b90506112cb8387600085856040518060200160405280600081525061139b565b60008581526002602090815260408083206001600160a01b038a1684529091529020548481101561130e5760405162461bcd60e51b815260040161041490612513565b60008681526002602090815260408083206001600160a01b038b81168086529184528285208a8703905582518b81529384018a905290929088169160008051602061280b833981519152910160405180910390a4604080516020810190915260009052611006565b60006001600160e01b03198216635a05180f60e01b148061044257506104428261182f565b610cfe868686868686611864565b6001600160a01b0384163b15610cfe5760405163bc197c8160e01b81526001600160a01b0385169063bc197c81906113ed9089908990889088908890600401612557565b6020604051808303816000875af1925050508015611428575060408051601f3d908101601f19168201909252611425918101906125b5565b60015b6114d4576114346125d2565b806308c379a00361146d57506114486125ee565b80611453575061146f565b8060405162461bcd60e51b81526004016104149190611c9d565b505b60405162461bcd60e51b815260206004820152603460248201527f455243313135353a207472616e7366657220746f206e6f6e2d455243313135356044820152732932b1b2b4bb32b91034b6b83632b6b2b73a32b960611b6064820152608401610414565b6001600160e01b0319811663bc197c8160e01b146110065760405162461bcd60e51b815260040161041490612677565b61150e82826108ea565b61061d5761151b816118cc565b6115268360206118de565b6040516020016115379291906126bf565b60408051601f198184030181529082905262461bcd60e51b825261041491600401611c9d565b61156782826108ea565b61061d576000828152602081815260408083206001600160a01b03851684529091529020805460ff1916600117905561159d3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60006108e3836001600160a01b038416611a79565b61160082826108ea565b1561061d576000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60006108e3836001600160a01b038416611ac8565b60055460ff166106a15760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610414565b604080516001808252818301909252606091600091906020808301908036833701905050905082816000815181106116f3576116f3612332565b602090810291909101015292915050565b6001600160a01b0384163b15610cfe5760405163f23a6e6160e01b81526001600160a01b0385169063f23a6e6190611748908990899088908890889060040161272e565b6020604051808303816000875af1925050508015611783575060408051601f3d908101601f19168201909252611780918101906125b5565b60015b61178f576114346125d2565b6001600160e01b0319811663f23a6e6160e01b146110065760405162461bcd60e51b815260040161041490612677565b60055460ff16156106a15760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610414565b600082600001828154811061181c5761181c612332565b9060005260206000200154905092915050565b60006001600160e01b03198216637965db0b60e01b148061044257506301ffc9a760e01b6001600160e01b0319831614610442565b60055460ff1615610cfe5760405162461bcd60e51b815260206004820152602c60248201527f455243313135355061757361626c653a20746f6b656e207472616e736665722060448201526b1dda1a5b19481c185d5cd95960a21b6064820152608401610414565b60606104426001600160a01b03831660145b606060006118ed836002612773565b6118f8906002612400565b6001600160401b0381111561190f5761190f611cb0565b6040519080825280601f01601f191660200182016040528015611939576020820181803683370190505b509050600360fc1b8160008151811061195457611954612332565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061198357611983612332565b60200101906001600160f81b031916908160001a90535060006119a7846002612773565b6119b2906001612400565b90505b6001811115611a2a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106119e6576119e6612332565b1a60f81b8282815181106119fc576119fc612332565b60200101906001600160f81b031916908160001a90535060049490941c93611a238161278a565b90506119b5565b5083156108e35760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610414565b6000818152600183016020526040812054611ac057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610442565b506000610442565b60008181526001830160205260408120548015611bb1576000611aec6001836127a1565b8554909150600090611b00906001906127a1565b9050818114611b65576000866000018281548110611b2057611b20612332565b9060005260206000200154905080876000018481548110611b4357611b43612332565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611b7657611b766127b4565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610442565b6000915050610442565b80356001600160a01b0381168114611bd257600080fd5b919050565b60008060408385031215611bea57600080fd5b611bf383611bbb565b946020939093013593505050565b6001600160e01b031981168114610d1057600080fd5b600060208284031215611c2957600080fd5b81356108e381611c01565b600060208284031215611c4657600080fd5b5035919050565b60005b83811015611c68578181015183820152602001611c50565b50506000910152565b60008151808452611c89816020860160208601611c4d565b601f01601f19169290920160200192915050565b6020815260006108e36020830184611c71565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715611ceb57611ceb611cb0565b6040525050565b60006001600160401b03821115611d0b57611d0b611cb0565b5060051b60200190565b600082601f830112611d2657600080fd5b81356020611d3382611cf2565b604051611d408282611cc6565b83815260059390931b8501820192828101915086841115611d6057600080fd5b8286015b84811015611d7b5780358352918301918301611d64565b509695505050505050565b600082601f830112611d9757600080fd5b81356001600160401b03811115611db057611db0611cb0565b604051611dc7601f8301601f191660200182611cc6565b818152846020838601011115611ddc57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215611e0f57600080fd5b611e1885611bbb565b935060208501356001600160401b0380821115611e3457600080fd5b611e4088838901611d15565b94506040870135915080821115611e5657600080fd5b611e6288838901611d15565b93506060870135915080821115611e7857600080fd5b50611e8587828801611d86565b91505092959194509250565b600080600080600060a08688031215611ea957600080fd5b611eb286611bbb565b9450611ec060208701611bbb565b935060408601356001600160401b0380821115611edc57600080fd5b611ee889838a01611d15565b94506060880135915080821115611efe57600080fd5b611f0a89838a01611d15565b93506080880135915080821115611f2057600080fd5b50611f2d88828901611d86565b9150509295509295909350565b60008060408385031215611f4d57600080fd5b82359150611f5d60208401611bbb565b90509250929050565b60008060408385031215611f7957600080fd5b82356001600160401b0380821115611f9057600080fd5b818501915085601f830112611fa457600080fd5b81356020611fb182611cf2565b604051611fbe8282611cc6565b83815260059390931b8501820192828101915089841115611fde57600080fd5b948201945b8386101561200357611ff486611bbb565b82529482019490820190611fe3565b9650508601359250508082111561201957600080fd5b5061202685828601611d15565b9150509250929050565b600081518084526020808501945080840160005b8381101561206057815187529582019590820190600101612044565b509495945050505050565b6020815260006108e36020830184612030565b60008060006060848603121561209357600080fd5b61209c84611bbb565b925060208401356001600160401b03808211156120b857600080fd5b6120c487838801611d15565b935060408601359150808211156120da57600080fd5b506120e786828701611d15565b9150509250925092565b6000806000806080858703121561210757600080fd5b61211085611bbb565b9350602085013592506040850135915060608501356001600160401b0381111561213957600080fd5b611e8587828801611d86565b6000806040838503121561215857600080fd5b50508035926020909101359150565b6000806040838503121561217a57600080fd5b61218383611bbb565b91506020830135801515811461219857600080fd5b809150509250929050565b600080604083850312156121b657600080fd5b6121bf83611bbb565b9150611f5d60208401611bbb565b600080600080600060a086880312156121e557600080fd5b6121ee86611bbb565b94506121fc60208701611bbb565b9350604086013592506060860135915060808601356001600160401b0381111561222557600080fd5b611f2d88828901611d86565b60008060006060848603121561224657600080fd5b61224f84611bbb565b95602085013595506040909401359392505050565b600181811c9082168061227857607f821691505b60208210810361229857634e487b7160e01b600052602260045260246000fd5b50919050565b60208082526038908201526000805160206127eb8339815191526040820152771a185d99481b5a5b9d195c881c9bdb19481d1bc81b5a5b9d60421b606082015260800190565b6020808252602e908201527f455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e60408201526d195c881bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161237057612370612348565b5060010190565b60208082526021908201527f455243313135353a206d696e7420746f20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526028908201527f455243313135353a2069647320616e6420616d6f756e7473206c656e677468206040820152670dad2e6dac2e8c6d60c31b606082015260800190565b8082018082111561044257610442612348565b6040815260006124266040830185612030565b82810360208401526124388185612030565b95945050505050565b60208082526025908201527f455243313135353a207472616e7366657220746f20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252602a908201527f455243313135353a20696e73756666696369656e742062616c616e636520666f60408201526939103a3930b739b332b960b11b606082015260800190565b60208082526023908201527f455243313135353a206275726e2066726f6d20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526024908201527f455243313135353a206275726e20616d6f756e7420657863656564732062616c604082015263616e636560e01b606082015260800190565b6001600160a01b0386811682528516602082015260a06040820181905260009061258390830186612030565b82810360608401526125958186612030565b905082810360808401526125a98185611c71565b98975050505050505050565b6000602082840312156125c757600080fd5b81516108e381611c01565b600060033d11156125eb5760046000803e5060005160e01c5b90565b600060443d10156125fc5790565b6040516003193d81016004833e81513d6001600160401b03816024840111818411171561262b57505050505090565b82850191508151818111156126435750505050505090565b843d870101602082850101111561265d5750505050505090565b61266c60208286010187611cc6565b509095945050505050565b60208082526028908201527f455243313135353a204552433131353552656365697665722072656a656374656040820152676420746f6b656e7360c01b606082015260800190565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b8152600083516126f1816017850160208801611c4d565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612722816028840160208801611c4d565b01602801949350505050565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061276890830184611c71565b979650505050505050565b808202811582820484141761044257610442612348565b60008161279957612799612348565b506000190190565b8181038181111561044257610442612348565b634e487b7160e01b600052603160045260246000fdfe4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb455243313135355072657365744d696e7465725061757365723a206d75737420c3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6265d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6a2646970667358221220294efe154e549198ff0c6b7ab7e9846223d9e8fe7ae7de1938f6eb7d0f5e66a664736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RootERC1155PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RootERC1155Predicate\",\n \"sourceName\": \"contracts/root/RootERC1155Predicate.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ERC1155Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"depositor\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"ERC1155DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ERC1155Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"withdrawer\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"ERC1155WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"TokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC1155Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"deposit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"depositBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"depositTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"exitHelper\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newExitHelper\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildERC1155Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IERC1155MetadataURI\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"mapToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC1155BatchReceived\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onERC1155Received\",\n \"outputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"\",\n \"type\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onL2StateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"bytes4\",\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\"\n }\n ],\n \"name\": \"supportsInterface\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611bd2806100206000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063bc197c81116100ad578063f23a6e6111610071578063f23a6e61146102fe578063f43cda8b1461031d578063f4a120f714610330578063f645125514610343578063f8c8765e1461036a57600080fd5b8063bc197c8114610238578063c5ac2b1c14610270578063cb10f94c14610297578063d41f1771146102b0578063d7c9e3ec146102d757600080fd5b80637efab4f5116100f45780637efab4f5146101a157806395c7041c146101ca578063a78e111c146101dd578063b1768065146101f0578063b68ad1e41461022557600080fd5b806301ffc9a7146101265780630efe6a8b1461014e5780634c4c45de14610163578063654715e614610176575b600080fd5b610139610134366004611173565b61037d565b60405190151581526020015b60405180910390f35b61016161015c3660046111bc565b6103b4565b005b61016161017136600461123c565b6103c5565b600254610189906001600160a01b031681565b6040516001600160a01b039091168152602001610145565b6101896101af3660046112e8565b6004602052600090815260409020546001600160a01b031681565b600154610189906001600160a01b031681565b6101616101eb366004611305565b610448565b6102177f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610145565b600354610189906001600160a01b031681565b610257610246366004611497565b63bc197c8160e01b95945050505050565b6040516001600160e01b03199091168152602001610145565b6102177faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b600054610189906201000090046001600160a01b031681565b6102177f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102177f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61025761030c366004611544565b63f23a6e6160e01b95945050505050565b61016161032b3660046115ac565b61045a565b61018961033e3660046112e8565b610629565b6102177f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b610161610378366004611634565b610945565b60006001600160e01b03198216630271189760e51b14806103ae57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6103c083338484610b54565b505050565b84831480156103d357508481145b6104305760405162461bcd60e51b8152602060048201526024808201527f526f6f74455243313135355072656469636174653a20494e56414c49445f4c4560448201526309c8ea8960e31b60648201526084015b60405180910390fd5b61043f87878787878787610cec565b50505050505050565b61045484848484610b54565b50505050565b6001546001600160a01b031633146104c35760405162461bcd60e51b815260206004820152602660248201527f526f6f74455243313135355072656469636174653a204f4e4c595f455849545f6044820152652422a62822a960d11b6064820152608401610427565b6002546001600160a01b038481169116146105335760405162461bcd60e51b815260206004820152602a60248201527f526f6f74455243313135355072656469636174653a204f4e4c595f4348494c446044820152695f50524544494341544560b01b6064820152608401610427565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e982869610562602060008486611690565b61056b916116ba565b0361058a576105856105808260208186611690565b610ecc565b610454565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed26105b9602060008486611690565b6105c2916116ba565b036105d1576105858282610fcb565b60405162461bcd60e51b815260206004820152602760248201527f526f6f74455243313135355072656469636174653a20494e56414c49445f5349604482015266474e415455524560c81b6064820152608401610427565b60006001600160a01b03821661068d5760405162461bcd60e51b815260206004820152602360248201527f526f6f74455243313135355072656469636174653a20494e56414c49445f544f60448201526225a2a760e91b6064820152608401610427565b6001600160a01b0382811660009081526004602052604090205416156107015760405162461bcd60e51b8152602060048201526024808201527f526f6f74455243313135355072656469636174653a20414c52454144595f4d416044820152631414115160e21b6064820152608401610427565b6002546003546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b03928316926107ab921690603401604051602081830303815290604052805190602001208360405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b03848116600081815260046020818152604080842080546001600160a01b031916968816969096179095558451908101855282815293516303a24d0760e21b8152908101919091529294509091630e89341c90602401600060405180830381865afa92505050801561084657506040513d6000823e601f3d908101601f1916820160405261084391908101906116fc565b60015b1561084e5790505b600060029054906101000a90046001600160a01b03166001600160a01b03166316f19831837f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad87856040516020016108a89392919061179e565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016108d49291906117c8565b600060405180830381600087803b1580156108ee57600080fd5b505af1158015610902573d6000803e3d6000fd5b50506040516001600160a01b038087169350871691507f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61790600090a35050919050565b600054610100900460ff16158080156109655750600054600160ff909116105b8061097f5750303b15801561097f575060005460ff166001145b6109e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610427565b6000805460ff191660011790558015610a05576000805461ff0019166101001790555b6001600160a01b03851615801590610a2557506001600160a01b03841615155b8015610a3957506001600160a01b03831615155b8015610a4d57506001600160a01b03821615155b610aaa5760405162461bcd60e51b815260206004820152602860248201527f526f6f74455243313135355072656469636174653a204241445f494e495449416044820152672624ad20aa24a7a760c11b6064820152608401610427565b6000805462010000600160b01b031916620100006001600160a01b038881169190910291909117909155600180546001600160a01b031990811687841617909155600280548216868416179055600380549091169184169190911790558015610b4d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6000610b5f8561112c565b604051637921219560e11b81529091506001600160a01b0386169063f242432a90610b949033903090889088906004016117f4565b600060405180830381600087803b158015610bae57600080fd5b505af1158015610bc2573d6000803e3d6000fd5b5050600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038b8116828401523360608301528a8116608083015260a082018a905260c08083018a90528351808403909101815260e08301938490526316f1983160e01b90935262010000909404841695506316f198319450610c5f939092169160e4016117c8565b600060405180830381600087803b158015610c7957600080fd5b505af1158015610c8d573d6000803e3d6000fd5b505060408051338152602081018790529081018590526001600160a01b03808816935084811692508816907fbcbdf0c69f975f2a4085544938b054f02e77e87cbd055146d388c0be7120e04f9060600160405180910390a45050505050565b6000610cf78861112c565b905060005b84811015610da357886001600160a01b031663f242432a3330898986818110610d2757610d2761182c565b90506020020135888887818110610d4057610d4061182c565b905060200201356040518563ffffffff1660e01b8152600401610d6694939291906117f4565b600060405180830381600087803b158015610d8057600080fd5b505af1158015610d94573d6000803e3d6000fd5b50505050806001019050610cfc565b506000546002546040516001600160a01b03620100009093048316926316f19831921690610e05907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908d9033908e908e908e908e908e908e906020016118bd565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610e319291906117c8565b600060405180830381600087803b158015610e4b57600080fd5b505af1158015610e5f573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316896001600160a01b03167f7e8ab6f25cb177d65db49b7a2197bb2a7df5757434857d411e2523b332a913e68a8a8a8a8a8a604051610eba96959493929190611928565b60405180910390a45050505050505050565b600080808080610ede86880188611971565b6001600160a01b03808616600090815260046020526040902054959a50939850919650945092501680610f1357610f136119cc565b604051637921219560e11b81526001600160a01b0387169063f242432a90610f459030908890889088906004016117f4565b600060405180830381600087803b158015610f5f57600080fd5b505af1158015610f73573d6000803e3d6000fd5b5050604080516001600160a01b0389811682526020820188905291810186905281881693508482169250908916907fc42752949ca07109e6f25adcde4a9407be23e084b1d32ca2bce8aa55bf3dd62590606001610eba565b600080808080610fdd868801886119e2565b6001600160a01b03808616600090815260046020526040902054959b509399509197509550935016905080611014576110146119cc565b60005b83518110156110da57866001600160a01b031663f242432a308784815181106110425761104261182c565b602002602001015187858151811061105c5761105c61182c565b60200260200101518786815181106110765761107661182c565b60200260200101516040518563ffffffff1660e01b815260040161109d94939291906117f4565b600060405180830381600087803b1580156110b757600080fd5b505af11580156110cb573d6000803e3d6000fd5b50505050806001019050611017565b50846001600160a01b0316816001600160a01b0316876001600160a01b03167fce612e98b81c726375e7c2395409e74ee0a29b22f7641ea5a8ce8508616448c0878787604051610eba93929190611b27565b6001600160a01b0380821660009081526004602052604090205416806111585761115582610629565b90505b6001600160a01b03811661116e5761116e6119cc565b919050565b60006020828403121561118557600080fd5b81356001600160e01b03198116811461119d57600080fd5b9392505050565b6001600160a01b03811681146111b957600080fd5b50565b6000806000606084860312156111d157600080fd5b83356111dc816111a4565b95602085013595506040909401359392505050565b60008083601f84011261120357600080fd5b5081356001600160401b0381111561121a57600080fd5b6020830191508360208260051b850101111561123557600080fd5b9250929050565b60008060008060008060006080888a03121561125757600080fd5b8735611262816111a4565b965060208801356001600160401b038082111561127e57600080fd5b61128a8b838c016111f1565b909850965060408a01359150808211156112a357600080fd5b6112af8b838c016111f1565b909650945060608a01359150808211156112c857600080fd5b506112d58a828b016111f1565b989b979a50959850939692959293505050565b6000602082840312156112fa57600080fd5b813561119d816111a4565b6000806000806080858703121561131b57600080fd5b8435611326816111a4565b93506020850135611336816111a4565b93969395505050506040820135916060013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156113895761138961134b565b604052919050565b60006001600160401b038211156113aa576113aa61134b565b5060051b60200190565b600082601f8301126113c557600080fd5b813560206113da6113d583611391565b611361565b82815260059290921b840181019181810190868411156113f957600080fd5b8286015b8481101561141457803583529183019183016113fd565b509695505050505050565b60006001600160401b038211156114385761143861134b565b50601f01601f191660200190565b600082601f83011261145757600080fd5b81356114656113d58261141f565b81815284602083860101111561147a57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156114af57600080fd5b85356114ba816111a4565b945060208601356114ca816111a4565b935060408601356001600160401b03808211156114e657600080fd5b6114f289838a016113b4565b9450606088013591508082111561150857600080fd5b61151489838a016113b4565b9350608088013591508082111561152a57600080fd5b5061153788828901611446565b9150509295509295909350565b600080600080600060a0868803121561155c57600080fd5b8535611567816111a4565b94506020860135611577816111a4565b9350604086013592506060860135915060808601356001600160401b038111156115a057600080fd5b61153788828901611446565b600080600080606085870312156115c257600080fd5b8435935060208501356115d4816111a4565b925060408501356001600160401b03808211156115f057600080fd5b818701915087601f83011261160457600080fd5b81358181111561161357600080fd5b88602082850101111561162557600080fd5b95989497505060200194505050565b6000806000806080858703121561164a57600080fd5b8435611655816111a4565b93506020850135611665816111a4565b92506040850135611675816111a4565b91506060850135611685816111a4565b939692955090935050565b600080858511156116a057600080fd5b838611156116ad57600080fd5b5050820193919092039150565b803560208310156103ae57600019602084900360031b1b1692915050565b60005b838110156116f35781810151838201526020016116db565b50506000910152565b60006020828403121561170e57600080fd5b81516001600160401b0381111561172457600080fd5b8201601f8101841361173557600080fd5b80516117436113d58261141f565b81815285602083850101111561175857600080fd5b6117698260208301602086016116d8565b95945050505050565b6000815180845261178a8160208601602086016116d8565b601f01601f19169290920160200192915050565b8381526001600160a01b038316602082015260606040820181905260009061176990830184611772565b6001600160a01b03831681526040602082018190526000906117ec90830184611772565b949350505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052603260045260246000fd5b8183526000602080850194508260005b85811015611880578135611865816111a4565b6001600160a01b031687529582019590820190600101611852565b509495945050505050565b81835260006001600160fb1b038311156118a457600080fd5b8260051b80836020870137939093016020019392505050565b8981526001600160a01b0389811660208301528816604082015260c0606082018190526000906118f0908301888a611842565b828103608084015261190381878961188b565b905082810360a084015261191881858761188b565b9c9b505050505050505050505050565b60608152600061193c60608301888a611842565b828103602084015261194f81878961188b565b9050828103604084015261196481858761188b565b9998505050505050505050565b600080600080600060a0868803121561198957600080fd5b8535611994816111a4565b945060208601356119a4816111a4565b935060408601356119b4816111a4565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052600160045260246000fd5b60008060008060008060c087890312156119fb57600080fd5b86359550602080880135611a0e816111a4565b95506040880135611a1e816111a4565b945060608801356001600160401b0380821115611a3a57600080fd5b818a0191508a601f830112611a4e57600080fd5b8135611a5c6113d582611391565b81815260059190911b8301840190848101908d831115611a7b57600080fd5b938501935b82851015611aa2578435611a93816111a4565b82529385019390850190611a80565b9750505060808a0135925080831115611aba57600080fd5b611ac68b848c016113b4565b945060a08a0135925080831115611adc57600080fd5b5050611aea89828a016113b4565b9150509295509295509295565b600081518084526020808501945080840160005b8381101561188057815187529582019590820190600101611b0b565b606080825284519082018190526000906020906080840190828801845b82811015611b695781516001600160a01b031684529284019290840190600101611b44565b50505083810382850152611b7d8187611af7565b9150508281036040840152611b928185611af7565b969550505050505056fea264697066735822122005fb54218b08fc0f9fa24d9c92ec93ef996fd7628635e6083aa645b236dbb08864736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063bc197c81116100ad578063f23a6e6111610071578063f23a6e61146102fe578063f43cda8b1461031d578063f4a120f714610330578063f645125514610343578063f8c8765e1461036a57600080fd5b8063bc197c8114610238578063c5ac2b1c14610270578063cb10f94c14610297578063d41f1771146102b0578063d7c9e3ec146102d757600080fd5b80637efab4f5116100f45780637efab4f5146101a157806395c7041c146101ca578063a78e111c146101dd578063b1768065146101f0578063b68ad1e41461022557600080fd5b806301ffc9a7146101265780630efe6a8b1461014e5780634c4c45de14610163578063654715e614610176575b600080fd5b610139610134366004611173565b61037d565b60405190151581526020015b60405180910390f35b61016161015c3660046111bc565b6103b4565b005b61016161017136600461123c565b6103c5565b600254610189906001600160a01b031681565b6040516001600160a01b039091168152602001610145565b6101896101af3660046112e8565b6004602052600090815260409020546001600160a01b031681565b600154610189906001600160a01b031681565b6101616101eb366004611305565b610448565b6102177f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610145565b600354610189906001600160a01b031681565b610257610246366004611497565b63bc197c8160e01b95945050505050565b6040516001600160e01b03199091168152602001610145565b6102177faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b600054610189906201000090046001600160a01b031681565b6102177f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6102177f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b61025761030c366004611544565b63f23a6e6160e01b95945050505050565b61016161032b3660046115ac565b61045a565b61018961033e3660046112e8565b610629565b6102177f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b610161610378366004611634565b610945565b60006001600160e01b03198216630271189760e51b14806103ae57506301ffc9a760e01b6001600160e01b03198316145b92915050565b6103c083338484610b54565b505050565b84831480156103d357508481145b6104305760405162461bcd60e51b8152602060048201526024808201527f526f6f74455243313135355072656469636174653a20494e56414c49445f4c4560448201526309c8ea8960e31b60648201526084015b60405180910390fd5b61043f87878787878787610cec565b50505050505050565b61045484848484610b54565b50505050565b6001546001600160a01b031633146104c35760405162461bcd60e51b815260206004820152602660248201527f526f6f74455243313135355072656469636174653a204f4e4c595f455849545f6044820152652422a62822a960d11b6064820152608401610427565b6002546001600160a01b038481169116146105335760405162461bcd60e51b815260206004820152602a60248201527f526f6f74455243313135355072656469636174653a204f4e4c595f4348494c446044820152695f50524544494341544560b01b6064820152608401610427565b7f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e982869610562602060008486611690565b61056b916116ba565b0361058a576105856105808260208186611690565b610ecc565b610454565b7f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed26105b9602060008486611690565b6105c2916116ba565b036105d1576105858282610fcb565b60405162461bcd60e51b815260206004820152602760248201527f526f6f74455243313135355072656469636174653a20494e56414c49445f5349604482015266474e415455524560c81b6064820152608401610427565b60006001600160a01b03821661068d5760405162461bcd60e51b815260206004820152602360248201527f526f6f74455243313135355072656469636174653a20494e56414c49445f544f60448201526225a2a760e91b6064820152608401610427565b6001600160a01b0382811660009081526004602052604090205416156107015760405162461bcd60e51b8152602060048201526024808201527f526f6f74455243313135355072656469636174653a20414c52454144595f4d416044820152631414115160e21b6064820152608401610427565b6002546003546040516bffffffffffffffffffffffff19606086901b1660208201526001600160a01b03928316926107ab921690603401604051602081830303815290604052805190602001208360405160388101919091526f5af43d82803e903d91602b57fd5bf3ff60248201526014810192909252733d602d80600a3d3981f3363d3d373d3d3d363d73825260588201526037600c8201206078820152605560439091012090565b6001600160a01b03848116600081815260046020818152604080842080546001600160a01b031916968816969096179095558451908101855282815293516303a24d0760e21b8152908101919091529294509091630e89341c90602401600060405180830381865afa92505050801561084657506040513d6000823e601f3d908101601f1916820160405261084391908101906116fc565b60015b1561084e5790505b600060029054906101000a90046001600160a01b03166001600160a01b03166316f19831837f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad87856040516020016108a89392919061179e565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016108d49291906117c8565b600060405180830381600087803b1580156108ee57600080fd5b505af1158015610902573d6000803e3d6000fd5b50506040516001600160a01b038087169350871691507f85920d35e6c72f6b2affffa04298b0cecfeba86e4a9f407df661f1cb8ab5e61790600090a35050919050565b600054610100900460ff16158080156109655750600054600160ff909116105b8061097f5750303b15801561097f575060005460ff166001145b6109e25760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610427565b6000805460ff191660011790558015610a05576000805461ff0019166101001790555b6001600160a01b03851615801590610a2557506001600160a01b03841615155b8015610a3957506001600160a01b03831615155b8015610a4d57506001600160a01b03821615155b610aaa5760405162461bcd60e51b815260206004820152602860248201527f526f6f74455243313135355072656469636174653a204241445f494e495449416044820152672624ad20aa24a7a760c11b6064820152608401610427565b6000805462010000600160b01b031916620100006001600160a01b038881169190910291909117909155600180546001600160a01b031990811687841617909155600280548216868416179055600380549091169184169190911790558015610b4d576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6000610b5f8561112c565b604051637921219560e11b81529091506001600160a01b0386169063f242432a90610b949033903090889088906004016117f4565b600060405180830381600087803b158015610bae57600080fd5b505af1158015610bc2573d6000803e3d6000fd5b5050600054600254604080517f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82160208201526001600160a01b038b8116828401523360608301528a8116608083015260a082018a905260c08083018a90528351808403909101815260e08301938490526316f1983160e01b90935262010000909404841695506316f198319450610c5f939092169160e4016117c8565b600060405180830381600087803b158015610c7957600080fd5b505af1158015610c8d573d6000803e3d6000fd5b505060408051338152602081018790529081018590526001600160a01b03808816935084811692508816907fbcbdf0c69f975f2a4085544938b054f02e77e87cbd055146d388c0be7120e04f9060600160405180910390a45050505050565b6000610cf78861112c565b905060005b84811015610da357886001600160a01b031663f242432a3330898986818110610d2757610d2761182c565b90506020020135888887818110610d4057610d4061182c565b905060200201356040518563ffffffff1660e01b8152600401610d6694939291906117f4565b600060405180830381600087803b158015610d8057600080fd5b505af1158015610d94573d6000803e3d6000fd5b50505050806001019050610cfc565b506000546002546040516001600160a01b03620100009093048316926316f19831921690610e05907faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d18908d9033908e908e908e908e908e908e906020016118bd565b6040516020818303038152906040526040518363ffffffff1660e01b8152600401610e319291906117c8565b600060405180830381600087803b158015610e4b57600080fd5b505af1158015610e5f573d6000803e3d6000fd5b50505050336001600160a01b0316816001600160a01b0316896001600160a01b03167f7e8ab6f25cb177d65db49b7a2197bb2a7df5757434857d411e2523b332a913e68a8a8a8a8a8a604051610eba96959493929190611928565b60405180910390a45050505050505050565b600080808080610ede86880188611971565b6001600160a01b03808616600090815260046020526040902054959a50939850919650945092501680610f1357610f136119cc565b604051637921219560e11b81526001600160a01b0387169063f242432a90610f459030908890889088906004016117f4565b600060405180830381600087803b158015610f5f57600080fd5b505af1158015610f73573d6000803e3d6000fd5b5050604080516001600160a01b0389811682526020820188905291810186905281881693508482169250908916907fc42752949ca07109e6f25adcde4a9407be23e084b1d32ca2bce8aa55bf3dd62590606001610eba565b600080808080610fdd868801886119e2565b6001600160a01b03808616600090815260046020526040902054959b509399509197509550935016905080611014576110146119cc565b60005b83518110156110da57866001600160a01b031663f242432a308784815181106110425761104261182c565b602002602001015187858151811061105c5761105c61182c565b60200260200101518786815181106110765761107661182c565b60200260200101516040518563ffffffff1660e01b815260040161109d94939291906117f4565b600060405180830381600087803b1580156110b757600080fd5b505af11580156110cb573d6000803e3d6000fd5b50505050806001019050611017565b50846001600160a01b0316816001600160a01b0316876001600160a01b03167fce612e98b81c726375e7c2395409e74ee0a29b22f7641ea5a8ce8508616448c0878787604051610eba93929190611b27565b6001600160a01b0380821660009081526004602052604090205416806111585761115582610629565b90505b6001600160a01b03811661116e5761116e6119cc565b919050565b60006020828403121561118557600080fd5b81356001600160e01b03198116811461119d57600080fd5b9392505050565b6001600160a01b03811681146111b957600080fd5b50565b6000806000606084860312156111d157600080fd5b83356111dc816111a4565b95602085013595506040909401359392505050565b60008083601f84011261120357600080fd5b5081356001600160401b0381111561121a57600080fd5b6020830191508360208260051b850101111561123557600080fd5b9250929050565b60008060008060008060006080888a03121561125757600080fd5b8735611262816111a4565b965060208801356001600160401b038082111561127e57600080fd5b61128a8b838c016111f1565b909850965060408a01359150808211156112a357600080fd5b6112af8b838c016111f1565b909650945060608a01359150808211156112c857600080fd5b506112d58a828b016111f1565b989b979a50959850939692959293505050565b6000602082840312156112fa57600080fd5b813561119d816111a4565b6000806000806080858703121561131b57600080fd5b8435611326816111a4565b93506020850135611336816111a4565b93969395505050506040820135916060013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156113895761138961134b565b604052919050565b60006001600160401b038211156113aa576113aa61134b565b5060051b60200190565b600082601f8301126113c557600080fd5b813560206113da6113d583611391565b611361565b82815260059290921b840181019181810190868411156113f957600080fd5b8286015b8481101561141457803583529183019183016113fd565b509695505050505050565b60006001600160401b038211156114385761143861134b565b50601f01601f191660200190565b600082601f83011261145757600080fd5b81356114656113d58261141f565b81815284602083860101111561147a57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156114af57600080fd5b85356114ba816111a4565b945060208601356114ca816111a4565b935060408601356001600160401b03808211156114e657600080fd5b6114f289838a016113b4565b9450606088013591508082111561150857600080fd5b61151489838a016113b4565b9350608088013591508082111561152a57600080fd5b5061153788828901611446565b9150509295509295909350565b600080600080600060a0868803121561155c57600080fd5b8535611567816111a4565b94506020860135611577816111a4565b9350604086013592506060860135915060808601356001600160401b038111156115a057600080fd5b61153788828901611446565b600080600080606085870312156115c257600080fd5b8435935060208501356115d4816111a4565b925060408501356001600160401b03808211156115f057600080fd5b818701915087601f83011261160457600080fd5b81358181111561161357600080fd5b88602082850101111561162557600080fd5b95989497505060200194505050565b6000806000806080858703121561164a57600080fd5b8435611655816111a4565b93506020850135611665816111a4565b92506040850135611675816111a4565b91506060850135611685816111a4565b939692955090935050565b600080858511156116a057600080fd5b838611156116ad57600080fd5b5050820193919092039150565b803560208310156103ae57600019602084900360031b1b1692915050565b60005b838110156116f35781810151838201526020016116db565b50506000910152565b60006020828403121561170e57600080fd5b81516001600160401b0381111561172457600080fd5b8201601f8101841361173557600080fd5b80516117436113d58261141f565b81815285602083850101111561175857600080fd5b6117698260208301602086016116d8565b95945050505050565b6000815180845261178a8160208601602086016116d8565b601f01601f19169290920160200192915050565b8381526001600160a01b038316602082015260606040820181905260009061176990830184611772565b6001600160a01b03831681526040602082018190526000906117ec90830184611772565b949350505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260a06080820181905260009082015260c00190565b634e487b7160e01b600052603260045260246000fd5b8183526000602080850194508260005b85811015611880578135611865816111a4565b6001600160a01b031687529582019590820190600101611852565b509495945050505050565b81835260006001600160fb1b038311156118a457600080fd5b8260051b80836020870137939093016020019392505050565b8981526001600160a01b0389811660208301528816604082015260c0606082018190526000906118f0908301888a611842565b828103608084015261190381878961188b565b905082810360a084015261191881858761188b565b9c9b505050505050505050505050565b60608152600061193c60608301888a611842565b828103602084015261194f81878961188b565b9050828103604084015261196481858761188b565b9998505050505050505050565b600080600080600060a0868803121561198957600080fd5b8535611994816111a4565b945060208601356119a4816111a4565b935060408601356119b4816111a4565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052600160045260246000fd5b60008060008060008060c087890312156119fb57600080fd5b86359550602080880135611a0e816111a4565b95506040880135611a1e816111a4565b945060608801356001600160401b0380821115611a3a57600080fd5b818a0191508a601f830112611a4e57600080fd5b8135611a5c6113d582611391565b81815260059190911b8301840190848101908d831115611a7b57600080fd5b938501935b82851015611aa2578435611a93816111a4565b82529385019390850190611a80565b9750505060808a0135925080831115611aba57600080fd5b611ac68b848c016113b4565b945060a08a0135925080831115611adc57600080fd5b5050611aea89828a016113b4565b9150509295509295509295565b600081518084526020808501945080840160005b8381101561188057815187529582019590820190600101611b0b565b606080825284519082018190526000906020906080840190828801845b82811015611b695781516001600160a01b031684529284019290840190600101611b44565b50505083810382850152611b7d8187611af7565b9150508281036040840152611b928185611af7565b969550505050505056fea264697066735822122005fb54218b08fc0f9fa24d9c92ec93ef996fd7628635e6083aa645b236dbb08864736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ChildMintableERC1155PredicateArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ChildMintableERC1155Predicate\",\n \"sourceName\": \"contracts/root/ChildMintableERC1155Predicate.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"MintableERC1155Deposit\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"MintableERC1155DepositBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"MintableERC1155Withdraw\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"MintableERC1155WithdrawBatch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"rootToken\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"MintableTokenMapped\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"DEPOSIT_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"MAP_TOKEN_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_BATCH_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAW_SIG\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childTokenTemplate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"exitHelper\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newExitHelper\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootERC1155Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildTokenTemplate\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onL2StateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rootERC1155Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"rootTokenToChildToken\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"stateSender\",\n \"outputs\": [\n {\n \"internalType\": \"contract IStateSender\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address[]\",\n \"name\": \"receivers\",\n \"type\": \"address[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"tokenIds\",\n \"type\": \"uint256[]\"\n },\n {\n \"internalType\": \"uint256[]\",\n \"name\": \"amounts\",\n \"type\": \"uint256[]\"\n }\n ],\n \"name\": \"withdrawBatch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC1155\",\n \"name\": \"childToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"receiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"tokenId\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawTo\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50611f7c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100d55760003560e01c8063b8cd3ec011610087578063b8cd3ec0146101b6578063c5ac2b1c146101c9578063cb10f94c146101f0578063d41f177114610209578063d7c9e3ec14610230578063f43cda8b14610257578063f64512551461026a578063f8c8765e1461029157600080fd5b8063051eb2e2146100da5780637efab4f51461010a57806386937eb41461013357806395c7041c14610148578063b17680651461015b578063b5c5f67214610190578063b68ad1e4146101a3575b600080fd5b6002546100ed906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ed610118366004611564565b6004602052600090815260409020546001600160a01b031681565b6101466101413660046115d3565b6102a4565b005b6001546100ed906001600160a01b031681565b6101827f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610101565b61014661019e36600461167f565b6102bc565b6003546100ed906001600160a01b031681565b6101466101c43660046116b4565b6102cd565b6101827faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6000546100ed906201000090046001600160a01b031681565b6101827f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101827f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b6101466102653660046116fa565b6102df565b6101827f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61014661029f366004611782565b610514565b6102b38787878787878761062d565b50505050505050565b6102c8833384846109ba565b505050565b6102d9848484846109ba565b50505050565b6001546001600160a01b031633146103565760405162461bcd60e51b815260206004820152602f60248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204f60448201526e27262cafa2ac24aa2fa422a62822a960891b60648201526084015b60405180910390fd5b6002546001600160a01b038481169116146103ce5760405162461bcd60e51b815260206004820152603260248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204f6044820152714e4c595f524f4f545f50524544494341544560701b606482015260840161034d565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216103fd6020600084866117de565b61040691611808565b036104255761042061041b82602081866117de565b610cd5565b6102d9565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d186104546020600084866117de565b61045d91611808565b0361046c576104208282610f40565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad61049b6020600084866117de565b6104a491611808565b036104b35761042082826111ad565b60405162461bcd60e51b815260206004820152603060248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204960448201526f4e56414c49445f5349474e415455524560801b606482015260840161034d565b600054610100900460ff16158080156105345750600054600160ff909116105b8061054e5750303b15801561054e575060005460ff166001145b6105b15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161034d565b6000805460ff1916600117905580156105d4576000805461ff0019166101001790555b6105e085858585611317565b8015610626576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b8661063781611420565b6106535760405162461bcd60e51b815260040161034d90611826565b6000886001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610693573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b79190611871565b6001600160a01b038181166000908152600460205260409020549192508a81169116146106f65760405162461bcd60e51b815260040161034d9061188e565b6001600160a01b03811661070c5761070c6118db565b306001600160a01b0316896001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610754573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107789190611871565b6001600160a01b03161461078e5761078e6118db565b868514801561079c57508483145b6107fe5760405162461bcd60e51b815260206004820152602d60248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204960448201526c09cac82989288be988a9c8ea89609b1b606482015260840161034d565b604051631ac8311560e21b81526001600160a01b038a1690636b20c454906108329033908a908a908a908a90600401611923565b6020604051808303816000875af1158015610851573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108759190611967565b6108915760405162461bcd60e51b815260040161034d90611989565b6000546002546040516001600160a01b03620100009093048316926316f198319216906108f2907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908f908f908f908f908f908f90602001611a1c565b6040516020818303038152906040526040518363ffffffff1660e01b815260040161091e929190611acd565b600060405180830381600087803b15801561093857600080fd5b505af115801561094c573d6000803e3d6000fd5b50505050336001600160a01b0316896001600160a01b0316826001600160a01b03167fdd47868997765508c515e1f8ca079846dafbdfd8f98f6e76bca0891810b9f9d18b8b8b8b8b8b6040516109a796959493929190611af9565b60405180910390a4505050505050505050565b836109c481611420565b6109e05760405162461bcd60e51b815260040161034d90611826565b6000856001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190611871565b6001600160a01b03818116600090815260046020526040902054919250878116911614610a835760405162461bcd60e51b815260040161034d9061188e565b6001600160a01b038116610a9957610a996118db565b306001600160a01b0316866001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b059190611871565b6001600160a01b031614610b1b57610b1b6118db565b604051637a94c56560e11b81526001600160a01b0387169063f5298aca90610b4b90339088908890600401611b42565b6020604051808303816000875af1158015610b6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8e9190611967565b610baa5760405162461bcd60e51b815260040161034d90611989565b600054600254604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152898116608083015260a0820189905260c08083018990528351808403909101815260e08301938490526316f1983160e01b909352620100009094048416936316f1983193610c429391169160e401611acd565b600060405180830381600087803b158015610c5c57600080fd5b505af1158015610c70573d6000803e3d6000fd5b50505050846001600160a01b0316866001600160a01b0316826001600160a01b03167fda58d73e08ba3c7767de904e68d208be8291494a9faaf70a6d4f736d24ec1f0f338888604051610cc593929190611b42565b60405180910390a4505050505050565b600080808080610ce786880188611b63565b6001600160a01b03808616600090815260046020526040902054959a50939850919650945092501680610d2c5760405162461bcd60e51b815260040161034d9061188e565b610d3581611420565b610d4157610d416118db565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da59190611871565b9050866001600160a01b0316816001600160a01b031614610dc857610dc86118db565b6001600160a01b038116610dde57610dde6118db565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4a9190611871565b6001600160a01b031614610e6057610e606118db565b604051630ab714fb60e11b81526001600160a01b0383169063156e29f690610e9090889088908890600401611b42565b6020604051808303816000875af1158015610eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed39190611967565b610eef5760405162461bcd60e51b815260040161034d90611bbe565b846001600160a01b0316826001600160a01b0316886001600160a01b03167f76a4cd47013e7e58abe817eedbb692d1614d71080b527412ebfb3f91a085a6de8988886040516109a793929190611b42565b600080808080610f5286880188611cdc565b6001600160a01b03808616600090815260046020526040902054959b509399509197509550935016905080610f995760405162461bcd60e51b815260040161034d9061188e565b610fa281611420565b610fae57610fae6118db565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110129190611871565b9050866001600160a01b0316816001600160a01b031614611035576110356118db565b6001600160a01b03811661104b5761104b6118db565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015611093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b79190611871565b6001600160a01b0316146110cd576110cd6118db565b604051635712868360e01b81526001600160a01b038316906357128683906110fd90889088908890600401611e21565b6020604051808303816000875af115801561111c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111409190611967565b61115c5760405162461bcd60e51b815260040161034d90611bbe565b856001600160a01b0316826001600160a01b0316886001600160a01b03167fc244cac13e0edc863dc5a2c3bd2b935f605b2ed225fb052eaef869bc24b76fde8888886040516109a793929190611e21565b6000806111bc83850185611e96565b9093509150506001600160a01b0382166111d8576111d86118db565b6001600160a01b038281166000908152600460205260409020541615611200576112006118db565b6003546040516bffffffffffffffffffffffff19606085901b166020820152600091611250916001600160a01b0390911690603401604051602081830303815290604052805190602001206114b5565b6001600160a01b0384811660009081526004602081905260409182902080546001600160a01b031916938516938417905590516379ccf11760e11b8152929350909163f399e22e916112a6918791879101611acd565b600060405180830381600087803b1580156112c057600080fd5b505af11580156112d4573d6000803e3d6000fd5b50506040516001600160a01b038085169350861691507f0a1eaf9aa124c3f84c9dd77f7016af0f16f67639abb913af1697387db01f5ca590600090a35050505050565b6001600160a01b0384161580159061133757506001600160a01b03831615155b801561134b57506001600160a01b03821615155b801561135f57506001600160a01b03811615155b6113c55760405162461bcd60e51b815260206004820152603160248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204260448201527020a22fa4a724aa24a0a624ad20aa24a7a760791b606482015260840161034d565b600080546001600160a01b03958616620100000262010000600160b01b0319909116179055600180549385166001600160a01b0319948516179055600280549285169284169290921790915560038054919093169116179055565b6000816001600160a01b03163b60000361143c57506000919050565b6040516301ffc9a760e01b8152636cdb3d1360e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa9250505080156114a3575060408051601f3d908101601f191682019092526114a091810190611967565b60015b6114af57506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b0381166114af5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b604482015260640161034d565b6001600160a01b038116811461156157600080fd5b50565b60006020828403121561157657600080fd5b81356115818161154c565b9392505050565b60008083601f84011261159a57600080fd5b5081356001600160401b038111156115b157600080fd5b6020830191508360208260051b85010111156115cc57600080fd5b9250929050565b60008060008060008060006080888a0312156115ee57600080fd5b87356115f98161154c565b965060208801356001600160401b038082111561161557600080fd5b6116218b838c01611588565b909850965060408a013591508082111561163a57600080fd5b6116468b838c01611588565b909650945060608a013591508082111561165f57600080fd5b5061166c8a828b01611588565b989b979a50959850939692959293505050565b60008060006060848603121561169457600080fd5b833561169f8161154c565b95602085013595506040909401359392505050565b600080600080608085870312156116ca57600080fd5b84356116d58161154c565b935060208501356116e58161154c565b93969395505050506040820135916060013590565b6000806000806060858703121561171057600080fd5b8435935060208501356117228161154c565b925060408501356001600160401b038082111561173e57600080fd5b818701915087601f83011261175257600080fd5b81358181111561176157600080fd5b88602082850101111561177357600080fd5b95989497505060200194505050565b6000806000806080858703121561179857600080fd5b84356117a38161154c565b935060208501356117b38161154c565b925060408501356117c38161154c565b915060608501356117d38161154c565b939692955090935050565b600080858511156117ee57600080fd5b838611156117fb57600080fd5b5050820193919092039150565b803560208310156114af57600019602084900360031b1b1692915050565b6020808252602b908201527f4368696c644d696e7461626c65455243313135355072656469636174653a204e60408201526a13d517d0d3d395149050d560aa1b606082015260800190565b60006020828403121561188357600080fd5b81516115818161154c565b6020808252602d908201527f4368696c644d696e7461626c65455243313135355072656469636174653a205560408201526c2726a0a82822a22faa27a5a2a760991b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b0383111561190a57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038616815260606020820181905260009061194890830186886118f1565b828103604084015261195b8185876118f1565b98975050505050505050565b60006020828403121561197957600080fd5b8151801515811461158157600080fd5b6020808252602a908201527f4368696c644d696e7461626c65455243313135355072656469636174653a204260408201526915549397d1905253115160b21b606082015260800190565b8183526000602080850194508260005b85811015611a115781356119f68161154c565b6001600160a01b0316875295820195908201906001016119e3565b509495945050505050565b8981526001600160a01b0389811660208301528816604082015260c060608201819052600090611a4f908301888a6119d3565b8281036080840152611a628187896118f1565b905082810360a0840152611a778185876118f1565b9c9b505050505050505050505050565b6000815180845260005b81811015611aad57602081850181015186830182015201611a91565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611af190830184611a87565b949350505050565b606081526000611b0d60608301888a6119d3565b8281036020840152611b208187896118f1565b90508281036040840152611b358185876118f1565b9998505050505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b600080600080600060a08688031215611b7b57600080fd5b8535611b868161154c565b94506020860135611b968161154c565b93506040860135611ba68161154c565b94979396509394606081013594506080013592915050565b6020808252602a908201527f4368696c644d696e7461626c65455243313135355072656469636174653a204d60408201526912539517d1905253115160b21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611c4657611c46611c08565b604052919050565b60006001600160401b03821115611c6757611c67611c08565b5060051b60200190565b600082601f830112611c8257600080fd5b81356020611c97611c9283611c4e565b611c1e565b82815260059290921b84018101918181019086841115611cb657600080fd5b8286015b84811015611cd15780358352918301918301611cba565b509695505050505050565b60008060008060008060c08789031215611cf557600080fd5b86359550602080880135611d088161154c565b95506040880135611d188161154c565b945060608801356001600160401b0380821115611d3457600080fd5b818a0191508a601f830112611d4857600080fd5b8135611d56611c9282611c4e565b81815260059190911b8301840190848101908d831115611d7557600080fd5b938501935b82851015611d9c578435611d8d8161154c565b82529385019390850190611d7a565b9750505060808a0135925080831115611db457600080fd5b611dc08b848c01611c71565b945060a08a0135925080831115611dd657600080fd5b5050611de489828a01611c71565b9150509295509295509295565b600081518084526020808501945080840160005b83811015611a1157815187529582019590820190600101611e05565b606080825284519082018190526000906020906080840190828801845b82811015611e635781516001600160a01b031684529284019290840190600101611e3e565b50505083810382850152611e778187611df1565b9150508281036040840152611e8c8185611df1565b9695505050505050565b600080600060608486031215611eab57600080fd5b83359250602080850135611ebe8161154c565b925060408501356001600160401b0380821115611eda57600080fd5b818701915087601f830112611eee57600080fd5b813581811115611f0057611f00611c08565b611f12601f8201601f19168501611c1e565b91508082528884828501011115611f2857600080fd5b8084840185840137600084828401015250809350505050925092509256fea264697066735822122026a554c5cf45bb8b62f522edf18a711a15c292f92508b7ed5d7fd755e7cb372a64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100d55760003560e01c8063b8cd3ec011610087578063b8cd3ec0146101b6578063c5ac2b1c146101c9578063cb10f94c146101f0578063d41f177114610209578063d7c9e3ec14610230578063f43cda8b14610257578063f64512551461026a578063f8c8765e1461029157600080fd5b8063051eb2e2146100da5780637efab4f51461010a57806386937eb41461013357806395c7041c14610148578063b17680651461015b578063b5c5f67214610190578063b68ad1e4146101a3575b600080fd5b6002546100ed906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ed610118366004611564565b6004602052600090815260409020546001600160a01b031681565b6101466101413660046115d3565b6102a4565b005b6001546100ed906001600160a01b031681565b6101827f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286981565b604051908152602001610101565b61014661019e36600461167f565b6102bc565b6003546100ed906001600160a01b031681565b6101466101c43660046116b4565b6102cd565b6101827faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d1881565b6000546100ed906201000090046001600160a01b031681565b6101827f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f82181565b6101827f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed281565b6101466102653660046116fa565b6102df565b6101827f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad81565b61014661029f366004611782565b610514565b6102b38787878787878761062d565b50505050505050565b6102c8833384846109ba565b505050565b6102d9848484846109ba565b50505050565b6001546001600160a01b031633146103565760405162461bcd60e51b815260206004820152602f60248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204f60448201526e27262cafa2ac24aa2fa422a62822a960891b60648201526084015b60405180910390fd5b6002546001600160a01b038481169116146103ce5760405162461bcd60e51b815260206004820152603260248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204f6044820152714e4c595f524f4f545f50524544494341544560701b606482015260840161034d565b7f87a7811f4bfedea3d341ad165680ae306b01aaeacc205d227629cf157dd9f8216103fd6020600084866117de565b61040691611808565b036104255761042061041b82602081866117de565b610cd5565b6102d9565b7faf50c8eab81226bc79eee3a10e3fe25db1a2be7241130e392b0675df839b6d186104546020600084866117de565b61045d91611808565b0361046c576104208282610f40565b7f2cef46a936bdc5b7e6e8c71aa04560c41cf7d88bb26901a7e7f4936ff02accad61049b6020600084866117de565b6104a491611808565b036104b35761042082826111ad565b60405162461bcd60e51b815260206004820152603060248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204960448201526f4e56414c49445f5349474e415455524560801b606482015260840161034d565b600054610100900460ff16158080156105345750600054600160ff909116105b8061054e5750303b15801561054e575060005460ff166001145b6105b15760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161034d565b6000805460ff1916600117905580156105d4576000805461ff0019166101001790555b6105e085858585611317565b8015610626576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b8661063781611420565b6106535760405162461bcd60e51b815260040161034d90611826565b6000886001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610693573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b79190611871565b6001600160a01b038181166000908152600460205260409020549192508a81169116146106f65760405162461bcd60e51b815260040161034d9061188e565b6001600160a01b03811661070c5761070c6118db565b306001600160a01b0316896001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610754573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107789190611871565b6001600160a01b03161461078e5761078e6118db565b868514801561079c57508483145b6107fe5760405162461bcd60e51b815260206004820152602d60248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204960448201526c09cac82989288be988a9c8ea89609b1b606482015260840161034d565b604051631ac8311560e21b81526001600160a01b038a1690636b20c454906108329033908a908a908a908a90600401611923565b6020604051808303816000875af1158015610851573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108759190611967565b6108915760405162461bcd60e51b815260040161034d90611989565b6000546002546040516001600160a01b03620100009093048316926316f198319216906108f2907f5fb452c5a8f2b7c7ef2984e2f1063c7ee9b80b110cdc98ccb98f6654e10b5ed290869033908f908f908f908f908f908f90602001611a1c565b6040516020818303038152906040526040518363ffffffff1660e01b815260040161091e929190611acd565b600060405180830381600087803b15801561093857600080fd5b505af115801561094c573d6000803e3d6000fd5b50505050336001600160a01b0316896001600160a01b0316826001600160a01b03167fdd47868997765508c515e1f8ca079846dafbdfd8f98f6e76bca0891810b9f9d18b8b8b8b8b8b6040516109a796959493929190611af9565b60405180910390a4505050505050505050565b836109c481611420565b6109e05760405162461bcd60e51b815260040161034d90611826565b6000856001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a449190611871565b6001600160a01b03818116600090815260046020526040902054919250878116911614610a835760405162461bcd60e51b815260040161034d9061188e565b6001600160a01b038116610a9957610a996118db565b306001600160a01b0316866001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ae1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b059190611871565b6001600160a01b031614610b1b57610b1b6118db565b604051637a94c56560e11b81526001600160a01b0387169063f5298aca90610b4b90339088908890600401611b42565b6020604051808303816000875af1158015610b6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8e9190611967565b610baa5760405162461bcd60e51b815260040161034d90611989565b600054600254604080517f7a8dc26796a1e50e6e190b70259f58f6a4edd5b22280ceecc82b687b8e98286960208201526001600160a01b0385811682840152336060830152898116608083015260a0820189905260c08083018990528351808403909101815260e08301938490526316f1983160e01b909352620100009094048416936316f1983193610c429391169160e401611acd565b600060405180830381600087803b158015610c5c57600080fd5b505af1158015610c70573d6000803e3d6000fd5b50505050846001600160a01b0316866001600160a01b0316826001600160a01b03167fda58d73e08ba3c7767de904e68d208be8291494a9faaf70a6d4f736d24ec1f0f338888604051610cc593929190611b42565b60405180910390a4505050505050565b600080808080610ce786880188611b63565b6001600160a01b03808616600090815260046020526040902054959a50939850919650945092501680610d2c5760405162461bcd60e51b815260040161034d9061188e565b610d3581611420565b610d4157610d416118db565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610da59190611871565b9050866001600160a01b0316816001600160a01b031614610dc857610dc86118db565b6001600160a01b038116610dde57610dde6118db565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4a9190611871565b6001600160a01b031614610e6057610e606118db565b604051630ab714fb60e11b81526001600160a01b0383169063156e29f690610e9090889088908890600401611b42565b6020604051808303816000875af1158015610eaf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed39190611967565b610eef5760405162461bcd60e51b815260040161034d90611bbe565b846001600160a01b0316826001600160a01b0316886001600160a01b03167f76a4cd47013e7e58abe817eedbb692d1614d71080b527412ebfb3f91a085a6de8988886040516109a793929190611b42565b600080808080610f5286880188611cdc565b6001600160a01b03808616600090815260046020526040902054959b509399509197509550935016905080610f995760405162461bcd60e51b815260040161034d9061188e565b610fa281611420565b610fae57610fae6118db565b6000816001600160a01b0316631f2d00656040518163ffffffff1660e01b8152600401602060405180830381865afa158015610fee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110129190611871565b9050866001600160a01b0316816001600160a01b031614611035576110356118db565b6001600160a01b03811661104b5761104b6118db565b306001600160a01b0316826001600160a01b031663e61987056040518163ffffffff1660e01b8152600401602060405180830381865afa158015611093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b79190611871565b6001600160a01b0316146110cd576110cd6118db565b604051635712868360e01b81526001600160a01b038316906357128683906110fd90889088908890600401611e21565b6020604051808303816000875af115801561111c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111409190611967565b61115c5760405162461bcd60e51b815260040161034d90611bbe565b856001600160a01b0316826001600160a01b0316886001600160a01b03167fc244cac13e0edc863dc5a2c3bd2b935f605b2ed225fb052eaef869bc24b76fde8888886040516109a793929190611e21565b6000806111bc83850185611e96565b9093509150506001600160a01b0382166111d8576111d86118db565b6001600160a01b038281166000908152600460205260409020541615611200576112006118db565b6003546040516bffffffffffffffffffffffff19606085901b166020820152600091611250916001600160a01b0390911690603401604051602081830303815290604052805190602001206114b5565b6001600160a01b0384811660009081526004602081905260409182902080546001600160a01b031916938516938417905590516379ccf11760e11b8152929350909163f399e22e916112a6918791879101611acd565b600060405180830381600087803b1580156112c057600080fd5b505af11580156112d4573d6000803e3d6000fd5b50506040516001600160a01b038085169350861691507f0a1eaf9aa124c3f84c9dd77f7016af0f16f67639abb913af1697387db01f5ca590600090a35050505050565b6001600160a01b0384161580159061133757506001600160a01b03831615155b801561134b57506001600160a01b03821615155b801561135f57506001600160a01b03811615155b6113c55760405162461bcd60e51b815260206004820152603160248201527f4368696c644d696e7461626c65455243313135355072656469636174653a204260448201527020a22fa4a724aa24a0a624ad20aa24a7a760791b606482015260840161034d565b600080546001600160a01b03958616620100000262010000600160b01b0319909116179055600180549385166001600160a01b0319948516179055600280549285169284169290921790915560038054919093169116179055565b6000816001600160a01b03163b60000361143c57506000919050565b6040516301ffc9a760e01b8152636cdb3d1360e11b60048201526001600160a01b038316906301ffc9a790602401602060405180830381865afa9250505080156114a3575060408051601f3d908101601f191682019092526114a091810190611967565b60015b6114af57506000919050565b92915050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008360601b60e81c176000526e5af43d82803e903d91602b57fd5bf38360781b1760205281603760096000f590506001600160a01b0381166114af5760405162461bcd60e51b8152602060048201526017602482015276115490cc4c4d8dce8818dc99585d194c8819985a5b1959604a1b604482015260640161034d565b6001600160a01b038116811461156157600080fd5b50565b60006020828403121561157657600080fd5b81356115818161154c565b9392505050565b60008083601f84011261159a57600080fd5b5081356001600160401b038111156115b157600080fd5b6020830191508360208260051b85010111156115cc57600080fd5b9250929050565b60008060008060008060006080888a0312156115ee57600080fd5b87356115f98161154c565b965060208801356001600160401b038082111561161557600080fd5b6116218b838c01611588565b909850965060408a013591508082111561163a57600080fd5b6116468b838c01611588565b909650945060608a013591508082111561165f57600080fd5b5061166c8a828b01611588565b989b979a50959850939692959293505050565b60008060006060848603121561169457600080fd5b833561169f8161154c565b95602085013595506040909401359392505050565b600080600080608085870312156116ca57600080fd5b84356116d58161154c565b935060208501356116e58161154c565b93969395505050506040820135916060013590565b6000806000806060858703121561171057600080fd5b8435935060208501356117228161154c565b925060408501356001600160401b038082111561173e57600080fd5b818701915087601f83011261175257600080fd5b81358181111561176157600080fd5b88602082850101111561177357600080fd5b95989497505060200194505050565b6000806000806080858703121561179857600080fd5b84356117a38161154c565b935060208501356117b38161154c565b925060408501356117c38161154c565b915060608501356117d38161154c565b939692955090935050565b600080858511156117ee57600080fd5b838611156117fb57600080fd5b5050820193919092039150565b803560208310156114af57600019602084900360031b1b1692915050565b6020808252602b908201527f4368696c644d696e7461626c65455243313135355072656469636174653a204e60408201526a13d517d0d3d395149050d560aa1b606082015260800190565b60006020828403121561188357600080fd5b81516115818161154c565b6020808252602d908201527f4368696c644d696e7461626c65455243313135355072656469636174653a205560408201526c2726a0a82822a22faa27a5a2a760991b606082015260800190565b634e487b7160e01b600052600160045260246000fd5b81835260006001600160fb1b0383111561190a57600080fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038616815260606020820181905260009061194890830186886118f1565b828103604084015261195b8185876118f1565b98975050505050505050565b60006020828403121561197957600080fd5b8151801515811461158157600080fd5b6020808252602a908201527f4368696c644d696e7461626c65455243313135355072656469636174653a204260408201526915549397d1905253115160b21b606082015260800190565b8183526000602080850194508260005b85811015611a115781356119f68161154c565b6001600160a01b0316875295820195908201906001016119e3565b509495945050505050565b8981526001600160a01b0389811660208301528816604082015260c060608201819052600090611a4f908301888a6119d3565b8281036080840152611a628187896118f1565b905082810360a0840152611a778185876118f1565b9c9b505050505050505050505050565b6000815180845260005b81811015611aad57602081850181015186830182015201611a91565b506000602082860101526020601f19601f83011685010191505092915050565b6001600160a01b0383168152604060208201819052600090611af190830184611a87565b949350505050565b606081526000611b0d60608301888a6119d3565b8281036020840152611b208187896118f1565b90508281036040840152611b358185876118f1565b9998505050505050505050565b6001600160a01b039390931683526020830191909152604082015260600190565b600080600080600060a08688031215611b7b57600080fd5b8535611b868161154c565b94506020860135611b968161154c565b93506040860135611ba68161154c565b94979396509394606081013594506080013592915050565b6020808252602a908201527f4368696c644d696e7461626c65455243313135355072656469636174653a204d60408201526912539517d1905253115160b21b606082015260800190565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611c4657611c46611c08565b604052919050565b60006001600160401b03821115611c6757611c67611c08565b5060051b60200190565b600082601f830112611c8257600080fd5b81356020611c97611c9283611c4e565b611c1e565b82815260059290921b84018101918181019086841115611cb657600080fd5b8286015b84811015611cd15780358352918301918301611cba565b509695505050505050565b60008060008060008060c08789031215611cf557600080fd5b86359550602080880135611d088161154c565b95506040880135611d188161154c565b945060608801356001600160401b0380821115611d3457600080fd5b818a0191508a601f830112611d4857600080fd5b8135611d56611c9282611c4e565b81815260059190911b8301840190848101908d831115611d7557600080fd5b938501935b82851015611d9c578435611d8d8161154c565b82529385019390850190611d7a565b9750505060808a0135925080831115611db457600080fd5b611dc08b848c01611c71565b945060a08a0135925080831115611dd657600080fd5b5050611de489828a01611c71565b9150509295509295509295565b600081518084526020808501945080840160005b83811015611a1157815187529582019590820190600101611e05565b606080825284519082018190526000906020906080840190828801845b82811015611e635781516001600160a01b031684529284019290840190600101611e3e565b50505083810382850152611e778187611df1565b9150508281036040840152611e8c8185611df1565b9695505050505050565b600080600060608486031215611eab57600080fd5b83359250602080850135611ebe8161154c565b925060408501356001600160401b0380821115611eda57600080fd5b818701915087601f830112611eee57600080fd5b813581811115611f0057611f00611c08565b611f12601f8201601f19168501611c1e565b91508082528884828501011115611f2857600080fd5b8084840185840137600084828401015250809350505050925092509256fea264697066735822122026a554c5cf45bb8b62f522edf18a711a15c292f92508b7ed5d7fd755e7cb372a64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var CustomSupernetManagerArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"CustomSupernetManager\",\n \"sourceName\": \"contracts/root/staking/CustomSupernetManager.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"InvalidSignature\",\n \"type\": \"error\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"message\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"AddedToWhitelist\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amountValidators\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"GenesisFinalized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferStarted\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"previousOwner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"OwnershipTransferred\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"RemovedFromWhitelist\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [],\n \"name\": \"StakingEnabled\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"ValidatorDeactivated\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n }\n ],\n \"name\": \"ValidatorRegistered\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"SLASHING_PERCENTAGE\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"acceptOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"domain\",\n \"outputs\": [\n {\n \"internalType\": \"bytes32\",\n \"name\": \"\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"enableStaking\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"finalizeGenesis\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"genesisSet\",\n \"outputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"initialStake\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct GenesisValidator[]\",\n \"name\": \"\",\n \"type\": \"tuple[]\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator_\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"getValidator\",\n \"outputs\": [\n {\n \"components\": [\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"blsKey\",\n \"type\": \"uint256[4]\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"stake\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"isWhitelisted\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"isActive\",\n \"type\": \"bool\"\n }\n ],\n \"internalType\": \"struct Validator\",\n \"name\": \"\",\n \"type\": \"tuple\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"id\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStakeManager\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newBls\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newMatic\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newChildValidatorSet\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newExitHelper\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"string\",\n \"name\": \"newDomain\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id_\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"onInit\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onL2StateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"onStake\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"owner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"pendingOwner\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256[2]\",\n \"name\": \"signature\",\n \"type\": \"uint256[2]\"\n },\n {\n \"internalType\": \"uint256[4]\",\n \"name\": \"pubkey\",\n \"type\": \"uint256[4]\"\n }\n ],\n \"name\": \"register\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"renounceOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newOwner\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"transferOwnership\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"validators\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"stake\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"isWhitelisted\",\n \"type\": \"bool\"\n },\n {\n \"internalType\": \"bool\",\n \"name\": \"isActive\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address[]\",\n \"name\": \"validators_\",\n \"type\": \"address[]\"\n }\n ],\n \"name\": \"whitelistValidators\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"withdrawSlashedStake\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b506120de806100206000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80639e19e9c1116100ad578063e30c397811610071578063e30c397814610232578063f2fde38b14610243578063f43cda8b14610256578063fa52c7d814610269578063fd051b4a146102bc57600080fd5b80639e19e9c1146101ed578063af640d0f14610202578063bd8d64d914610219578063c2fb26a614610221578063d11aca621461022a57600080fd5b8063715018a6116100f4578063715018a6146101a857806379ba5097146101b057806385758cc7146101b85780638c087b1c146101c05780638da5cb5b146101d357600080fd5b80631904bb2e146101315780631f6590b81461015a578063344a5e641461016f57806344efbf8414610182578063542c85f214610195575b600080fd5b61014461013f366004611930565b6102cf565b604051610151919061194d565b60405180910390f35b61016d6101683660046119a1565b610359565b005b61016d61017d3660046119e3565b610426565b61016d610190366004611930565b6104a5565b61016d6101a33660046119fc565b61053d565b61016d610598565b61016d6105ac565b61016d610626565b61016d6101ce366004611a71565b610677565b6033546001600160a01b03165b6040516101519190611a9d565b6101f56106ab565b6040516101519190611ab1565b61020b60985481565b604051908152602001610151565b61020b603281565b61020b60d05481565b61016d6106bc565b6065546001600160a01b03166101e0565b61016d610251366004611930565b6106f9565b61016d610264366004611b09565b61076a565b61029f610277366004611930565b60d4602052600090815260409020600481015460059091015460ff8082169161010090041683565b604080519384529115156020840152151590820152606001610151565b61016d6102ca366004611bd9565b6108a7565b6102d761185e565b6001600160a01b038216600090815260d46020526040908190208151610100810190925281608081018260048282826020028201915b81548152602001906001019080831161030d5750505091835250506004820154602082015260059091015460ff8082161515604084015261010090910416151560609091015292915050565b33600090815260d460205260409020600581015460ff166103ae5760405163973d02cb60e01b815260206004820152600960248201526815d2125511531254d560ba1b60448201526064015b60405180910390fd5b6103b9338484610b02565b6103c58183600461188c565b5060058101805461ff0019166101001790556103e033610be1565b336001600160a01b03167f110ae3ae039a4632f836a35dc9b1282df88780883fb28779f22c2f7ccde8dd0a836040516104199190611cde565b60405180910390a2505050565b6097546001600160a01b031633146104505760405162461bcd60e51b81526004016103a590611ced565b609854156104a05760405162461bcd60e51b815260206004820152601f60248201527f53757065726e65744d616e616765723a2049445f414c52454144595f5345540060448201526064016103a5565b609855565b6104ad610c2d565b60cd546040516370a0823160e01b81526000916001600160a01b0316906370a08231906104de903090600401611a9d565b602060405180830381865afa1580156104fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051f9190611d30565b60cd54909150610539906001600160a01b03168383610c87565b5050565b610545610c2d565b8060005b818110156105925761058084848381811061056657610566611d49565b905060200201602081019061057b9190611930565b610ce2565b8061058a81611d75565b915050610549565b50505050565b6105a0610c2d565b6105aa6000610d31565b565b60655433906001600160a01b0316811461061a5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016103a5565b61062381610d31565b50565b61062e610c2d565b61063860d1610d4a565b7f87f41ee3facb6317b1c2811e539539ac1693525b4460699b4245e8aac9f590cb61066360d1610dc4565b5160405190815260200160405180910390a1565b6097546001600160a01b031633146106a15760405162461bcd60e51b81526004016103a590611ced565b6105398282610e3d565b60606106b760d1610dc4565b905090565b6106c4610c2d565b6106ce60d1610fb6565b6040517fda917aeab736a19e4ba54207413dbe4f8c7d558fde2c14d7e66fc8f7186ea8a390600090a1565b610701610c2d565b606580546001600160a01b0383166001600160a01b031990911681179091556107326033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60cf546001600160a01b031633141580610792575060ce546001600160a01b03848116911614155b156107cd5760405163973d02cb60e01b815260206004820152600a60248201526932bc34ba2432b63832b960b11b60448201526064016103a5565b7f8ca9a95e41b5eece253c93f5b31eed1253aed6b145d8a6e14d913fdf8e7322936107fc602060008486611d8e565b61080591611db8565b0361083c5760008061081a8360208187611d8e565b8101906108279190611a71565b91509150610835828261108d565b5050610592565b7f117f1d6f44fd34ccb7a58f1261fa59e5c4bf68e2712d65f246a8805167a9334461086b602060008486611d8e565b61087491611db8565b036105925760006108888260208186611d8e565b8101906108959190611930565b90506108a0816110fa565b5050505050565b600054610100900460ff16158080156108c75750600054600160ff909116105b806108e15750303b1580156108e1575060005460ff166001145b6109445760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103a5565b6000805460ff191660011790558015610967576000805461ff0019166101001790555b6001600160a01b0388161580159061098757506001600160a01b03871615155b801561099b57506001600160a01b03861615155b80156109af57506001600160a01b03851615155b80156109c357506001600160a01b03841615155b80156109d757506001600160a01b03831615155b80156109e35750815115155b610a1f5760405162461bcd60e51b815260206004820152600d60248201526c1253959053125117d253941555609a1b60448201526064016103a5565b610a28886111f8565b60cb80546001600160a01b03199081166001600160a01b038a81169190911790925560cc8054821689841617905560cd8054821688841617905560ce8054821687841617905560cf8054909116918516919091179055604051610a8f908390602001611dfa565b60408051601f19818403018152919052805160209091012060d055610ab2611241565b8015610af8576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b8135158015610b1357506020820135155b15610b335782604051633615713d60e21b81526004016103a59190611a9d565b60cb5460009081906001600160a01b031663ebbdac918585610b5489611270565b6040518463ffffffff1660e01b8152600401610b7293929190611e16565b6040805180830381865afa158015610b8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb29190611e6f565b91509150801580610bc1575081155b156108a05784604051633615713d60e21b81526004016103a59190611a9d565b6001600160a01b038116600081815260d46020526040808220600501805460ff19169055517fcdd2e9b91a56913d370075169cefa1602ba36be5301664f752192bb1709df7579190a250565b6033546001600160a01b031633146105aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103a5565b610cdd8363a9059cbb60e01b8484604051602401610ca6929190611ea2565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611332565b505050565b6001600160a01b038116600081815260d46020526040808220600501805460ff19166001179055517fa850ae9193f515cbae8d35e8925bd2be26627fc91bce650b8652ed254e9cab039190a250565b606580546001600160a01b031916905561062381611407565b6000600182015460ff166002811115610d6557610d65611ebb565b14610db25760405162461bcd60e51b815260206004820152601d60248201527f47656e657369734c69623a20616c72656164792066696e616c697a656400000060448201526064016103a5565b6001908101805460ff19169091179055565b606081600001805480602002602001604051908101604052809291908181526020016000905b82821015610e32576000848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101610dea565b505050509050919050565b6001600160a01b038216600090815260d460205260409020600501548290610100900460ff16610e9c5760405163973d02cb60e01b81526020600482015260096024820152682b20a624a220aa27a960b91b60448201526064016103a5565b610ea660d1611459565b15610eb757610cdd60d1848461147d565b610ec160d161158f565b15610f7a5760cc5460ce54604080517f1bcc0f4c3fad314e585165815f94ecca9b96690a26d6417d7876448a9a867a6960208201526001600160a01b038781168284015260608083018890528351808403909101815260808301938490526316f1983160e01b909352938416936316f1983193610f4393911691608401611efd565b600060405180830381600087803b158015610f5d57600080fd5b505af1158015610f71573d6000803e3d6000fd5b50505050505050565b60405163973d02cb60e01b815260206004820152601060248201526f5761697420666f722067656e6573697360801b60448201526064016103a5565b600181015460ff166000816002811115610fd257610fd2611ebb565b0361101b5760405162461bcd60e51b815260206004820152601960248201527811d95b995cda5cd31a588e881b9bdd08199a5b985b1a5e9959603a1b60448201526064016103a5565b600281600281111561102f5761102f611ebb565b0361107c5760405162461bcd60e51b815260206004820152601b60248201527f47656e657369734c69623a20616c726561647920656e61626c6564000000000060448201526064016103a5565b50600101805460ff19166002179055565b609754604051633651bb1d60e01b81526001600160a01b0390911690633651bb1d906110bf9085908590600401611ea2565b600060405180830381600087803b1580156110d957600080fd5b505af11580156110ed573d6000803e3d6000fd5b5050505061053982611598565b609754609854604051633b61c5a760e21b81526000926001600160a01b03169163ed87169c9161112e918691600401611ea2565b602060405180830381865afa15801561114b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116f9190611d30565b905060006064611180603284611f21565b61118a9190611f38565b609754604051638028a6db60e01b81529192506001600160a01b031690638028a6db906111bd9086908590600401611ea2565b600060405180830381600087803b1580156111d757600080fd5b505af11580156111eb573d6000803e3d6000fd5b50505050610cdd83611598565b600054610100900460ff1661121f5760405162461bcd60e51b81526004016103a590611f5a565b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166112685760405162461bcd60e51b81526004016103a590611f5a565b6105aa611661565b6112786118ca565b60cb5460d0546040516bffffffffffffffffffffffff19606086811b8216602084015230901b1660348201524660488201526001600160a01b039092169163a850a90991906068016040516020818303038152906040526040518363ffffffff1660e01b81526004016112ec929190611fa5565b6040805180830381865afa158015611308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132c9190611fbe565b92915050565b6000611387826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166116919092919063ffffffff16565b90508051600014806113a85750808060200190518101906113a8919061203e565b610cdd5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016103a5565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000805b600183015460ff16600281111561147657611476611ebb565b1492915050565b6000600184015460ff16600281111561149857611498611ebb565b146114a5576114a5612059565b6001600160a01b0382166000908152600284016020526040812054908190036115425783546114d590600161206f565b6001600160a01b03848116600081815260028881016020908152604080842087905580518082019091529384528381018881528a5460018082018d558c86529290942094519390920290930180546001600160a01b03191692909416919091178355519101559050610592565b60008461154f81866116a8565b8154811061155f5761155f611d49565b9060005260206000209060020201905082816001016000828254611583919061206f565b90915550505050505050565b6000600261145d565b609754609854604051633b61c5a760e21b81526001600160a01b039092169163ed87169c916115cc91859190600401611ea2565b602060405180830381865afa1580156115e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160d9190611d30565b600003610623576001600160a01b038116600081815260d46020526040808220600501805461ff0019169055517f23d934bfe7f1275bc6fd70432159c9cc1c0075d069f89da6a40f43bfe7a94ed39190a250565b600054610100900460ff166116885760405162461bcd60e51b81526004016103a590611f5a565b6105aa33610d31565b60606116a084846000856116e5565b949350505050565b6001600160a01b0381166000908152600283016020526040812054908190036116d3576116d3612059565b6116de600182612082565b9392505050565b6060824710156117465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016103a5565b600080866001600160a01b031685876040516117629190611dfa565b60006040518083038185875af1925050503d806000811461179f576040519150601f19603f3d011682016040523d82523d6000602084013e6117a4565b606091505b50915091506117b5878383876117c0565b979650505050505050565b6060831561182f578251600003611828576001600160a01b0385163b6118285760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103a5565b50816116a0565b6116a083838151156118445781518083602001fd5b8060405162461bcd60e51b81526004016103a59190612095565b60405180608001604052806118716118e8565b81526000602082018190526040820181905260609091015290565b82600481019282156118ba579160200282015b828111156118ba57823582559160200191906001019061189f565b506118c6929150611906565b5090565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b5b808211156118c65760008155600101611907565b6001600160a01b038116811461062357600080fd5b60006020828403121561194257600080fd5b81356116de8161191b565b815160e08201908260005b6004811015611977578251825260209283019290910190600101611958565b505050602083015160808301526040830151151560a0830152606090920151151560c09091015290565b60008060c083850312156119b457600080fd5b60408301848111156119c557600080fd5b8392508460c0850111156119d857600080fd5b809150509250929050565b6000602082840312156119f557600080fd5b5035919050565b60008060208385031215611a0f57600080fd5b823567ffffffffffffffff80821115611a2757600080fd5b818501915085601f830112611a3b57600080fd5b813581811115611a4a57600080fd5b8660208260051b8501011115611a5f57600080fd5b60209290920196919550909350505050565b60008060408385031215611a8457600080fd5b8235611a8f8161191b565b946020939093013593505050565b6001600160a01b0391909116815260200190565b602080825282518282018190526000919060409081850190868401855b82811015611afc57815180516001600160a01b03168552860151868501529284019290850190600101611ace565b5091979650505050505050565b60008060008060608587031215611b1f57600080fd5b843593506020850135611b318161191b565b9250604085013567ffffffffffffffff80821115611b4e57600080fd5b818701915087601f830112611b6257600080fd5b813581811115611b7157600080fd5b886020828501011115611b8357600080fd5b95989497505060200194505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611bd157611bd1611b92565b604052919050565b600080600080600080600060e0888a031215611bf457600080fd5b8735611bff8161191b565b9650602088810135611c108161191b565b96506040890135611c208161191b565b95506060890135611c308161191b565b94506080890135611c408161191b565b935060a0890135611c508161191b565b925060c089013567ffffffffffffffff80821115611c6d57600080fd5b818b0191508b601f830112611c8157600080fd5b813581811115611c9357611c93611b92565b611ca5601f8201601f19168501611ba8565b91508082528c84828501011115611cbb57600080fd5b808484018584013760008482840101525080935050505092959891949750929550565b60808181019083833792915050565b60208082526023908201527f53757065726e65744d616e616765723a204f4e4c595f5354414b455f4d414e4160408201526223a2a960e91b606082015260800190565b600060208284031215611d4257600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611d8757611d87611d5f565b5060010190565b60008085851115611d9e57600080fd5b83861115611dab57600080fd5b5050820193919092039150565b8035602083101561132c57600019602084900360031b1b1692915050565b60005b83811015611df1578181015183820152602001611dd9565b50506000910152565b60008251611e0c818460208701611dd6565b9190910192915050565b61010081016040858337608084604084013760c082018360005b6002811015611e4f578151835260209283019290910190600101611e30565b505050949350505050565b80518015158114611e6a57600080fd5b919050565b60008060408385031215611e8257600080fd5b611e8b83611e5a565b9150611e9960208401611e5a565b90509250929050565b6001600160a01b03929092168252602082015260400190565b634e487b7160e01b600052602160045260246000fd5b60008151808452611ee9816020860160208601611dd6565b601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906116a090830184611ed1565b808202811582820484141761132c5761132c611d5f565b600082611f5557634e487b7160e01b600052601260045260246000fd5b500490565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8281526040602082015260006116a06040830184611ed1565b600060408284031215611fd057600080fd5b82601f830112611fdf57600080fd5b6040516040810181811067ffffffffffffffff8211171561200257612002611b92565b806040525080604084018581111561201957600080fd5b845b8181101561203357805183526020928301920161201b565b509195945050505050565b60006020828403121561205057600080fd5b6116de82611e5a565b634e487b7160e01b600052600160045260246000fd5b8082018082111561132c5761132c611d5f565b8181038181111561132c5761132c611d5f565b6020815260006116de6020830184611ed156fea2646970667358221220bc982b5eb2308e71d272d016ed22be05a9dcf98b734fd3bd0b62563ec962766664736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80639e19e9c1116100ad578063e30c397811610071578063e30c397814610232578063f2fde38b14610243578063f43cda8b14610256578063fa52c7d814610269578063fd051b4a146102bc57600080fd5b80639e19e9c1146101ed578063af640d0f14610202578063bd8d64d914610219578063c2fb26a614610221578063d11aca621461022a57600080fd5b8063715018a6116100f4578063715018a6146101a857806379ba5097146101b057806385758cc7146101b85780638c087b1c146101c05780638da5cb5b146101d357600080fd5b80631904bb2e146101315780631f6590b81461015a578063344a5e641461016f57806344efbf8414610182578063542c85f214610195575b600080fd5b61014461013f366004611930565b6102cf565b604051610151919061194d565b60405180910390f35b61016d6101683660046119a1565b610359565b005b61016d61017d3660046119e3565b610426565b61016d610190366004611930565b6104a5565b61016d6101a33660046119fc565b61053d565b61016d610598565b61016d6105ac565b61016d610626565b61016d6101ce366004611a71565b610677565b6033546001600160a01b03165b6040516101519190611a9d565b6101f56106ab565b6040516101519190611ab1565b61020b60985481565b604051908152602001610151565b61020b603281565b61020b60d05481565b61016d6106bc565b6065546001600160a01b03166101e0565b61016d610251366004611930565b6106f9565b61016d610264366004611b09565b61076a565b61029f610277366004611930565b60d4602052600090815260409020600481015460059091015460ff8082169161010090041683565b604080519384529115156020840152151590820152606001610151565b61016d6102ca366004611bd9565b6108a7565b6102d761185e565b6001600160a01b038216600090815260d46020526040908190208151610100810190925281608081018260048282826020028201915b81548152602001906001019080831161030d5750505091835250506004820154602082015260059091015460ff8082161515604084015261010090910416151560609091015292915050565b33600090815260d460205260409020600581015460ff166103ae5760405163973d02cb60e01b815260206004820152600960248201526815d2125511531254d560ba1b60448201526064015b60405180910390fd5b6103b9338484610b02565b6103c58183600461188c565b5060058101805461ff0019166101001790556103e033610be1565b336001600160a01b03167f110ae3ae039a4632f836a35dc9b1282df88780883fb28779f22c2f7ccde8dd0a836040516104199190611cde565b60405180910390a2505050565b6097546001600160a01b031633146104505760405162461bcd60e51b81526004016103a590611ced565b609854156104a05760405162461bcd60e51b815260206004820152601f60248201527f53757065726e65744d616e616765723a2049445f414c52454144595f5345540060448201526064016103a5565b609855565b6104ad610c2d565b60cd546040516370a0823160e01b81526000916001600160a01b0316906370a08231906104de903090600401611a9d565b602060405180830381865afa1580156104fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061051f9190611d30565b60cd54909150610539906001600160a01b03168383610c87565b5050565b610545610c2d565b8060005b818110156105925761058084848381811061056657610566611d49565b905060200201602081019061057b9190611930565b610ce2565b8061058a81611d75565b915050610549565b50505050565b6105a0610c2d565b6105aa6000610d31565b565b60655433906001600160a01b0316811461061a5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016103a5565b61062381610d31565b50565b61062e610c2d565b61063860d1610d4a565b7f87f41ee3facb6317b1c2811e539539ac1693525b4460699b4245e8aac9f590cb61066360d1610dc4565b5160405190815260200160405180910390a1565b6097546001600160a01b031633146106a15760405162461bcd60e51b81526004016103a590611ced565b6105398282610e3d565b60606106b760d1610dc4565b905090565b6106c4610c2d565b6106ce60d1610fb6565b6040517fda917aeab736a19e4ba54207413dbe4f8c7d558fde2c14d7e66fc8f7186ea8a390600090a1565b610701610c2d565b606580546001600160a01b0383166001600160a01b031990911681179091556107326033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60cf546001600160a01b031633141580610792575060ce546001600160a01b03848116911614155b156107cd5760405163973d02cb60e01b815260206004820152600a60248201526932bc34ba2432b63832b960b11b60448201526064016103a5565b7f8ca9a95e41b5eece253c93f5b31eed1253aed6b145d8a6e14d913fdf8e7322936107fc602060008486611d8e565b61080591611db8565b0361083c5760008061081a8360208187611d8e565b8101906108279190611a71565b91509150610835828261108d565b5050610592565b7f117f1d6f44fd34ccb7a58f1261fa59e5c4bf68e2712d65f246a8805167a9334461086b602060008486611d8e565b61087491611db8565b036105925760006108888260208186611d8e565b8101906108959190611930565b90506108a0816110fa565b5050505050565b600054610100900460ff16158080156108c75750600054600160ff909116105b806108e15750303b1580156108e1575060005460ff166001145b6109445760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103a5565b6000805460ff191660011790558015610967576000805461ff0019166101001790555b6001600160a01b0388161580159061098757506001600160a01b03871615155b801561099b57506001600160a01b03861615155b80156109af57506001600160a01b03851615155b80156109c357506001600160a01b03841615155b80156109d757506001600160a01b03831615155b80156109e35750815115155b610a1f5760405162461bcd60e51b815260206004820152600d60248201526c1253959053125117d253941555609a1b60448201526064016103a5565b610a28886111f8565b60cb80546001600160a01b03199081166001600160a01b038a81169190911790925560cc8054821689841617905560cd8054821688841617905560ce8054821687841617905560cf8054909116918516919091179055604051610a8f908390602001611dfa565b60408051601f19818403018152919052805160209091012060d055610ab2611241565b8015610af8576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b8135158015610b1357506020820135155b15610b335782604051633615713d60e21b81526004016103a59190611a9d565b60cb5460009081906001600160a01b031663ebbdac918585610b5489611270565b6040518463ffffffff1660e01b8152600401610b7293929190611e16565b6040805180830381865afa158015610b8e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb29190611e6f565b91509150801580610bc1575081155b156108a05784604051633615713d60e21b81526004016103a59190611a9d565b6001600160a01b038116600081815260d46020526040808220600501805460ff19169055517fcdd2e9b91a56913d370075169cefa1602ba36be5301664f752192bb1709df7579190a250565b6033546001600160a01b031633146105aa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103a5565b610cdd8363a9059cbb60e01b8484604051602401610ca6929190611ea2565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611332565b505050565b6001600160a01b038116600081815260d46020526040808220600501805460ff19166001179055517fa850ae9193f515cbae8d35e8925bd2be26627fc91bce650b8652ed254e9cab039190a250565b606580546001600160a01b031916905561062381611407565b6000600182015460ff166002811115610d6557610d65611ebb565b14610db25760405162461bcd60e51b815260206004820152601d60248201527f47656e657369734c69623a20616c72656164792066696e616c697a656400000060448201526064016103a5565b6001908101805460ff19169091179055565b606081600001805480602002602001604051908101604052809291908181526020016000905b82821015610e32576000848152602090819020604080518082019091526002850290910180546001600160a01b03168252600190810154828401529083529092019101610dea565b505050509050919050565b6001600160a01b038216600090815260d460205260409020600501548290610100900460ff16610e9c5760405163973d02cb60e01b81526020600482015260096024820152682b20a624a220aa27a960b91b60448201526064016103a5565b610ea660d1611459565b15610eb757610cdd60d1848461147d565b610ec160d161158f565b15610f7a5760cc5460ce54604080517f1bcc0f4c3fad314e585165815f94ecca9b96690a26d6417d7876448a9a867a6960208201526001600160a01b038781168284015260608083018890528351808403909101815260808301938490526316f1983160e01b909352938416936316f1983193610f4393911691608401611efd565b600060405180830381600087803b158015610f5d57600080fd5b505af1158015610f71573d6000803e3d6000fd5b50505050505050565b60405163973d02cb60e01b815260206004820152601060248201526f5761697420666f722067656e6573697360801b60448201526064016103a5565b600181015460ff166000816002811115610fd257610fd2611ebb565b0361101b5760405162461bcd60e51b815260206004820152601960248201527811d95b995cda5cd31a588e881b9bdd08199a5b985b1a5e9959603a1b60448201526064016103a5565b600281600281111561102f5761102f611ebb565b0361107c5760405162461bcd60e51b815260206004820152601b60248201527f47656e657369734c69623a20616c726561647920656e61626c6564000000000060448201526064016103a5565b50600101805460ff19166002179055565b609754604051633651bb1d60e01b81526001600160a01b0390911690633651bb1d906110bf9085908590600401611ea2565b600060405180830381600087803b1580156110d957600080fd5b505af11580156110ed573d6000803e3d6000fd5b5050505061053982611598565b609754609854604051633b61c5a760e21b81526000926001600160a01b03169163ed87169c9161112e918691600401611ea2565b602060405180830381865afa15801561114b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116f9190611d30565b905060006064611180603284611f21565b61118a9190611f38565b609754604051638028a6db60e01b81529192506001600160a01b031690638028a6db906111bd9086908590600401611ea2565b600060405180830381600087803b1580156111d757600080fd5b505af11580156111eb573d6000803e3d6000fd5b50505050610cdd83611598565b600054610100900460ff1661121f5760405162461bcd60e51b81526004016103a590611f5a565b609780546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166112685760405162461bcd60e51b81526004016103a590611f5a565b6105aa611661565b6112786118ca565b60cb5460d0546040516bffffffffffffffffffffffff19606086811b8216602084015230901b1660348201524660488201526001600160a01b039092169163a850a90991906068016040516020818303038152906040526040518363ffffffff1660e01b81526004016112ec929190611fa5565b6040805180830381865afa158015611308573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061132c9190611fbe565b92915050565b6000611387826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166116919092919063ffffffff16565b90508051600014806113a85750808060200190518101906113a8919061203e565b610cdd5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016103a5565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000805b600183015460ff16600281111561147657611476611ebb565b1492915050565b6000600184015460ff16600281111561149857611498611ebb565b146114a5576114a5612059565b6001600160a01b0382166000908152600284016020526040812054908190036115425783546114d590600161206f565b6001600160a01b03848116600081815260028881016020908152604080842087905580518082019091529384528381018881528a5460018082018d558c86529290942094519390920290930180546001600160a01b03191692909416919091178355519101559050610592565b60008461154f81866116a8565b8154811061155f5761155f611d49565b9060005260206000209060020201905082816001016000828254611583919061206f565b90915550505050505050565b6000600261145d565b609754609854604051633b61c5a760e21b81526001600160a01b039092169163ed87169c916115cc91859190600401611ea2565b602060405180830381865afa1580156115e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160d9190611d30565b600003610623576001600160a01b038116600081815260d46020526040808220600501805461ff0019169055517f23d934bfe7f1275bc6fd70432159c9cc1c0075d069f89da6a40f43bfe7a94ed39190a250565b600054610100900460ff166116885760405162461bcd60e51b81526004016103a590611f5a565b6105aa33610d31565b60606116a084846000856116e5565b949350505050565b6001600160a01b0381166000908152600283016020526040812054908190036116d3576116d3612059565b6116de600182612082565b9392505050565b6060824710156117465760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016103a5565b600080866001600160a01b031685876040516117629190611dfa565b60006040518083038185875af1925050503d806000811461179f576040519150601f19603f3d011682016040523d82523d6000602084013e6117a4565b606091505b50915091506117b5878383876117c0565b979650505050505050565b6060831561182f578251600003611828576001600160a01b0385163b6118285760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103a5565b50816116a0565b6116a083838151156118445781518083602001fd5b8060405162461bcd60e51b81526004016103a59190612095565b60405180608001604052806118716118e8565b81526000602082018190526040820181905260609091015290565b82600481019282156118ba579160200282015b828111156118ba57823582559160200191906001019061189f565b506118c6929150611906565b5090565b60405180604001604052806002906020820280368337509192915050565b60405180608001604052806004906020820280368337509192915050565b5b808211156118c65760008155600101611907565b6001600160a01b038116811461062357600080fd5b60006020828403121561194257600080fd5b81356116de8161191b565b815160e08201908260005b6004811015611977578251825260209283019290910190600101611958565b505050602083015160808301526040830151151560a0830152606090920151151560c09091015290565b60008060c083850312156119b457600080fd5b60408301848111156119c557600080fd5b8392508460c0850111156119d857600080fd5b809150509250929050565b6000602082840312156119f557600080fd5b5035919050565b60008060208385031215611a0f57600080fd5b823567ffffffffffffffff80821115611a2757600080fd5b818501915085601f830112611a3b57600080fd5b813581811115611a4a57600080fd5b8660208260051b8501011115611a5f57600080fd5b60209290920196919550909350505050565b60008060408385031215611a8457600080fd5b8235611a8f8161191b565b946020939093013593505050565b6001600160a01b0391909116815260200190565b602080825282518282018190526000919060409081850190868401855b82811015611afc57815180516001600160a01b03168552860151868501529284019290850190600101611ace565b5091979650505050505050565b60008060008060608587031215611b1f57600080fd5b843593506020850135611b318161191b565b9250604085013567ffffffffffffffff80821115611b4e57600080fd5b818701915087601f830112611b6257600080fd5b813581811115611b7157600080fd5b886020828501011115611b8357600080fd5b95989497505060200194505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715611bd157611bd1611b92565b604052919050565b600080600080600080600060e0888a031215611bf457600080fd5b8735611bff8161191b565b9650602088810135611c108161191b565b96506040890135611c208161191b565b95506060890135611c308161191b565b94506080890135611c408161191b565b935060a0890135611c508161191b565b925060c089013567ffffffffffffffff80821115611c6d57600080fd5b818b0191508b601f830112611c8157600080fd5b813581811115611c9357611c93611b92565b611ca5601f8201601f19168501611ba8565b91508082528c84828501011115611cbb57600080fd5b808484018584013760008482840101525080935050505092959891949750929550565b60808181019083833792915050565b60208082526023908201527f53757065726e65744d616e616765723a204f4e4c595f5354414b455f4d414e4160408201526223a2a960e91b606082015260800190565b600060208284031215611d4257600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201611d8757611d87611d5f565b5060010190565b60008085851115611d9e57600080fd5b83861115611dab57600080fd5b5050820193919092039150565b8035602083101561132c57600019602084900360031b1b1692915050565b60005b83811015611df1578181015183820152602001611dd9565b50506000910152565b60008251611e0c818460208701611dd6565b9190910192915050565b61010081016040858337608084604084013760c082018360005b6002811015611e4f578151835260209283019290910190600101611e30565b505050949350505050565b80518015158114611e6a57600080fd5b919050565b60008060408385031215611e8257600080fd5b611e8b83611e5a565b9150611e9960208401611e5a565b90509250929050565b6001600160a01b03929092168252602082015260400190565b634e487b7160e01b600052602160045260246000fd5b60008151808452611ee9816020860160208601611dd6565b601f01601f19169290920160200192915050565b6001600160a01b03831681526040602082018190526000906116a090830184611ed1565b808202811582820484141761132c5761132c611d5f565b600082611f5557634e487b7160e01b600052601260045260246000fd5b500490565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8281526040602082015260006116a06040830184611ed1565b600060408284031215611fd057600080fd5b82601f830112611fdf57600080fd5b6040516040810181811067ffffffffffffffff8211171561200257612002611b92565b806040525080604084018581111561201957600080fd5b845b8181101561203357805183526020928301920161201b565b509195945050505050565b60006020828403121561205057600080fd5b6116de82611e5a565b634e487b7160e01b600052600160045260246000fd5b8082018082111561132c5761132c611d5f565b8181038181111561132c5761132c611d5f565b6020815260006116de6020830184611ed156fea2646970667358221220bc982b5eb2308e71d272d016ed22be05a9dcf98b734fd3bd0b62563ec962766664736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var StakeManagerArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"StakeManager\",\n \"sourceName\": \"contracts/root/staking/StakeManager.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"manager\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"ChildManagerRegistered\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"StakeAdded\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"StakeRemoved\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"recipient\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"StakeWithdrawn\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"ValidatorSlashed\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"manager\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"idFor\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newMatic\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"managerOf\",\n \"outputs\": [\n {\n \"internalType\": \"contract ISupernetManager\",\n \"name\": \"manager\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"manager\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"registerChildChain\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"releaseStakeOf\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"slashStakeOf\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"stakeFor\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"stakeOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalStake\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"totalStakeOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"totalStakeOfChild\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"withdrawStake\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"withdrawableStake\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610f7d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100bf5760003560e01c8063c60662721161007c578063c606627214610140578063c73a7a1f14610153578063d5364bbf14610166578063d7fbee3d14610179578063e3f56eaa146101a4578063ed87169c146101b7578063f90423fe146101ca57600080fd5b80633651bb1d146100c457806339ed8c90146100d95780638028a6db146100ff5780638b0e9f3f14610112578063b64ddbf61461011a578063c4d66de81461012d575b600080fd5b6100d76100d2366004610ddd565b6101dd565b005b6100ec6100e7366004610e07565b610240565b6040519081526020015b60405180910390f35b6100d761010d366004610ddd565b610256565b6004546100ec565b6100ec610128366004610e20565b610323565b6100d761013b366004610e20565b610431565b6100d761014e366004610ddd565b61055d565b6100d7610161366004610e3b565b610568565b6100ec610174366004610e20565b61068d565b61018c610187366004610e07565b6106ab565b6040516001600160a01b0390911681526020016100f6565b6100ec6101b2366004610e20565b6106b8565b6100ec6101c5366004610ddd565b6106d6565b6100ec6101d8366004610e20565b610702565b60006101e833610702565b90506101f7600484838561070f565b826001600160a01b0316817fcbc2141407acdf7a77731afda2c1369f3c46e04194b90a9d527385c17608eb0d8460405161023391815260200190565b60405180910390a3505050565b6000818152600660205260408120545b92915050565b600061026133610702565b9050600061026f84836106d6565b90508083111561027d578092505b61028a600485848461070f565b6102958433856107eb565b836001600160a01b0316827fcbc2141407acdf7a77731afda2c1369f3c46e04194b90a9d527385c17608eb0d836040516102d191815260200190565b60405180910390a3836001600160a01b0316827fff61f9c95b299671af1bb01c9888e344ed74c6fdff2b1c98eeed2be18714aac08560405161031591815260200190565b60405180910390a350505050565b6001600160a01b0381166000908152600360205260408120541561038e5760405162461bcd60e51b815260206004820152601c60248201527f5374616b654d616e616765723a2049445f414c52454144595f5345540000000060448201526064015b60405180910390fd5b610399600183610859565b604051630d12979960e21b8152600481018290529091506001600160a01b0383169063344a5e6490602401600060405180830381600087803b1580156103de57600080fd5b505af11580156103f2573d6000803e3d6000fd5b50506040516001600160a01b03851692508391507f64566eaf28160aee8cce7464dbf8eb54939f81ac929a8ebeea66865ff57963c490600090a3919050565b600054610100900460ff16158080156104515750600054600160ff909116105b8061046b5750303b15801561046b575060005460ff166001145b6104ce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610385565b6000805460ff1916600117905580156104f1576000805461ff0019166101001790555b6000805462010000600160b01b031916620100006001600160a01b038516021790558015610559576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6105593383836107eb565b811580159061057957506001548211155b6105c05760405162461bcd60e51b815260206004820152601860248201527714dd185ad953585b9859d95c8e881253959053125117d25160421b6044820152606401610385565b6000546105de906201000090046001600160a01b031633308461090e565b6105eb600433848461097f565b60006105f6836106ab565b6040516323021ec760e21b8152336004820152602481018490529091506001600160a01b03821690638c087b1c90604401600060405180830381600087803b15801561064157600080fd5b505af1158015610655573d6000803e3d6000fd5b50506040518481523392508591507fc1d3c31619aec7561f6fa519052617aed252a25edaddc5d7428681180516837a90602001610233565b6001600160a01b038116600090815260086020526040812054610250565b6000610250600183610a21565b6001600160a01b038116600090815260076020526040812054610250565b6001600160a01b03821660009081526005602090815260408083208484529091528120545b9392505050565b6000610250600183610a88565b6001600160a01b0383166000908152600185016020908152604080832085845290915281208054839290610744908490610e73565b9091555050600082815260028501602052604081208054839290610769908490610e73565b90915550506001600160a01b038316600090815260038501602052604081208054839290610798908490610e73565b90915550508354819085906000906107b1908490610e73565b90915550506001600160a01b0383166000908152600485016020526040812080548392906107e0908490610e86565b909155505050505050565b6107f760048483610af3565b600054610814906201000090046001600160a01b03168383610b27565b816001600160a01b0316836001600160a01b03167fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda38360405161023391815260200190565b60006001600160a01b0382166108b15760405162461bcd60e51b815260206004820181905260248201527f4368696c644d616e616765724c69623a20494e56414c49445f414444524553536044820152606401610385565b82600001600081546108c290610e99565b91829055506000818152600185016020908152604080832080546001600160a01b039097166001600160a01b031990971687179055948252600290950190945291909220819055919050565b6040516001600160a01b03808516602483015283166044820152606481018290526109799085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610b5c565b50505050565b6001600160a01b03831660009081526001850160209081526040808320858452909152812080548392906109b4908490610e86565b90915550506000828152600285016020526040812080548392906109d9908490610e86565b90915550506001600160a01b038316600090815260038501602052604081208054839290610a08908490610e86565b90915550508354819085906000906107e0908490610e86565b60008181526001830160205260409020546001600160a01b0316806102505760405162461bcd60e51b815260206004820152601b60248201527f4368696c644d616e616765724c69623a20494e56414c49445f494400000000006044820152606401610385565b6001600160a01b0381166000908152600283016020526040812054908190036102505760405162461bcd60e51b815260206004820181905260248201527f4368696c644d616e616765724c69623a20494e56414c49445f4d414e414745526044820152606401610385565b6001600160a01b038216600090815260048401602052604081208054839290610b1d908490610e73565b9091555050505050565b6040516001600160a01b038316602482015260448101829052610b5790849063a9059cbb60e01b90606401610942565b505050565b6000610bb1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610c319092919063ffffffff16565b9050805160001480610bd2575080806020019051810190610bd29190610eb2565b610b575760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610385565b6060610c408484600085610c48565b949350505050565b606082471015610ca95760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610385565b600080866001600160a01b03168587604051610cc59190610ef8565b60006040518083038185875af1925050503d8060008114610d02576040519150601f19603f3d011682016040523d82523d6000602084013e610d07565b606091505b5091509150610d1887838387610d23565b979650505050505050565b60608315610d92578251600003610d8b576001600160a01b0385163b610d8b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610385565b5081610c40565b610c408383815115610da75781518083602001fd5b8060405162461bcd60e51b81526004016103859190610f14565b80356001600160a01b0381168114610dd857600080fd5b919050565b60008060408385031215610df057600080fd5b610df983610dc1565b946020939093013593505050565b600060208284031215610e1957600080fd5b5035919050565b600060208284031215610e3257600080fd5b6106fb82610dc1565b60008060408385031215610e4e57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b8181038181111561025057610250610e5d565b8082018082111561025057610250610e5d565b600060018201610eab57610eab610e5d565b5060010190565b600060208284031215610ec457600080fd5b815180151581146106fb57600080fd5b60005b83811015610eef578181015183820152602001610ed7565b50506000910152565b60008251610f0a818460208701610ed4565b9190910192915050565b6020815260008251806020840152610f33816040850160208701610ed4565b601f01601f1916919091016040019291505056fea264697066735822122023b0a75ec2b5e9f66ad966a88679ad7eee0eb952b3bfc7f6dbd5b2adfa2ee0c164736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106100bf5760003560e01c8063c60662721161007c578063c606627214610140578063c73a7a1f14610153578063d5364bbf14610166578063d7fbee3d14610179578063e3f56eaa146101a4578063ed87169c146101b7578063f90423fe146101ca57600080fd5b80633651bb1d146100c457806339ed8c90146100d95780638028a6db146100ff5780638b0e9f3f14610112578063b64ddbf61461011a578063c4d66de81461012d575b600080fd5b6100d76100d2366004610ddd565b6101dd565b005b6100ec6100e7366004610e07565b610240565b6040519081526020015b60405180910390f35b6100d761010d366004610ddd565b610256565b6004546100ec565b6100ec610128366004610e20565b610323565b6100d761013b366004610e20565b610431565b6100d761014e366004610ddd565b61055d565b6100d7610161366004610e3b565b610568565b6100ec610174366004610e20565b61068d565b61018c610187366004610e07565b6106ab565b6040516001600160a01b0390911681526020016100f6565b6100ec6101b2366004610e20565b6106b8565b6100ec6101c5366004610ddd565b6106d6565b6100ec6101d8366004610e20565b610702565b60006101e833610702565b90506101f7600484838561070f565b826001600160a01b0316817fcbc2141407acdf7a77731afda2c1369f3c46e04194b90a9d527385c17608eb0d8460405161023391815260200190565b60405180910390a3505050565b6000818152600660205260408120545b92915050565b600061026133610702565b9050600061026f84836106d6565b90508083111561027d578092505b61028a600485848461070f565b6102958433856107eb565b836001600160a01b0316827fcbc2141407acdf7a77731afda2c1369f3c46e04194b90a9d527385c17608eb0d836040516102d191815260200190565b60405180910390a3836001600160a01b0316827fff61f9c95b299671af1bb01c9888e344ed74c6fdff2b1c98eeed2be18714aac08560405161031591815260200190565b60405180910390a350505050565b6001600160a01b0381166000908152600360205260408120541561038e5760405162461bcd60e51b815260206004820152601c60248201527f5374616b654d616e616765723a2049445f414c52454144595f5345540000000060448201526064015b60405180910390fd5b610399600183610859565b604051630d12979960e21b8152600481018290529091506001600160a01b0383169063344a5e6490602401600060405180830381600087803b1580156103de57600080fd5b505af11580156103f2573d6000803e3d6000fd5b50506040516001600160a01b03851692508391507f64566eaf28160aee8cce7464dbf8eb54939f81ac929a8ebeea66865ff57963c490600090a3919050565b600054610100900460ff16158080156104515750600054600160ff909116105b8061046b5750303b15801561046b575060005460ff166001145b6104ce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610385565b6000805460ff1916600117905580156104f1576000805461ff0019166101001790555b6000805462010000600160b01b031916620100006001600160a01b038516021790558015610559576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6105593383836107eb565b811580159061057957506001548211155b6105c05760405162461bcd60e51b815260206004820152601860248201527714dd185ad953585b9859d95c8e881253959053125117d25160421b6044820152606401610385565b6000546105de906201000090046001600160a01b031633308461090e565b6105eb600433848461097f565b60006105f6836106ab565b6040516323021ec760e21b8152336004820152602481018490529091506001600160a01b03821690638c087b1c90604401600060405180830381600087803b15801561064157600080fd5b505af1158015610655573d6000803e3d6000fd5b50506040518481523392508591507fc1d3c31619aec7561f6fa519052617aed252a25edaddc5d7428681180516837a90602001610233565b6001600160a01b038116600090815260086020526040812054610250565b6000610250600183610a21565b6001600160a01b038116600090815260076020526040812054610250565b6001600160a01b03821660009081526005602090815260408083208484529091528120545b9392505050565b6000610250600183610a88565b6001600160a01b0383166000908152600185016020908152604080832085845290915281208054839290610744908490610e73565b9091555050600082815260028501602052604081208054839290610769908490610e73565b90915550506001600160a01b038316600090815260038501602052604081208054839290610798908490610e73565b90915550508354819085906000906107b1908490610e73565b90915550506001600160a01b0383166000908152600485016020526040812080548392906107e0908490610e86565b909155505050505050565b6107f760048483610af3565b600054610814906201000090046001600160a01b03168383610b27565b816001600160a01b0316836001600160a01b03167fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda38360405161023391815260200190565b60006001600160a01b0382166108b15760405162461bcd60e51b815260206004820181905260248201527f4368696c644d616e616765724c69623a20494e56414c49445f414444524553536044820152606401610385565b82600001600081546108c290610e99565b91829055506000818152600185016020908152604080832080546001600160a01b039097166001600160a01b031990971687179055948252600290950190945291909220819055919050565b6040516001600160a01b03808516602483015283166044820152606481018290526109799085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610b5c565b50505050565b6001600160a01b03831660009081526001850160209081526040808320858452909152812080548392906109b4908490610e86565b90915550506000828152600285016020526040812080548392906109d9908490610e86565b90915550506001600160a01b038316600090815260038501602052604081208054839290610a08908490610e86565b90915550508354819085906000906107e0908490610e86565b60008181526001830160205260409020546001600160a01b0316806102505760405162461bcd60e51b815260206004820152601b60248201527f4368696c644d616e616765724c69623a20494e56414c49445f494400000000006044820152606401610385565b6001600160a01b0381166000908152600283016020526040812054908190036102505760405162461bcd60e51b815260206004820181905260248201527f4368696c644d616e616765724c69623a20494e56414c49445f4d414e414745526044820152606401610385565b6001600160a01b038216600090815260048401602052604081208054839290610b1d908490610e73565b9091555050505050565b6040516001600160a01b038316602482015260448101829052610b5790849063a9059cbb60e01b90606401610942565b505050565b6000610bb1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610c319092919063ffffffff16565b9050805160001480610bd2575080806020019051810190610bd29190610eb2565b610b575760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610385565b6060610c408484600085610c48565b949350505050565b606082471015610ca95760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610385565b600080866001600160a01b03168587604051610cc59190610ef8565b60006040518083038185875af1925050503d8060008114610d02576040519150601f19603f3d011682016040523d82523d6000602084013e610d07565b606091505b5091509150610d1887838387610d23565b979650505050505050565b60608315610d92578251600003610d8b576001600160a01b0385163b610d8b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610385565b5081610c40565b610c408383815115610da75781518083602001fd5b8060405162461bcd60e51b81526004016103859190610f14565b80356001600160a01b0381168114610dd857600080fd5b919050565b60008060408385031215610df057600080fd5b610df983610dc1565b946020939093013593505050565b600060208284031215610e1957600080fd5b5035919050565b600060208284031215610e3257600080fd5b6106fb82610dc1565b60008060408385031215610e4e57600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b8181038181111561025057610250610e5d565b8082018082111561025057610250610e5d565b600060018201610eab57610eab610e5d565b5060010190565b600060208284031215610ec457600080fd5b815180151581146106fb57600080fd5b60005b83811015610eef578181015183820152602001610ed7565b50506000910152565b60008251610f0a818460208701610ed4565b9190910192915050565b6020815260008251806020840152610f33816040850160208701610ed4565b601f01601f1916919091016040019291505056fea264697066735822122023b0a75ec2b5e9f66ad966a88679ad7eee0eb952b3bfc7f6dbd5b2adfa2ee0c164736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var RewardPoolArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"RewardPool\",\n \"sourceName\": \"contracts/child/validator/RewardPool.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"epochId\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"totalReward\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"RewardDistributed\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"baseReward\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochId\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"validator\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"signedBlocks\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct Uptime[]\",\n \"name\": \"uptime\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"distributeRewardFor\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newRewardToken\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRewardWallet\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newValidatorSet\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"newBaseReward\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"paidRewardPerEpoch\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"pendingRewards\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rewardToken\",\n \"outputs\": [\n {\n \"internalType\": \"contract IERC20Upgradeable\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"rewardWallet\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"validatorSet\",\n \"outputs\": [\n {\n \"internalType\": \"contract IValidatorSet\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"withdrawReward\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610ee1806100206000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c80638a9cd82d116100a2578063c885bc5811610071578063c885bc581461020f578063cf756fdf14610217578063e0563ab11461022a578063f7c618c114610233578063fb75b2c71461024c57600080fd5b80638a9cd82d146101d45780639426e226146101e9578063947287cf146101fc57806397e5230d1461020557600080fd5b80633b878c22116100e95780633b878c221461019d57806351351d53146101a657806355b01e4d146101b45780635ea5df79146101c257806376ad03bc146101cb57600080fd5b806307358b991461011b57806307b3e2521461014e578063284017f51461017457806331d7a2621461017d575b600080fd5b61013b610129366004610be0565b60366020526000908152604090205481565b6040519081526020015b60405180910390f35b61015c6004600360981b0181565b6040516001600160a01b039091168152602001610145565b61015c61202081565b61013b61018b366004610c15565b60376020526000908152604090205481565b61015c61101081565b61015c6002600160a01b0381565b61015c6004600160991b0181565b61013b61138881565b61013b60355481565b6101e76101e2366004610c37565b61025f565b005b60345461015c906001600160a01b031681565b61013b61520881565b61013b620249f081565b6101e76106a9565b6101e7610225366004610cb6565b6106df565b61015c61203081565b60325461015c906201000090046001600160a01b031681565b60335461015c906001600160a01b031681565b336002600160a01b03146102a85760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064015b60405180910390fd5b600083815260366020526040902054156103045760405162461bcd60e51b815260206004820152601a60248201527f5245574152445f414c52454144595f4449535452494255544544000000000000604482015260640161029f565b603454604051633f490b0560e21b8152600481018590526000916001600160a01b03169063fd242c1490602401602060405180830381865afa15801561034e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103729190610d01565b9050806000036103ba5760405162461bcd60e51b8152602060048201526013602482015272115413d0d217d393d517d0d3d3535255151151606a1b604482015260640161029f565b60345460408051636265600360e01b815290516000926001600160a01b03169163626560039160048083019260209291908290030181865afa158015610404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104289190610d01565b90506000818360355461043b9190610d30565b6104459190610d4d565b603454604051630981b24d60e41b8152600481018990529192506000916001600160a01b039091169063981b24d090602401602060405180830381865afa158015610494573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b89190610d01565b9050846000805b828110156106495760008989838181106104db576104db610d6f565b9050604002018036038101906104f19190610d85565b905087816020015111156105475760405162461bcd60e51b815260206004820152601b60248201527f5349474e45445f424c4f434b535f455843454544535f544f54414c0000000000604482015260640161029f565b603454815160405163277166bf60e11b81526001600160a01b039182166004820152602481018e90526000929190911690634ee2cd7e90604401602060405180830381865afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c29190610d01565b905060006105d08a88610d30565b60208401516105df848b610d30565b6105e99190610d30565b6105f39190610d4d565b83516001600160a01b0316600090815260376020526040812080549293508392909190610621908490610dea565b9091555061063190508186610dea565b9450505050808061064190610dfd565b9150506104bf565b506000898152603660205260409020819055610664816108b1565b887feaf3d57629d9b1ce95715ccd98d6f5bf48023be1d5a06e09f64ab7f6d8be01d58260405161069691815260200190565b60405180910390a2505050505050505050565b336000818152603760205260408120805491905560325490916106dc916201000090046001600160a01b031690836108d5565b50565b603254610100900460ff16158080156106ff5750603254600160ff909116105b806107195750303b158015610719575060325460ff166001145b61077c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161029f565b6032805460ff19166001179055801561079f576032805461ff0019166101001790555b6001600160a01b038516158015906107bf57506001600160a01b03841615155b80156107d357506001600160a01b03831615155b61080e5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b604482015260640161029f565b603280546001600160a01b03808816620100000262010000600160b01b031990921691909117909155603380548683166001600160a01b0319918216179091556034805492861692909116919091179055603582905580156108aa576032805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6033546032546106dc916001600160a01b036201000090920482169116308461093d565b6040516001600160a01b03831660248201526044810182905261093890849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261097b565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526109759085906323b872dd60e01b90608401610901565b50505050565b60006109d0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610a509092919063ffffffff16565b90508051600014806109f15750808060200190518101906109f19190610e16565b6109385760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161029f565b6060610a5f8484600085610a67565b949350505050565b606082471015610ac85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161029f565b600080866001600160a01b03168587604051610ae49190610e5c565b60006040518083038185875af1925050503d8060008114610b21576040519150601f19603f3d011682016040523d82523d6000602084013e610b26565b606091505b5091509150610b3787838387610b42565b979650505050505050565b60608315610bb1578251600003610baa576001600160a01b0385163b610baa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161029f565b5081610a5f565b610a5f8383815115610bc65781518083602001fd5b8060405162461bcd60e51b815260040161029f9190610e78565b600060208284031215610bf257600080fd5b5035919050565b80356001600160a01b0381168114610c1057600080fd5b919050565b600060208284031215610c2757600080fd5b610c3082610bf9565b9392505050565b600080600060408486031215610c4c57600080fd5b83359250602084013567ffffffffffffffff80821115610c6b57600080fd5b818601915086601f830112610c7f57600080fd5b813581811115610c8e57600080fd5b8760208260061b8501011115610ca357600080fd5b6020830194508093505050509250925092565b60008060008060808587031215610ccc57600080fd5b610cd585610bf9565b9350610ce360208601610bf9565b9250610cf160408601610bf9565b9396929550929360600135925050565b600060208284031215610d1357600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d4757610d47610d1a565b92915050565b600082610d6a57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060408284031215610d9757600080fd5b6040516040810181811067ffffffffffffffff82111715610dc857634e487b7160e01b600052604160045260246000fd5b604052610dd483610bf9565b8152602083013560208201528091505092915050565b80820180821115610d4757610d47610d1a565b600060018201610e0f57610e0f610d1a565b5060010190565b600060208284031215610e2857600080fd5b81518015158114610c3057600080fd5b60005b83811015610e53578181015183820152602001610e3b565b50506000910152565b60008251610e6e818460208701610e38565b9190910192915050565b6020815260008251806020840152610e97816040850160208701610e38565b601f01601f1916919091016040019291505056fea2646970667358221220d9d5cb95a8c6f1edeb2b53a8eebe52a4d92f5c1ea3f95d4f766548e10cc60cb464736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106101165760003560e01c80638a9cd82d116100a2578063c885bc5811610071578063c885bc581461020f578063cf756fdf14610217578063e0563ab11461022a578063f7c618c114610233578063fb75b2c71461024c57600080fd5b80638a9cd82d146101d45780639426e226146101e9578063947287cf146101fc57806397e5230d1461020557600080fd5b80633b878c22116100e95780633b878c221461019d57806351351d53146101a657806355b01e4d146101b45780635ea5df79146101c257806376ad03bc146101cb57600080fd5b806307358b991461011b57806307b3e2521461014e578063284017f51461017457806331d7a2621461017d575b600080fd5b61013b610129366004610be0565b60366020526000908152604090205481565b6040519081526020015b60405180910390f35b61015c6004600360981b0181565b6040516001600160a01b039091168152602001610145565b61015c61202081565b61013b61018b366004610c15565b60376020526000908152604090205481565b61015c61101081565b61015c6002600160a01b0381565b61015c6004600160991b0181565b61013b61138881565b61013b60355481565b6101e76101e2366004610c37565b61025f565b005b60345461015c906001600160a01b031681565b61013b61520881565b61013b620249f081565b6101e76106a9565b6101e7610225366004610cb6565b6106df565b61015c61203081565b60325461015c906201000090046001600160a01b031681565b60335461015c906001600160a01b031681565b336002600160a01b03146102a85760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064015b60405180910390fd5b600083815260366020526040902054156103045760405162461bcd60e51b815260206004820152601a60248201527f5245574152445f414c52454144595f4449535452494255544544000000000000604482015260640161029f565b603454604051633f490b0560e21b8152600481018590526000916001600160a01b03169063fd242c1490602401602060405180830381865afa15801561034e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103729190610d01565b9050806000036103ba5760405162461bcd60e51b8152602060048201526013602482015272115413d0d217d393d517d0d3d3535255151151606a1b604482015260640161029f565b60345460408051636265600360e01b815290516000926001600160a01b03169163626560039160048083019260209291908290030181865afa158015610404573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104289190610d01565b90506000818360355461043b9190610d30565b6104459190610d4d565b603454604051630981b24d60e41b8152600481018990529192506000916001600160a01b039091169063981b24d090602401602060405180830381865afa158015610494573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104b89190610d01565b9050846000805b828110156106495760008989838181106104db576104db610d6f565b9050604002018036038101906104f19190610d85565b905087816020015111156105475760405162461bcd60e51b815260206004820152601b60248201527f5349474e45445f424c4f434b535f455843454544535f544f54414c0000000000604482015260640161029f565b603454815160405163277166bf60e11b81526001600160a01b039182166004820152602481018e90526000929190911690634ee2cd7e90604401602060405180830381865afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c29190610d01565b905060006105d08a88610d30565b60208401516105df848b610d30565b6105e99190610d30565b6105f39190610d4d565b83516001600160a01b0316600090815260376020526040812080549293508392909190610621908490610dea565b9091555061063190508186610dea565b9450505050808061064190610dfd565b9150506104bf565b506000898152603660205260409020819055610664816108b1565b887feaf3d57629d9b1ce95715ccd98d6f5bf48023be1d5a06e09f64ab7f6d8be01d58260405161069691815260200190565b60405180910390a2505050505050505050565b336000818152603760205260408120805491905560325490916106dc916201000090046001600160a01b031690836108d5565b50565b603254610100900460ff16158080156106ff5750603254600160ff909116105b806107195750303b158015610719575060325460ff166001145b61077c5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161029f565b6032805460ff19166001179055801561079f576032805461ff0019166101001790555b6001600160a01b038516158015906107bf57506001600160a01b03841615155b80156107d357506001600160a01b03831615155b61080e5760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b604482015260640161029f565b603280546001600160a01b03808816620100000262010000600160b01b031990921691909117909155603380548683166001600160a01b0319918216179091556034805492861692909116919091179055603582905580156108aa576032805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050565b6033546032546106dc916001600160a01b036201000090920482169116308461093d565b6040516001600160a01b03831660248201526044810182905261093890849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261097b565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526109759085906323b872dd60e01b90608401610901565b50505050565b60006109d0826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610a509092919063ffffffff16565b90508051600014806109f15750808060200190518101906109f19190610e16565b6109385760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840161029f565b6060610a5f8484600085610a67565b949350505050565b606082471015610ac85760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840161029f565b600080866001600160a01b03168587604051610ae49190610e5c565b60006040518083038185875af1925050503d8060008114610b21576040519150601f19603f3d011682016040523d82523d6000602084013e610b26565b606091505b5091509150610b3787838387610b42565b979650505050505050565b60608315610bb1578251600003610baa576001600160a01b0385163b610baa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161029f565b5081610a5f565b610a5f8383815115610bc65781518083602001fd5b8060405162461bcd60e51b815260040161029f9190610e78565b600060208284031215610bf257600080fd5b5035919050565b80356001600160a01b0381168114610c1057600080fd5b919050565b600060208284031215610c2757600080fd5b610c3082610bf9565b9392505050565b600080600060408486031215610c4c57600080fd5b83359250602084013567ffffffffffffffff80821115610c6b57600080fd5b818601915086601f830112610c7f57600080fd5b813581811115610c8e57600080fd5b8760208260061b8501011115610ca357600080fd5b6020830194508093505050509250925092565b60008060008060808587031215610ccc57600080fd5b610cd585610bf9565b9350610ce360208601610bf9565b9250610cf160408601610bf9565b9396929550929360600135925050565b600060208284031215610d1357600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610d4757610d47610d1a565b92915050565b600082610d6a57634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603260045260246000fd5b600060408284031215610d9757600080fd5b6040516040810181811067ffffffffffffffff82111715610dc857634e487b7160e01b600052604160045260246000fd5b604052610dd483610bf9565b8152602083013560208201528091505092915050565b80820180821115610d4757610d47610d1a565b600060018201610e0f57610e0f610d1a565b5060010190565b600060208284031215610e2857600080fd5b81518015158114610c3057600080fd5b60005b83811015610e53578181015183820152602001610e3b565b50506000910152565b60008251610e6e818460208701610e38565b9190910192915050565b6020815260008251806020840152610e97816040850160208701610e38565b601f01601f1916919091016040019291505056fea2646970667358221220d9d5cb95a8c6f1edeb2b53a8eebe52a4d92f5c1ea3f95d4f766548e10cc60cb464736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var ValidatorSetArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"ValidatorSet\",\n \"sourceName\": \"contracts/child/validator/ValidatorSet.sol\",\n \"abi\": [\n {\n \"inputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"only\",\n \"type\": \"string\"\n }\n ],\n \"name\": \"Unauthorized\",\n \"type\": \"error\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Approval\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"startBlock\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"endBlock\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"bytes32\",\n \"name\": \"epochRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"name\": \"NewEpoch\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"uint256\",\n \"name\": \"validator\",\n \"type\": \"uint256\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Slashed\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Snapshot\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"value\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Transfer\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"Withdrawal\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"WithdrawalRegistered\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"ALLOWLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"BLOCKLIST_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"EPOCH_SIZE\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TOKEN_CONTRACT\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"NATIVE_TRANSFER_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"READ_ADDRESSLIST_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"SYSTEM\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"VALIDATOR_PKCHECK_PRECOMPILE_GAS\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"WITHDRAWAL_WAIT_PERIOD\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"owner\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"allowance\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"approve\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"balanceOf\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochNumber\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"balanceOfAt\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"id\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"epochRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"internalType\": \"struct Epoch\",\n \"name\": \"epoch\",\n \"type\": \"tuple\"\n }\n ],\n \"name\": \"commitEpoch\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"currentEpochId\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"decimals\",\n \"outputs\": [\n {\n \"internalType\": \"uint8\",\n \"name\": \"\",\n \"type\": \"uint8\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"subtractedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"decreaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"epochEndBlocks\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"epochs\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"startBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"endBlock\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"bytes32\",\n \"name\": \"epochRoot\",\n \"type\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"spender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"addedValue\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"increaseAllowance\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"newStateSender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newStateReceiver\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newRootChainManager\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"newEpochSize\",\n \"type\": \"uint256\"\n },\n {\n \"components\": [\n {\n \"internalType\": \"address\",\n \"name\": \"addr\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"stake\",\n \"type\": \"uint256\"\n }\n ],\n \"internalType\": \"struct ValidatorInit[]\",\n \"name\": \"initialValidators\",\n \"type\": \"tuple[]\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"name\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"sender\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"bytes\",\n \"name\": \"data\",\n \"type\": \"bytes\"\n }\n ],\n \"name\": \"onStateReceive\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"pendingWithdrawals\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"symbol\",\n \"outputs\": [\n {\n \"internalType\": \"string\",\n \"name\": \"\",\n \"type\": \"string\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochId\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"totalBlocks\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"length\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"totalSupply\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"epochNumber\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"totalSupplyAt\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transfer\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"from\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"to\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"transferFrom\",\n \"outputs\": [\n {\n \"internalType\": \"bool\",\n \"name\": \"\",\n \"type\": \"bool\"\n }\n ],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"unstake\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"account\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"withdrawable\",\n \"outputs\": [\n {\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50612167806100206000396000f3fe608060405234801561001057600080fd5b50600436106102015760003560e01c806361cc276311610125578063c6b61e4c116100ad578063ea0fee4f1161007c578063ea0fee4f1461043d578063eacdc5ff14610445578063eeb499451461044e578063f3f4370314610461578063fd242c141461047457600080fd5b8063c6b61e4c146103c4578063ce513b6f1461040e578063dd62ed3e14610421578063e0563ab11461043457600080fd5b806395d89b41116100f457806395d89b411461037957806397e5230d14610381578063981b24d01461038b578063a457c2d71461039e578063a9059cbb146103b157600080fd5b806361cc276314610341578063626560031461035457806370a082311461035d578063947287cf1461037057600080fd5b8063313ce567116101a85780633fd50001116101775780633fd50001146102f65780634ee2cd7e1461030957806351351d531461031c57806355b01e4d1461032a5780635ea5df791461033857600080fd5b8063313ce567146102c357806339509351146102d25780633b878c22146102e55780633ccfd60b146102ee57600080fd5b806306fdde031461020657806307b3e25214610224578063095ea7b31461024a5780630f50287c1461026d57806318160ddd1461028257806323b872dd14610294578063284017f5146102a75780632e17de78146102b0575b600080fd5b61020e610487565b60405161021b9190611af6565b60405180910390f35b6102326004600360981b0181565b6040516001600160a01b03909116815260200161021b565b61025d610258366004611b1e565b610519565b604051901515815260200161021b565b61028061027b366004611b4a565b610533565b005b6035545b60405190815260200161021b565b61025d6102a2366004611b82565b6107c5565b61023261202081565b6102806102be366004611bc3565b6107e9565b6040516012815260200161021b565b61025d6102e0366004611b1e565b610800565b61023261101081565b610280610822565b610286610304366004611bc3565b610933565b610286610317366004611b1e565b610954565b6102326002600160a01b0381565b6102326004600160991b0181565b61028661138881565b61028061034f366004611c4c565b610967565b61028660cc5481565b61028661036b366004611d65565b610c10565b61028661520881565b61020e610c2b565b610286620249f081565b610286610399366004611bc3565b610c3a565b61025d6103ac366004611b1e565b610c45565b61025d6103bf366004611b1e565b610cc0565b6103f36103d2366004611bc3565b60ce6020526000908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161021b565b61028661041c366004611d65565b610cce565b61028661042f366004611d82565b610cfc565b61023261203081565b610286600181565b61028660cd5481565b61028061045c366004611dbb565b610d27565b61028661046f366004611d65565b610df9565b610286610482366004611bc3565b610e20565b60606036805461049690611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546104c290611e44565b801561050f5780601f106104e45761010080835404028352916020019161050f565b820191906000526020600020905b8154815290600101906020018083116104f257829003601f168201915b5050505050905090565b600033610527818585610e6a565b60019150505b92915050565b336002600160a01b031461057c5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064015b60405180910390fd5b60cd80546000918261058d83611e94565b9190505590508083146105d85760405162461bcd60e51b815260206004820152601360248201527215539156141150d5115117d15413d0d217d251606a1b6044820152606401610573565b81356020830135116106225760405162461bcd60e51b81526020600482015260136024820152721393d7d09313d0d2d4d7d0d3d3535255151151606a1b6044820152606401610573565b60cc5461063483356020850135611ead565b61063f906001611ec0565b6106499190611ee9565b156106a45760405162461bcd60e51b815260206004820152602560248201527f45504f43485f4d5553545f42455f444956495349424c455f42595f45504f43486044820152645f53495a4560d81b6064820152608401610573565b813560ce60006106b5600185611ead565b81526020019081526020016000206001015460016106d39190611ec0565b146107165760405162461bcd60e51b8152602060048201526013602482015272494e56414c49445f53544152545f424c4f434b60681b6044820152606401610573565b600081815260ce60205260409020829061074782828135815560208201356001820155604082013560028201555050565b505060cf80546001810182556000919091526020838101357facb8d954e2cfef495862221e91bd7523613cf8808827cb33edfe4904cc51bf299092018290556040805190850135815284359186917f0ce8712c4dee4bd5a691f0bc1c39594671591e77395f8ebf6a3fb5f63fbea66a910160405180910390a4505050565b6000336107d3858285610f8f565b6107de858585611003565b506001949350505050565b6107f333826111a7565b6107fd33826112d2565b50565b6000336105278185856108138383610cfc565b61081d9190611ec0565b610e6a565b33600090815260d06020526040812060cd54909190819061084490849061134b565b808555604051828152919350915033907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a260c95460cb54604080517f8ca9a95e41b5eece253c93f5b31eed1253aed6b145d8a6e14d913fdf8e7322936020820152338183015260608082018790528251808303909101815260808201928390526316f1983160e01b9092526001600160a01b03938416936316f19831936108fc93911691608401611efd565b600060405180830381600087803b15801561091657600080fd5b505af115801561092a573d6000803e3d6000fd5b50505050505050565b60cf818154811061094357600080fd5b600091825260209091200154905081565b600061096083836113bd565b9392505050565b600054610100900460ff16158080156109875750600054600160ff909116105b806109a15750303b1580156109a1575060005460ff166001145b610a045760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610573565b6000805460ff191660011790558015610a27576000805461ff0019166101001790555b6001600160a01b03861615801590610a4757506001600160a01b03851615155b8015610a5b57506001600160a01b03841615155b8015610a6657508215155b610aa25760405162461bcd60e51b815260206004820152600d60248201526c1253959053125117d253941555609a1b6044820152606401610573565b610aec6040518060400160405280600c81526020016b15985b1a59185d1bdc94d95d60a21b815250604051806040016040528060048152602001631594d15560e21b815250611406565b60c980546001600160a01b038089166001600160a01b03199283161790925560ca805488841690831617905560cb80549287169290911691909117905560cc83905560005b8251811015610b8657610b7e838281518110610b4f57610b4f611f21565b602002602001015160000151848381518110610b6d57610b6d611f21565b60200260200101516020015161143b565b600101610b31565b5060cf80546001818101835560009283527facb8d954e2cfef495862221e91bd7523613cf8808827cb33edfe4904cc51bf299091019190915560cd558015610c08576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6001600160a01b031660009081526033602052604090205490565b60606037805461049690611e44565b600061052d82611445565b60003381610c538286610cfc565b905083811015610cb35760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610573565b6107de8286868403610e6a565b600033610527818585611003565b60cd546001600160a01b038216600090815260d0602052604081209091610cf5919061134b565b5092915050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b60ca546001600160a01b031633148015610d4e575060cb546001600160a01b038481169116145b610d8b5760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a2a72222a960911b6044820152606401610573565b7f1bcc0f4c3fad314e585165815f94ecca9b96690a26d6417d7876448a9a867a69610dba602060008486611f37565b610dc391611f61565b03610df357600080610dd88360208187611f37565b810190610de59190611b1e565b91509150610c08828261143b565b50505050565b60cd546001600160a01b038216600090815260d060205260408120909161052d9190611470565b600081815260ce60205260408120600101548015610e6157600083815260ce6020526040902054610e519082611ead565b610e5c906001611ec0565b610960565b60009392505050565b6001600160a01b038316610ecc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610573565b6001600160a01b038216610f2d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610573565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000610f9b8484610cfc565b90506000198114610df35781811015610ff65760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610573565b610df38484848403610e6a565b6001600160a01b0383166110675760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610573565b6001600160a01b0382166110c95760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610573565b6110d483838361150e565b6001600160a01b0383166000908152603360205260409020548181101561114c5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610573565b6001600160a01b0380851660008181526033602052604080822086860390559286168082529083902080548601905591516000805160206121128339815191529061119a9086815260200190565b60405180910390a3610df3565b6001600160a01b0382166112075760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610573565b6112138260008361150e565b6001600160a01b038216600090815260336020526040902054818110156112875760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610573565b6001600160a01b03831660008181526033602090815260408083208686039055603580548790039055518581529192916000805160206121128339815191529101610f82565b505050565b61130481600160cd546112e59190611ec0565b6001600160a01b038516600090815260d0602052604090209190611577565b816001600160a01b03167f655c1cd0236fb6dc4916f34c8ff10e3b18fcaea5b344dfc16c36fbb1bdfc5df28260405161133f91815260200190565b60405180910390a25050565b81546000905b83600101548110156113b65760008181526002850160209081526040918290208251808401909352805483526001015490820181905284101561139457506113b6565b80516113a09084611ec0565b92505080806113ae90611e94565b915050611351565b9250929050565b6001600160a01b0382166000908152606560205260408120819081906113e49085906116ed565b91509150816113fb576113f685610c10565b6113fd565b805b95945050505050565b600054610100900460ff1661142d5760405162461bcd60e51b815260040161057390611f7f565b61143782826117db565b5050565b611437828261181b565b60008060006114558460666116ed565b915091508161146657603554611468565b805b949350505050565b600182015460009080820361148957600091505061052d565b6000611496600183611ead565b90505b845481106115065760008181526002860160209081526040918290208251808401909352805483526001015490820181905285106114d75750611506565b80516114e39085611ec0565b9350816000036114f35750611506565b50806114fe81611fca565b915050611499565b505092915050565b6001600160a01b038316158061152b57506001600160a01b038216155b61156c5760405162461bcd60e51b81526020600482015260126024820152712a2920a729a322a92fa327a92124a22222a760711b6044820152606401610573565b6112cd8383836118d6565b816000036115d25760405162461bcd60e51b815260206004820152602260248201527f5769746864726177616c51756575654c69623a20494e56414c49445f414d4f55604482015261139560f21b6064820152608401610573565b82546001840154818103611629576040805180820182528581526020808201868152600085815260028a01909252928120915182559151600191820155860180549161161d83611e94565b91905055505050505050565b6000600286018161163b600185611ead565b81526020019081526020016000206001015490508084101561165f5761165f611fe1565b838110156116ae576040805180820182528681526020808201878152600086815260028b0190925292812091518255915160019182015587018054916116a483611e94565b9190505550610c08565b846002870160006116c0600186611ead565b815260200190815260200160002060000160008282546116e09190611ec0565b9091555050505050505050565b600080600084116117395760405162461bcd60e51b815260206004820152601660248201527504552433230536e617073686f743a20696420697320360541b6044820152606401610573565b60cd5484111561178b5760405162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e742069640000006044820152606401610573565b6000611797848661191e565b845490915081036117af5760008092509250506113b6565b60018460010182815481106117c6576117c6611f21565b906000526020600020015492509250506113b6565b600054610100900460ff166118025760405162461bcd60e51b815260040161057390611f7f565b603661180e838261203d565b5060376112cd828261203d565b6001600160a01b0382166118715760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610573565b61187d6000838361150e565b806035600082825461188f9190611ec0565b90915550506001600160a01b038216600081815260336020908152604080832080548601905551848152600080516020612112833981519152910160405180910390a35050565b6001600160a01b0383166118f5576118ed826119cb565b6112cd6119f5565b6001600160a01b03821661190c576118ed836119cb565b611915836119cb565b6112cd826119cb565b815460009081036119315750600061052d565b82546000905b8082101561197e57600061194b8383611a05565b6000878152602090209091508590820154111561196a57809150611978565b611975816001611ec0565b92505b50611937565b6000821180156119aa5750836119a786611999600186611ead565b600091825260209091200190565b54145b156119c3576119ba600183611ead565b9250505061052d565b50905061052d565b6001600160a01b03811660009081526065602052604090206107fd906119f083610c10565b611a20565b611a0360666119f060355490565b565b6000611a1460028484186120fd565b61096090848416611ec0565b6000611a2b60cd5490565b905080611a3784611a6b565b10156112cd578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b80546000908103611a7e57506000919050565b81548290611a8e90600190611ead565b81548110611a9e57611a9e611f21565b90600052602060002001549050919050565b6000815180845260005b81811015611ad657602081850181015186830182015201611aba565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006109606020830184611ab0565b6001600160a01b03811681146107fd57600080fd5b60008060408385031215611b3157600080fd5b8235611b3c81611b09565b946020939093013593505050565b6000808284036080811215611b5e57600080fd5b833592506060601f1982011215611b7457600080fd5b506020830190509250929050565b600080600060608486031215611b9757600080fd5b8335611ba281611b09565b92506020840135611bb281611b09565b929592945050506040919091013590565b600060208284031215611bd557600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611c1557611c15611bdc565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c4457611c44611bdc565b604052919050565b600080600080600060a08688031215611c6457600080fd5b8535611c6f81611b09565b9450602086810135611c8081611b09565b9450604087810135611c9181611b09565b945060608801359350608088013567ffffffffffffffff80821115611cb557600080fd5b818a0191508a601f830112611cc957600080fd5b813581811115611cdb57611cdb611bdc565b611ce9858260051b01611c1b565b818152858101925060069190911b83018501908c821115611d0957600080fd5b928501925b81841015611d525784848e031215611d265760008081fd5b611d2e611bf2565b8435611d3981611b09565b8152848701358782015283529284019291850191611d0e565b8096505050505050509295509295909350565b600060208284031215611d7757600080fd5b813561096081611b09565b60008060408385031215611d9557600080fd5b8235611da081611b09565b91506020830135611db081611b09565b809150509250929050565b60008060008060608587031215611dd157600080fd5b843593506020850135611de381611b09565b9250604085013567ffffffffffffffff80821115611e0057600080fd5b818701915087601f830112611e1457600080fd5b813581811115611e2357600080fd5b886020828501011115611e3557600080fd5b95989497505060200194505050565b600181811c90821680611e5857607f821691505b602082108103611e7857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600060018201611ea657611ea6611e7e565b5060010190565b8181038181111561052d5761052d611e7e565b8082018082111561052d5761052d611e7e565b634e487b7160e01b600052601260045260246000fd5b600082611ef857611ef8611ed3565b500690565b6001600160a01b038316815260406020820181905260009061146890830184611ab0565b634e487b7160e01b600052603260045260246000fd5b60008085851115611f4757600080fd5b83861115611f5457600080fd5b5050820193919092039150565b8035602083101561052d57600019602084900360031b1b1692915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600081611fd957611fd9611e7e565b506000190190565b634e487b7160e01b600052600160045260246000fd5b601f8211156112cd57600081815260208120601f850160051c8101602086101561201e5750805b601f850160051c820191505b81811015610c085782815560010161202a565b815167ffffffffffffffff81111561205757612057611bdc565b61206b816120658454611e44565b84611ff7565b602080601f8311600181146120a057600084156120885750858301515b600019600386901b1c1916600185901b178555610c08565b600085815260208120601f198616915b828110156120cf578886015182559484019460019091019084016120b0565b50858210156120ed5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008261210c5761210c611ed3565b50049056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212203c4d95e2d3f73d67d2168a29cb8be58c25d393af2555dd32816d324aba1cccfc64736f6c63430008130033\",\n \"deployedBytecode\": \"0x608060405234801561001057600080fd5b50600436106102015760003560e01c806361cc276311610125578063c6b61e4c116100ad578063ea0fee4f1161007c578063ea0fee4f1461043d578063eacdc5ff14610445578063eeb499451461044e578063f3f4370314610461578063fd242c141461047457600080fd5b8063c6b61e4c146103c4578063ce513b6f1461040e578063dd62ed3e14610421578063e0563ab11461043457600080fd5b806395d89b41116100f457806395d89b411461037957806397e5230d14610381578063981b24d01461038b578063a457c2d71461039e578063a9059cbb146103b157600080fd5b806361cc276314610341578063626560031461035457806370a082311461035d578063947287cf1461037057600080fd5b8063313ce567116101a85780633fd50001116101775780633fd50001146102f65780634ee2cd7e1461030957806351351d531461031c57806355b01e4d1461032a5780635ea5df791461033857600080fd5b8063313ce567146102c357806339509351146102d25780633b878c22146102e55780633ccfd60b146102ee57600080fd5b806306fdde031461020657806307b3e25214610224578063095ea7b31461024a5780630f50287c1461026d57806318160ddd1461028257806323b872dd14610294578063284017f5146102a75780632e17de78146102b0575b600080fd5b61020e610487565b60405161021b9190611af6565b60405180910390f35b6102326004600360981b0181565b6040516001600160a01b03909116815260200161021b565b61025d610258366004611b1e565b610519565b604051901515815260200161021b565b61028061027b366004611b4a565b610533565b005b6035545b60405190815260200161021b565b61025d6102a2366004611b82565b6107c5565b61023261202081565b6102806102be366004611bc3565b6107e9565b6040516012815260200161021b565b61025d6102e0366004611b1e565b610800565b61023261101081565b610280610822565b610286610304366004611bc3565b610933565b610286610317366004611b1e565b610954565b6102326002600160a01b0381565b6102326004600160991b0181565b61028661138881565b61028061034f366004611c4c565b610967565b61028660cc5481565b61028661036b366004611d65565b610c10565b61028661520881565b61020e610c2b565b610286620249f081565b610286610399366004611bc3565b610c3a565b61025d6103ac366004611b1e565b610c45565b61025d6103bf366004611b1e565b610cc0565b6103f36103d2366004611bc3565b60ce6020526000908152604090208054600182015460029092015490919083565b6040805193845260208401929092529082015260600161021b565b61028661041c366004611d65565b610cce565b61028661042f366004611d82565b610cfc565b61023261203081565b610286600181565b61028660cd5481565b61028061045c366004611dbb565b610d27565b61028661046f366004611d65565b610df9565b610286610482366004611bc3565b610e20565b60606036805461049690611e44565b80601f01602080910402602001604051908101604052809291908181526020018280546104c290611e44565b801561050f5780601f106104e45761010080835404028352916020019161050f565b820191906000526020600020905b8154815290600101906020018083116104f257829003601f168201915b5050505050905090565b600033610527818585610e6a565b60019150505b92915050565b336002600160a01b031461057c5760405163973d02cb60e01b815260206004820152600a60248201526914d654d5115350d0531360b21b60448201526064015b60405180910390fd5b60cd80546000918261058d83611e94565b9190505590508083146105d85760405162461bcd60e51b815260206004820152601360248201527215539156141150d5115117d15413d0d217d251606a1b6044820152606401610573565b81356020830135116106225760405162461bcd60e51b81526020600482015260136024820152721393d7d09313d0d2d4d7d0d3d3535255151151606a1b6044820152606401610573565b60cc5461063483356020850135611ead565b61063f906001611ec0565b6106499190611ee9565b156106a45760405162461bcd60e51b815260206004820152602560248201527f45504f43485f4d5553545f42455f444956495349424c455f42595f45504f43486044820152645f53495a4560d81b6064820152608401610573565b813560ce60006106b5600185611ead565b81526020019081526020016000206001015460016106d39190611ec0565b146107165760405162461bcd60e51b8152602060048201526013602482015272494e56414c49445f53544152545f424c4f434b60681b6044820152606401610573565b600081815260ce60205260409020829061074782828135815560208201356001820155604082013560028201555050565b505060cf80546001810182556000919091526020838101357facb8d954e2cfef495862221e91bd7523613cf8808827cb33edfe4904cc51bf299092018290556040805190850135815284359186917f0ce8712c4dee4bd5a691f0bc1c39594671591e77395f8ebf6a3fb5f63fbea66a910160405180910390a4505050565b6000336107d3858285610f8f565b6107de858585611003565b506001949350505050565b6107f333826111a7565b6107fd33826112d2565b50565b6000336105278185856108138383610cfc565b61081d9190611ec0565b610e6a565b33600090815260d06020526040812060cd54909190819061084490849061134b565b808555604051828152919350915033907f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b659060200160405180910390a260c95460cb54604080517f8ca9a95e41b5eece253c93f5b31eed1253aed6b145d8a6e14d913fdf8e7322936020820152338183015260608082018790528251808303909101815260808201928390526316f1983160e01b9092526001600160a01b03938416936316f19831936108fc93911691608401611efd565b600060405180830381600087803b15801561091657600080fd5b505af115801561092a573d6000803e3d6000fd5b50505050505050565b60cf818154811061094357600080fd5b600091825260209091200154905081565b600061096083836113bd565b9392505050565b600054610100900460ff16158080156109875750600054600160ff909116105b806109a15750303b1580156109a1575060005460ff166001145b610a045760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610573565b6000805460ff191660011790558015610a27576000805461ff0019166101001790555b6001600160a01b03861615801590610a4757506001600160a01b03851615155b8015610a5b57506001600160a01b03841615155b8015610a6657508215155b610aa25760405162461bcd60e51b815260206004820152600d60248201526c1253959053125117d253941555609a1b6044820152606401610573565b610aec6040518060400160405280600c81526020016b15985b1a59185d1bdc94d95d60a21b815250604051806040016040528060048152602001631594d15560e21b815250611406565b60c980546001600160a01b038089166001600160a01b03199283161790925560ca805488841690831617905560cb80549287169290911691909117905560cc83905560005b8251811015610b8657610b7e838281518110610b4f57610b4f611f21565b602002602001015160000151848381518110610b6d57610b6d611f21565b60200260200101516020015161143b565b600101610b31565b5060cf80546001818101835560009283527facb8d954e2cfef495862221e91bd7523613cf8808827cb33edfe4904cc51bf299091019190915560cd558015610c08576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6001600160a01b031660009081526033602052604090205490565b60606037805461049690611e44565b600061052d82611445565b60003381610c538286610cfc565b905083811015610cb35760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610573565b6107de8286868403610e6a565b600033610527818585611003565b60cd546001600160a01b038216600090815260d0602052604081209091610cf5919061134b565b5092915050565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b60ca546001600160a01b031633148015610d4e575060cb546001600160a01b038481169116145b610d8b5760405162461bcd60e51b815260206004820152600e60248201526d24a72b20a624a22fa9a2a72222a960911b6044820152606401610573565b7f1bcc0f4c3fad314e585165815f94ecca9b96690a26d6417d7876448a9a867a69610dba602060008486611f37565b610dc391611f61565b03610df357600080610dd88360208187611f37565b810190610de59190611b1e565b91509150610c08828261143b565b50505050565b60cd546001600160a01b038216600090815260d060205260408120909161052d9190611470565b600081815260ce60205260408120600101548015610e6157600083815260ce6020526040902054610e519082611ead565b610e5c906001611ec0565b610960565b60009392505050565b6001600160a01b038316610ecc5760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610573565b6001600160a01b038216610f2d5760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610573565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6000610f9b8484610cfc565b90506000198114610df35781811015610ff65760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610573565b610df38484848403610e6a565b6001600160a01b0383166110675760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610573565b6001600160a01b0382166110c95760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610573565b6110d483838361150e565b6001600160a01b0383166000908152603360205260409020548181101561114c5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610573565b6001600160a01b0380851660008181526033602052604080822086860390559286168082529083902080548601905591516000805160206121128339815191529061119a9086815260200190565b60405180910390a3610df3565b6001600160a01b0382166112075760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610573565b6112138260008361150e565b6001600160a01b038216600090815260336020526040902054818110156112875760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610573565b6001600160a01b03831660008181526033602090815260408083208686039055603580548790039055518581529192916000805160206121128339815191529101610f82565b505050565b61130481600160cd546112e59190611ec0565b6001600160a01b038516600090815260d0602052604090209190611577565b816001600160a01b03167f655c1cd0236fb6dc4916f34c8ff10e3b18fcaea5b344dfc16c36fbb1bdfc5df28260405161133f91815260200190565b60405180910390a25050565b81546000905b83600101548110156113b65760008181526002850160209081526040918290208251808401909352805483526001015490820181905284101561139457506113b6565b80516113a09084611ec0565b92505080806113ae90611e94565b915050611351565b9250929050565b6001600160a01b0382166000908152606560205260408120819081906113e49085906116ed565b91509150816113fb576113f685610c10565b6113fd565b805b95945050505050565b600054610100900460ff1661142d5760405162461bcd60e51b815260040161057390611f7f565b61143782826117db565b5050565b611437828261181b565b60008060006114558460666116ed565b915091508161146657603554611468565b805b949350505050565b600182015460009080820361148957600091505061052d565b6000611496600183611ead565b90505b845481106115065760008181526002860160209081526040918290208251808401909352805483526001015490820181905285106114d75750611506565b80516114e39085611ec0565b9350816000036114f35750611506565b50806114fe81611fca565b915050611499565b505092915050565b6001600160a01b038316158061152b57506001600160a01b038216155b61156c5760405162461bcd60e51b81526020600482015260126024820152712a2920a729a322a92fa327a92124a22222a760711b6044820152606401610573565b6112cd8383836118d6565b816000036115d25760405162461bcd60e51b815260206004820152602260248201527f5769746864726177616c51756575654c69623a20494e56414c49445f414d4f55604482015261139560f21b6064820152608401610573565b82546001840154818103611629576040805180820182528581526020808201868152600085815260028a01909252928120915182559151600191820155860180549161161d83611e94565b91905055505050505050565b6000600286018161163b600185611ead565b81526020019081526020016000206001015490508084101561165f5761165f611fe1565b838110156116ae576040805180820182528681526020808201878152600086815260028b0190925292812091518255915160019182015587018054916116a483611e94565b9190505550610c08565b846002870160006116c0600186611ead565b815260200190815260200160002060000160008282546116e09190611ec0565b9091555050505050505050565b600080600084116117395760405162461bcd60e51b815260206004820152601660248201527504552433230536e617073686f743a20696420697320360541b6044820152606401610573565b60cd5484111561178b5760405162461bcd60e51b815260206004820152601d60248201527f4552433230536e617073686f743a206e6f6e6578697374656e742069640000006044820152606401610573565b6000611797848661191e565b845490915081036117af5760008092509250506113b6565b60018460010182815481106117c6576117c6611f21565b906000526020600020015492509250506113b6565b600054610100900460ff166118025760405162461bcd60e51b815260040161057390611f7f565b603661180e838261203d565b5060376112cd828261203d565b6001600160a01b0382166118715760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610573565b61187d6000838361150e565b806035600082825461188f9190611ec0565b90915550506001600160a01b038216600081815260336020908152604080832080548601905551848152600080516020612112833981519152910160405180910390a35050565b6001600160a01b0383166118f5576118ed826119cb565b6112cd6119f5565b6001600160a01b03821661190c576118ed836119cb565b611915836119cb565b6112cd826119cb565b815460009081036119315750600061052d565b82546000905b8082101561197e57600061194b8383611a05565b6000878152602090209091508590820154111561196a57809150611978565b611975816001611ec0565b92505b50611937565b6000821180156119aa5750836119a786611999600186611ead565b600091825260209091200190565b54145b156119c3576119ba600183611ead565b9250505061052d565b50905061052d565b6001600160a01b03811660009081526065602052604090206107fd906119f083610c10565b611a20565b611a0360666119f060355490565b565b6000611a1460028484186120fd565b61096090848416611ec0565b6000611a2b60cd5490565b905080611a3784611a6b565b10156112cd578254600180820185556000858152602080822090930193909355938401805494850181558252902090910155565b80546000908103611a7e57506000919050565b81548290611a8e90600190611ead565b81548110611a9e57611a9e611f21565b90600052602060002001549050919050565b6000815180845260005b81811015611ad657602081850181015186830182015201611aba565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006109606020830184611ab0565b6001600160a01b03811681146107fd57600080fd5b60008060408385031215611b3157600080fd5b8235611b3c81611b09565b946020939093013593505050565b6000808284036080811215611b5e57600080fd5b833592506060601f1982011215611b7457600080fd5b506020830190509250929050565b600080600060608486031215611b9757600080fd5b8335611ba281611b09565b92506020840135611bb281611b09565b929592945050506040919091013590565b600060208284031215611bd557600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611c1557611c15611bdc565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c4457611c44611bdc565b604052919050565b600080600080600060a08688031215611c6457600080fd5b8535611c6f81611b09565b9450602086810135611c8081611b09565b9450604087810135611c9181611b09565b945060608801359350608088013567ffffffffffffffff80821115611cb557600080fd5b818a0191508a601f830112611cc957600080fd5b813581811115611cdb57611cdb611bdc565b611ce9858260051b01611c1b565b818152858101925060069190911b83018501908c821115611d0957600080fd5b928501925b81841015611d525784848e031215611d265760008081fd5b611d2e611bf2565b8435611d3981611b09565b8152848701358782015283529284019291850191611d0e565b8096505050505050509295509295909350565b600060208284031215611d7757600080fd5b813561096081611b09565b60008060408385031215611d9557600080fd5b8235611da081611b09565b91506020830135611db081611b09565b809150509250929050565b60008060008060608587031215611dd157600080fd5b843593506020850135611de381611b09565b9250604085013567ffffffffffffffff80821115611e0057600080fd5b818701915087601f830112611e1457600080fd5b813581811115611e2357600080fd5b886020828501011115611e3557600080fd5b95989497505060200194505050565b600181811c90821680611e5857607f821691505b602082108103611e7857634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600060018201611ea657611ea6611e7e565b5060010190565b8181038181111561052d5761052d611e7e565b8082018082111561052d5761052d611e7e565b634e487b7160e01b600052601260045260246000fd5b600082611ef857611ef8611ed3565b500690565b6001600160a01b038316815260406020820181905260009061146890830184611ab0565b634e487b7160e01b600052603260045260246000fd5b60008085851115611f4757600080fd5b83861115611f5457600080fd5b5050820193919092039150565b8035602083101561052d57600019602084900360031b1b1692915050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b600081611fd957611fd9611e7e565b506000190190565b634e487b7160e01b600052600160045260246000fd5b601f8211156112cd57600081815260208120601f850160051c8101602086101561201e5750805b601f850160051c820191505b81811015610c085782815560010161202a565b815167ffffffffffffffff81111561205757612057611bdc565b61206b816120658454611e44565b84611ff7565b602080601f8311600181146120a057600084156120885750858301515b600019600386901b1c1916600185901b178555610c08565b600085815260208120601f198616915b828110156120cf578886015182559484019460019091019084016120b0565b50858210156120ed5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008261210c5761210c611ed3565b50049056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212203c4d95e2d3f73d67d2168a29cb8be58c25d393af2555dd32816d324aba1cccfc64736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" +var EIP1559BurnArtifact string = "{\n \"_format\": \"hh-sol-artifact-1\",\n \"contractName\": \"EIP1559Burn\",\n \"sourceName\": \"contracts/child/EIP1559Burn.sol\",\n \"abi\": [\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": false,\n \"internalType\": \"uint8\",\n \"name\": \"version\",\n \"type\": \"uint8\"\n }\n ],\n \"name\": \"Initialized\",\n \"type\": \"event\"\n },\n {\n \"anonymous\": false,\n \"inputs\": [\n {\n \"indexed\": true,\n \"internalType\": \"address\",\n \"name\": \"burner\",\n \"type\": \"address\"\n },\n {\n \"indexed\": false,\n \"internalType\": \"uint256\",\n \"name\": \"amount\",\n \"type\": \"uint256\"\n }\n ],\n \"name\": \"NativeTokenBurnt\",\n \"type\": \"event\"\n },\n {\n \"inputs\": [],\n \"name\": \"burnDestination\",\n \"outputs\": [\n {\n \"internalType\": \"address\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"childERC20Predicate\",\n \"outputs\": [\n {\n \"internalType\": \"contract IChildERC20Predicate\",\n \"name\": \"\",\n \"type\": \"address\"\n }\n ],\n \"stateMutability\": \"view\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [\n {\n \"internalType\": \"contract IChildERC20Predicate\",\n \"name\": \"newChildERC20Predicate\",\n \"type\": \"address\"\n },\n {\n \"internalType\": \"address\",\n \"name\": \"newBurnDestination\",\n \"type\": \"address\"\n }\n ],\n \"name\": \"initialize\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"inputs\": [],\n \"name\": \"withdraw\",\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\",\n \"type\": \"function\"\n },\n {\n \"stateMutability\": \"payable\",\n \"type\": \"receive\"\n }\n ],\n \"bytecode\": \"0x608060405234801561001057600080fd5b50610425806100206000396000f3fe6080604052600436106100435760003560e01c80630fca96871461004f5780633ccfd60b1461008b578063485cc955146100a2578063d57184e4146100c257600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b5060015461006f906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b34801561009757600080fd5b506100a06100e8565b005b3480156100ae57600080fd5b506100a06100bd3660046103b6565b6101fc565b3480156100ce57600080fd5b5060005461006f906201000090046001600160a01b031681565b6000546201000090046001600160a01b031661014b5760405162461bcd60e51b815260206004820152601a60248201527f454950313535394275726e3a20554e494e495449414c495a454400000000000060448201526064015b60405180910390fd5b6000546001546040516361d9ad3f60e11b815261101060048201526001600160a01b0391821660248201524760448201819052926201000090049091169063c3b35a7e90606401600060405180830381600087803b1580156101ac57600080fd5b505af11580156101c0573d6000803e3d6000fd5b50506040518381523392507feb347a9a474ae97b7b32a903d84decf8fc80dc9cd6129085f5097de5cd3b3256915060200160405180910390a250565b600054610100900460ff161580801561021c5750600054600160ff909116105b806102365750303b158015610236575060005460ff166001145b6102995760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610142565b6000805460ff1916600117905580156102bc576000805461ff0019166101001790555b6001600160a01b0383166103125760405162461bcd60e51b815260206004820152601f60248201527f454950313535394275726e3a204241445f494e495449414c495a4154494f4e006044820152606401610142565b6000805462010000600160b01b031916620100006001600160a01b038681169190910291909117909155600180546001600160a01b0319169184169190911790558015610399576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03811681146103b357600080fd5b50565b600080604083850312156103c957600080fd5b82356103d48161039e565b915060208301356103e48161039e565b80915050925092905056fea264697066735822122017aa34fe0fb30c4917a2b19c5df8508e7d7149f54977cecd862fec4444e087b364736f6c63430008130033\",\n \"deployedBytecode\": \"0x6080604052600436106100435760003560e01c80630fca96871461004f5780633ccfd60b1461008b578063485cc955146100a2578063d57184e4146100c257600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b5060015461006f906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b34801561009757600080fd5b506100a06100e8565b005b3480156100ae57600080fd5b506100a06100bd3660046103b6565b6101fc565b3480156100ce57600080fd5b5060005461006f906201000090046001600160a01b031681565b6000546201000090046001600160a01b031661014b5760405162461bcd60e51b815260206004820152601a60248201527f454950313535394275726e3a20554e494e495449414c495a454400000000000060448201526064015b60405180910390fd5b6000546001546040516361d9ad3f60e11b815261101060048201526001600160a01b0391821660248201524760448201819052926201000090049091169063c3b35a7e90606401600060405180830381600087803b1580156101ac57600080fd5b505af11580156101c0573d6000803e3d6000fd5b50506040518381523392507feb347a9a474ae97b7b32a903d84decf8fc80dc9cd6129085f5097de5cd3b3256915060200160405180910390a250565b600054610100900460ff161580801561021c5750600054600160ff909116105b806102365750303b158015610236575060005460ff166001145b6102995760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610142565b6000805460ff1916600117905580156102bc576000805461ff0019166101001790555b6001600160a01b0383166103125760405162461bcd60e51b815260206004820152601f60248201527f454950313535394275726e3a204241445f494e495449414c495a4154494f4e006044820152606401610142565b6000805462010000600160b01b031916620100006001600160a01b038681169190910291909117909155600180546001600160a01b0319169184169190911790558015610399576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b6001600160a01b03811681146103b357600080fd5b50565b600080604083850312156103c957600080fd5b82356103d48161039e565b915060208301356103e48161039e565b80915050925092905056fea264697066735822122017aa34fe0fb30c4917a2b19c5df8508e7d7149f54977cecd862fec4444e087b364736f6c63430008130033\",\n \"linkReferences\": {},\n \"deployedLinkReferences\": {}\n}\n" diff --git a/consensus/polybft/contractsapi/helper.go b/consensus/polybft/contractsapi/helper.go index 645598f37d..9eb38707aa 100644 --- a/consensus/polybft/contractsapi/helper.go +++ b/consensus/polybft/contractsapi/helper.go @@ -1,8 +1,6 @@ package contractsapi import ( - "math/big" - "github.com/0xPolygon/polygon-edge/types" "github.com/umbracle/ethgo/abi" ) @@ -29,13 +27,18 @@ func (sse *StateSyncedEvent) EncodeAbi() ([]byte, error) { return stateSyncABIType.Encode([]interface{}{sse}) } -// AddValidatorUptime is an extension (helper) function on a generated Uptime type -// that adds uptime data for given validator to Uptime struct -func (u *Uptime) AddValidatorUptime(address types.Address, count int64) { - u.UptimeData = append(u.UptimeData, &UptimeData{ - Validator: address, - SignedBlocks: big.NewInt(count), - }) +var ( + _ StateTransactionInput = &CommitEpochValidatorSetFn{} + _ StateTransactionInput = &DistributeRewardForRewardPoolFn{} +) + +// IsStake indicates if transfer event (from ERC20 implementation) mints tokens to a non zero address +func (t *TransferEvent) IsStake() bool { + return t.To != types.ZeroAddress && t.From == types.ZeroAddress } -var _ StateTransactionInput = &CommitEpochChildValidatorSetFn{} +// IsUnstake indicates if transfer event (from ERC20 implementation) burns tokens from a non zero address +// meaning, it transfers them to zero address +func (t *TransferEvent) IsUnstake() bool { + return t.To == types.ZeroAddress && t.From != types.ZeroAddress +} diff --git a/consensus/polybft/contractsapi/init.go b/consensus/polybft/contractsapi/init.go index 8f385ca19e..33b76bf157 100644 --- a/consensus/polybft/contractsapi/init.go +++ b/consensus/polybft/contractsapi/init.go @@ -14,28 +14,54 @@ const ( var ( // core-contracts smart contracts - CheckpointManager *artifact.Artifact - ExitHelper *artifact.Artifact - StateSender *artifact.Artifact - RootERC20Predicate *artifact.Artifact - BLS *artifact.Artifact - BLS256 *artifact.Artifact - System *artifact.Artifact - Merkle *artifact.Artifact - ChildValidatorSet *artifact.Artifact - NativeERC20 *artifact.Artifact - NativeERC20Mintable *artifact.Artifact - StateReceiver *artifact.Artifact - ChildERC20 *artifact.Artifact - ChildERC20Predicate *artifact.Artifact - L2StateSender *artifact.Artifact + CheckpointManager *artifact.Artifact + ExitHelper *artifact.Artifact + StateSender *artifact.Artifact + RootERC20Predicate *artifact.Artifact + RootERC721Predicate *artifact.Artifact + RootERC1155Predicate *artifact.Artifact + ChildMintableERC20Predicate *artifact.Artifact + ChildMintableERC721Predicate *artifact.Artifact + ChildMintableERC1155Predicate *artifact.Artifact + BLS *artifact.Artifact + BLS256 *artifact.Artifact + System *artifact.Artifact + Merkle *artifact.Artifact + ChildValidatorSet *artifact.Artifact + NativeERC20 *artifact.Artifact + NativeERC20Mintable *artifact.Artifact + StateReceiver *artifact.Artifact + ChildERC20 *artifact.Artifact + ChildERC20Predicate *artifact.Artifact + ChildERC20PredicateACL *artifact.Artifact + RootMintableERC20Predicate *artifact.Artifact + RootMintableERC20PredicateACL *artifact.Artifact + ChildERC721 *artifact.Artifact + ChildERC721Predicate *artifact.Artifact + ChildERC721PredicateACL *artifact.Artifact + RootMintableERC721Predicate *artifact.Artifact + RootMintableERC721PredicateACL *artifact.Artifact + ChildERC1155 *artifact.Artifact + ChildERC1155Predicate *artifact.Artifact + ChildERC1155PredicateACL *artifact.Artifact + RootMintableERC1155Predicate *artifact.Artifact + RootMintableERC1155PredicateACL *artifact.Artifact + L2StateSender *artifact.Artifact + CustomSupernetManager *artifact.Artifact + StakeManager *artifact.Artifact + RewardPool *artifact.Artifact + ValidatorSet *artifact.Artifact + RootERC721 *artifact.Artifact + RootERC1155 *artifact.Artifact + EIP1559Burn *artifact.Artifact // test smart contracts //go:embed test-contracts/* testContracts embed.FS - TestL1StateReceiver *artifact.Artifact TestWriteBlockMetadata *artifact.Artifact RootERC20 *artifact.Artifact + TestSimple *artifact.Artifact + TestRewardToken *artifact.Artifact ) func init() { @@ -81,6 +107,31 @@ func init() { log.Fatal(err) } + RootERC721Predicate, err = artifact.DecodeArtifact([]byte(RootERC721PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + RootERC1155Predicate, err = artifact.DecodeArtifact([]byte(RootERC1155PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + ChildMintableERC20Predicate, err = artifact.DecodeArtifact([]byte(ChildMintableERC20PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + ChildMintableERC721Predicate, err = artifact.DecodeArtifact([]byte(ChildMintableERC721PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + ChildMintableERC1155Predicate, err = artifact.DecodeArtifact([]byte(ChildMintableERC1155PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + StateReceiver, err = artifact.DecodeArtifact([]byte(StateReceiverArtifact)) if err != nil { log.Fatal(err) @@ -101,7 +152,67 @@ func init() { log.Fatal(err) } - ChildValidatorSet, err = artifact.DecodeArtifact([]byte(ChildValidatorSetArtifact)) + ChildERC20PredicateACL, err = artifact.DecodeArtifact([]byte(ChildERC20PredicateACLArtifact)) + if err != nil { + log.Fatal(err) + } + + RootMintableERC20Predicate, err = artifact.DecodeArtifact([]byte(RootMintableERC20PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + RootMintableERC20PredicateACL, err = artifact.DecodeArtifact([]byte(RootMintableERC20PredicateACLArtifact)) + if err != nil { + log.Fatal(err) + } + + ChildERC721, err = artifact.DecodeArtifact([]byte(ChildERC721Artifact)) + if err != nil { + log.Fatal(err) + } + + ChildERC721Predicate, err = artifact.DecodeArtifact([]byte(ChildERC721PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + ChildERC721PredicateACL, err = artifact.DecodeArtifact([]byte(ChildERC721PredicateACLArtifact)) + if err != nil { + log.Fatal(err) + } + + RootMintableERC721Predicate, err = artifact.DecodeArtifact([]byte(RootMintableERC721PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + RootMintableERC721PredicateACL, err = artifact.DecodeArtifact([]byte(RootMintableERC721PredicateACLArtifact)) + if err != nil { + log.Fatal(err) + } + + ChildERC1155, err = artifact.DecodeArtifact([]byte(ChildERC1155Artifact)) + if err != nil { + log.Fatal(err) + } + + ChildERC1155Predicate, err = artifact.DecodeArtifact([]byte(ChildERC1155PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + ChildERC1155PredicateACL, err = artifact.DecodeArtifact([]byte(ChildERC1155PredicateACLArtifact)) + if err != nil { + log.Fatal(err) + } + + RootMintableERC1155Predicate, err = artifact.DecodeArtifact([]byte(RootMintableERC1155PredicateArtifact)) + if err != nil { + log.Fatal(err) + } + + RootMintableERC1155PredicateACL, err = artifact.DecodeArtifact([]byte(RootMintableERC1155PredicateACLArtifact)) if err != nil { log.Fatal(err) } @@ -121,7 +232,12 @@ func init() { log.Fatal(err) } - TestL1StateReceiver, err = artifact.DecodeArtifact(readTestContractContent("TestL1StateReceiver.json")) + RootERC721, err = artifact.DecodeArtifact([]byte(MockERC721Artifact)) + if err != nil { + log.Fatal(err) + } + + RootERC1155, err = artifact.DecodeArtifact([]byte(MockERC1155Artifact)) if err != nil { log.Fatal(err) } @@ -130,6 +246,41 @@ func init() { if err != nil { log.Fatal(err) } + + TestSimple, err = artifact.DecodeArtifact(readTestContractContent("TestSimple.json")) + if err != nil { + log.Fatal(err) + } + + TestRewardToken, err = artifact.DecodeArtifact(readTestContractContent("TestRewardToken.json")) + if err != nil { + log.Fatal(err) + } + + CustomSupernetManager, err = artifact.DecodeArtifact([]byte(CustomSupernetManagerArtifact)) + if err != nil { + log.Fatal(err) + } + + StakeManager, err = artifact.DecodeArtifact([]byte(StakeManagerArtifact)) + if err != nil { + log.Fatal(err) + } + + RewardPool, err = artifact.DecodeArtifact([]byte(RewardPoolArtifact)) + if err != nil { + log.Fatal(err) + } + + ValidatorSet, err = artifact.DecodeArtifact([]byte(ValidatorSetArtifact)) + if err != nil { + log.Fatal(err) + } + + EIP1559Burn, err = artifact.DecodeArtifact([]byte(EIP1559BurnArtifact)) + if err != nil { + log.Fatal(err) + } } func readTestContractContent(contractFileName string) []byte { diff --git a/consensus/polybft/contractsapi/test-contracts/TestL1StateReceiver.json b/consensus/polybft/contractsapi/test-contracts/TestL1StateReceiver.json deleted file mode 100644 index f8e62a97d0..0000000000 --- a/consensus/polybft/contractsapi/test-contracts/TestL1StateReceiver.json +++ /dev/null @@ -1,86 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "TestL1StateReceiver", - "sourceName": "test-contracts/TestL1StateReceiver.sol", - "abi": [ - { - "inputs": [], - "name": "addr", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "counter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "data", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "id", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "_id", - "type": "uint256" - }, - { - "internalType": "address", - "name": "_addr", - "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "onL2StateReceive", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "bytecode": "0x608060405234801561001057600080fd5b5061048e806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806361bc221a1461005c57806373d4a13a14610078578063767800de1461008d578063af640d0f146100b8578063f43cda8b146100c1575b600080fd5b61006560035481565b6040519081526020015b60405180910390f35b6100806100d6565b60405161006f91906101ab565b6001546100a0906001600160a01b031681565b6040516001600160a01b03909116815260200161006f565b61006560005481565b6100d46100cf36600461020f565b610164565b005b600280546100e3906102e8565b80601f016020809104026020016040519081016040528092919081815260200182805461010f906102e8565b801561015c5780601f106101315761010080835404028352916020019161015c565b820191906000526020600020905b81548152906001019060200180831161013f57829003601f168201915b505050505081565b6000839055600180546001600160a01b0319166001600160a01b03841617905560026101908282610371565b50600380549060006101a183610431565b9190505550505050565b600060208083528351808285015260005b818110156101d8578581018301518582016040015282016101bc565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561022457600080fd5b8335925060208401356001600160a01b038116811461024257600080fd5b9150604084013567ffffffffffffffff8082111561025f57600080fd5b818601915086601f83011261027357600080fd5b813581811115610285576102856101f9565b604051601f8201601f19908116603f011681019083821181831017156102ad576102ad6101f9565b816040528281528960208487010111156102c657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b600181811c908216806102fc57607f821691505b60208210810361031c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561036c57600081815260208120601f850160051c810160208610156103495750805b601f850160051c820191505b8181101561036857828155600101610355565b5050505b505050565b815167ffffffffffffffff81111561038b5761038b6101f9565b61039f8161039984546102e8565b84610322565b602080601f8311600181146103d457600084156103bc5750858301515b600019600386901b1c1916600185901b178555610368565b600085815260208120601f198616915b82811015610403578886015182559484019460019091019084016103e4565b50858210156104215787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001820161045157634e487b7160e01b600052601160045260246000fd5b506001019056fea264697066735822122059d4887cdfb5a893df715259d93546c8e85fa890245389c3d2e7e4fb6eb293de64736f6c63430008110033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806361bc221a1461005c57806373d4a13a14610078578063767800de1461008d578063af640d0f146100b8578063f43cda8b146100c1575b600080fd5b61006560035481565b6040519081526020015b60405180910390f35b6100806100d6565b60405161006f91906101ab565b6001546100a0906001600160a01b031681565b6040516001600160a01b03909116815260200161006f565b61006560005481565b6100d46100cf36600461020f565b610164565b005b600280546100e3906102e8565b80601f016020809104026020016040519081016040528092919081815260200182805461010f906102e8565b801561015c5780601f106101315761010080835404028352916020019161015c565b820191906000526020600020905b81548152906001019060200180831161013f57829003601f168201915b505050505081565b6000839055600180546001600160a01b0319166001600160a01b03841617905560026101908282610371565b50600380549060006101a183610431565b9190505550505050565b600060208083528351808285015260005b818110156101d8578581018301518582016040015282016101bc565b506000604082860101526040601f19601f8301168501019250505092915050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561022457600080fd5b8335925060208401356001600160a01b038116811461024257600080fd5b9150604084013567ffffffffffffffff8082111561025f57600080fd5b818601915086601f83011261027357600080fd5b813581811115610285576102856101f9565b604051601f8201601f19908116603f011681019083821181831017156102ad576102ad6101f9565b816040528281528960208487010111156102c657600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b600181811c908216806102fc57607f821691505b60208210810361031c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561036c57600081815260208120601f850160051c810160208610156103495750805b601f850160051c820191505b8181101561036857828155600101610355565b5050505b505050565b815167ffffffffffffffff81111561038b5761038b6101f9565b61039f8161039984546102e8565b84610322565b602080601f8311600181146103d457600084156103bc5750858301515b600019600386901b1c1916600185901b178555610368565b600085815260208120601f198616915b82811015610403578886015182559484019460019091019084016103e4565b50858210156104215787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60006001820161045157634e487b7160e01b600052601160045260246000fd5b506001019056fea264697066735822122059d4887cdfb5a893df715259d93546c8e85fa890245389c3d2e7e4fb6eb293de64736f6c63430008110033", - "linkReferences": {}, - "deployedLinkReferences": {} -} \ No newline at end of file diff --git a/consensus/polybft/contractsapi/test-contracts/TestL1StateReceiver.sol b/consensus/polybft/contractsapi/test-contracts/TestL1StateReceiver.sol deleted file mode 100644 index 0e066c3202..0000000000 --- a/consensus/polybft/contractsapi/test-contracts/TestL1StateReceiver.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.17; - -contract TestL1StateReceiver { - uint256 public id; - address public addr; - bytes public data; - uint256 public counter; - - function onL2StateReceive( - uint256 _id, - address _addr, - bytes memory _data - ) public { - id = _id; - addr = _addr; - data = _data; - counter++; - } -} diff --git a/consensus/polybft/contractsapi/test-contracts/TestRewardToken.json b/consensus/polybft/contractsapi/test-contracts/TestRewardToken.json new file mode 100644 index 0000000000..86f12b2af3 --- /dev/null +++ b/consensus/polybft/contractsapi/test-contracts/TestRewardToken.json @@ -0,0 +1,330 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TestRewardToken", + "sourceName": "contracts/mocks/TestRewardToken.sol", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50610a87806100206000396000f3fe608060405234801561001057600080fd5b50600436106100bf5760003560e01c806340c10f191161007c57806340c10f191461014c57806370a082311461016157806395d89b411461018a5780639dc29fac14610192578063a457c2d7146101a5578063a9059cbb146101b8578063dd62ed3e146101cb57600080fd5b806306fdde03146100c4578063095ea7b3146100e257806318160ddd1461010557806323b872dd14610117578063313ce5671461012a5780633950935114610139575b600080fd5b6100cc6101de565b6040516100d991906108b1565b60405180910390f35b6100f56100f036600461091b565b610270565b60405190151581526020016100d9565b6035545b6040519081526020016100d9565b6100f5610125366004610945565b61028a565b604051601281526020016100d9565b6100f561014736600461091b565b6102ae565b61015f61015a36600461091b565b6102d0565b005b61010961016f366004610981565b6001600160a01b031660009081526033602052604090205490565b6100cc6102de565b61015f6101a036600461091b565b6102ed565b6100f56101b336600461091b565b6102f7565b6100f56101c636600461091b565b610377565b6101096101d93660046109a3565b610385565b6060603680546101ed906109d6565b80601f0160208091040260200160405190810160405280929190818152602001828054610219906109d6565b80156102665780601f1061023b57610100808354040283529160200191610266565b820191906000526020600020905b81548152906001019060200180831161024957829003601f168201915b5050505050905090565b60003361027e8185856103b0565b60019150505b92915050565b6000336102988582856104d5565b6102a385858561054f565b506001949350505050565b60003361027e8185856102c18383610385565b6102cb9190610a10565b6103b0565b6102da82826106e8565b5050565b6060603780546101ed906109d6565b6102da8282610797565b600033816103058286610385565b90508381101561036a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a382868684036103b0565b60003361027e81858561054f565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6001600160a01b0383166104125760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610361565b6001600160a01b0382166104735760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610361565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006104e18484610385565b90506000198114610549578181101561053c5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610361565b61054984848484036103b0565b50505050565b6001600160a01b0383166105b35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610361565b6001600160a01b0382166106155760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610361565b6001600160a01b0383166000908152603360205260409020548181101561068d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610361565b6001600160a01b038085166000818152603360205260408082208686039055928616808252908390208054860190559151600080516020610a32833981519152906106db9086815260200190565b60405180910390a3610549565b6001600160a01b03821661073e5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610361565b80603560008282546107509190610a10565b90915550506001600160a01b038216600081815260336020908152604080832080548601905551848152600080516020610a32833981519152910160405180910390a35050565b6001600160a01b0382166107f75760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610361565b6001600160a01b0382166000908152603360205260409020548181101561086b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610361565b6001600160a01b0383166000818152603360209081526040808320868603905560358054879003905551858152919291600080516020610a3283398151915291016104c8565b600060208083528351808285015260005b818110156108de578581018301518582016040015282016108c2565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461091657600080fd5b919050565b6000806040838503121561092e57600080fd5b610937836108ff565b946020939093013593505050565b60008060006060848603121561095a57600080fd5b610963846108ff565b9250610971602085016108ff565b9150604084013590509250925092565b60006020828403121561099357600080fd5b61099c826108ff565b9392505050565b600080604083850312156109b657600080fd5b6109bf836108ff565b91506109cd602084016108ff565b90509250929050565b600181811c908216806109ea57607f821691505b602082108103610a0a57634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561028457634e487b7160e01b600052601160045260246000fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212207a3087f7ea340d96d27d018cb7cdeb374c187cb5bf45382f42a2c2793bd19ff264736f6c63430008130033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100bf5760003560e01c806340c10f191161007c57806340c10f191461014c57806370a082311461016157806395d89b411461018a5780639dc29fac14610192578063a457c2d7146101a5578063a9059cbb146101b8578063dd62ed3e146101cb57600080fd5b806306fdde03146100c4578063095ea7b3146100e257806318160ddd1461010557806323b872dd14610117578063313ce5671461012a5780633950935114610139575b600080fd5b6100cc6101de565b6040516100d991906108b1565b60405180910390f35b6100f56100f036600461091b565b610270565b60405190151581526020016100d9565b6035545b6040519081526020016100d9565b6100f5610125366004610945565b61028a565b604051601281526020016100d9565b6100f561014736600461091b565b6102ae565b61015f61015a36600461091b565b6102d0565b005b61010961016f366004610981565b6001600160a01b031660009081526033602052604090205490565b6100cc6102de565b61015f6101a036600461091b565b6102ed565b6100f56101b336600461091b565b6102f7565b6100f56101c636600461091b565b610377565b6101096101d93660046109a3565b610385565b6060603680546101ed906109d6565b80601f0160208091040260200160405190810160405280929190818152602001828054610219906109d6565b80156102665780601f1061023b57610100808354040283529160200191610266565b820191906000526020600020905b81548152906001019060200180831161024957829003601f168201915b5050505050905090565b60003361027e8185856103b0565b60019150505b92915050565b6000336102988582856104d5565b6102a385858561054f565b506001949350505050565b60003361027e8185856102c18383610385565b6102cb9190610a10565b6103b0565b6102da82826106e8565b5050565b6060603780546101ed906109d6565b6102da8282610797565b600033816103058286610385565b90508381101561036a5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084015b60405180910390fd5b6102a382868684036103b0565b60003361027e81858561054f565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b6001600160a01b0383166104125760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610361565b6001600160a01b0382166104735760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610361565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006104e18484610385565b90506000198114610549578181101561053c5760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610361565b61054984848484036103b0565b50505050565b6001600160a01b0383166105b35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610361565b6001600160a01b0382166106155760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610361565b6001600160a01b0383166000908152603360205260409020548181101561068d5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610361565b6001600160a01b038085166000818152603360205260408082208686039055928616808252908390208054860190559151600080516020610a32833981519152906106db9086815260200190565b60405180910390a3610549565b6001600160a01b03821661073e5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610361565b80603560008282546107509190610a10565b90915550506001600160a01b038216600081815260336020908152604080832080548601905551848152600080516020610a32833981519152910160405180910390a35050565b6001600160a01b0382166107f75760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608401610361565b6001600160a01b0382166000908152603360205260409020548181101561086b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608401610361565b6001600160a01b0383166000818152603360209081526040808320868603905560358054879003905551858152919291600080516020610a3283398151915291016104c8565b600060208083528351808285015260005b818110156108de578581018301518582016040015282016108c2565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b038116811461091657600080fd5b919050565b6000806040838503121561092e57600080fd5b610937836108ff565b946020939093013593505050565b60008060006060848603121561095a57600080fd5b610963846108ff565b9250610971602085016108ff565b9150604084013590509250925092565b60006020828403121561099357600080fd5b61099c826108ff565b9392505050565b600080604083850312156109b657600080fd5b6109bf836108ff565b91506109cd602084016108ff565b90509250929050565b600181811c908216806109ea57607f821691505b602082108103610a0a57634e487b7160e01b600052602260045260246000fd5b50919050565b8082018082111561028457634e487b7160e01b600052601160045260246000fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212207a3087f7ea340d96d27d018cb7cdeb374c187cb5bf45382f42a2c2793bd19ff264736f6c63430008130033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/consensus/polybft/contractsapi/test-contracts/TestSimple.json b/consensus/polybft/contractsapi/test-contracts/TestSimple.json new file mode 100644 index 0000000000..2772c448ee --- /dev/null +++ b/consensus/polybft/contractsapi/test-contracts/TestSimple.json @@ -0,0 +1,39 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "TestSimple", + "sourceName": "contracts/TestSimple.sol", + "abi": [ + { + "inputs": [], + "name": "getValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_val", + "type": "uint256" + } + ], + "name": "setValue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063209652551461003b5780635524107714610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea2646970667358221220470fde08a8031bec841c7cc72e8ff6af3fefb578f1a87c4d89d5fb45f57a532464736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063209652551461003b5780635524107714610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea2646970667358221220470fde08a8031bec841c7cc72e8ff6af3fefb578f1a87c4d89d5fb45f57a532464736f6c63430008110033", + "linkReferences": {}, + "deployedLinkReferences": {} +} + + diff --git a/consensus/polybft/contractsapi/test-contracts/TestSimple.sol b/consensus/polybft/contractsapi/test-contracts/TestSimple.sol new file mode 100644 index 0000000000..9366467e74 --- /dev/null +++ b/consensus/polybft/contractsapi/test-contracts/TestSimple.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +contract TestSimple { + uint256 val; + + function getValue() public view returns (uint256) { + return val; + } + + function setValue(uint256 _val) public { + val = _val; + } +} diff --git a/consensus/polybft/contractsapi/test-contracts/TestWriteBlockMetadata.sol b/consensus/polybft/contractsapi/test-contracts/TestWriteBlockMetadata.sol index 90fe2a2ee3..c24384b34b 100644 --- a/consensus/polybft/contractsapi/test-contracts/TestWriteBlockMetadata.sol +++ b/consensus/polybft/contractsapi/test-contracts/TestWriteBlockMetadata.sol @@ -13,7 +13,7 @@ contract TestWriteBlockMetadata { data.push(block.gaslimit); data.push(block.chainid); coinbase = block.coinbase; - // data.push(block.basefee); + data.push(block.basefee); // hash = blockhash(block.number); } } \ No newline at end of file diff --git a/consensus/polybft/extra.go b/consensus/polybft/extra.go index 8b7776964a..42ba463738 100644 --- a/consensus/polybft/extra.go +++ b/consensus/polybft/extra.go @@ -1,12 +1,11 @@ package polybft import ( - "bytes" "fmt" "math/big" - "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/crypto" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" @@ -27,8 +26,7 @@ var PolyBFTMixDigest = types.StringToHash("adce6e5230abe012342a44e4e9b6d05997d6f // Extra defines the structure of the extra field for Istanbul type Extra struct { - Validators *ValidatorSetDelta - Seal []byte + Validators *validator.ValidatorSetDelta Parent *Signature Committed *Signature Checkpoint *CheckpointData @@ -38,7 +36,7 @@ type Extra struct { func (i *Extra) MarshalRLPTo(dst []byte) []byte { ar := &fastrlp.Arena{} - return i.MarshalRLPWith(ar).MarshalTo(dst) + return append(make([]byte, ExtraVanity), i.MarshalRLPWith(ar).MarshalTo(dst)...) } // MarshalRLPWith defines the marshal function implementation for Extra @@ -52,21 +50,14 @@ func (i *Extra) MarshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value { vv.Set(i.Validators.MarshalRLPWith(ar)) } - // Seal - if len(i.Seal) == 0 { - vv.Set(ar.NewNull()) - } else { - vv.Set(ar.NewBytes(i.Seal)) - } - - // ParentSeal + // Parent Signatures if i.Parent == nil { vv.Set(ar.NewNullArray()) } else { vv.Set(i.Parent.MarshalRLPWith(ar)) } - // CommittedSeal + // Committed Signatures if i.Committed == nil { vv.Set(ar.NewNullArray()) } else { @@ -85,12 +76,12 @@ func (i *Extra) MarshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value { // UnmarshalRLP defines the unmarshal function wrapper for Extra func (i *Extra) UnmarshalRLP(input []byte) error { - return fastrlp.UnmarshalRLP(input, i) + return fastrlp.UnmarshalRLP(input[ExtraVanity:], i) } // UnmarshalRLPWith defines the unmarshal implementation for Extra func (i *Extra) UnmarshalRLPWith(v *fastrlp.Value) error { - const expectedElements = 5 + const expectedElements = 4 elems, err := v.GetElems() if err != nil { @@ -103,39 +94,32 @@ func (i *Extra) UnmarshalRLPWith(v *fastrlp.Value) error { // Validators if elems[0].Elems() > 0 { - i.Validators = &ValidatorSetDelta{} + i.Validators = &validator.ValidatorSetDelta{} if err := i.Validators.UnmarshalRLPWith(elems[0]); err != nil { return err } } - // Seal - if elems[1].Len() > 0 { - if i.Seal, err = elems[1].GetBytes(i.Seal); err != nil { - return err - } - } - - // Parent - if elems[2].Elems() > 0 { + // Parent Signatures + if elems[1].Elems() > 0 { i.Parent = &Signature{} - if err := i.Parent.UnmarshalRLPWith(elems[2]); err != nil { + if err := i.Parent.UnmarshalRLPWith(elems[1]); err != nil { return err } } - // Committed - if elems[3].Elems() > 0 { + // Committed Signatures + if elems[2].Elems() > 0 { i.Committed = &Signature{} - if err := i.Committed.UnmarshalRLPWith(elems[3]); err != nil { + if err := i.Committed.UnmarshalRLPWith(elems[2]); err != nil { return err } } // Checkpoint - if elems[4].Elems() > 0 { + if elems[3].Elems() > 0 { i.Checkpoint = &CheckpointData{} - if err := i.Checkpoint.UnmarshalRLPWith(elems[4]); err != nil { + if err := i.Checkpoint.UnmarshalRLPWith(elems[3]); err != nil { return err } } @@ -186,21 +170,6 @@ func (i *Extra) ValidateFinalizedData(header *types.Header, parent *types.Header return i.Checkpoint.ValidateBasic(parentExtra.Checkpoint) } -// ValidateDelta validates validator set delta provided in the Extra -// with the one being calculated by the validator itself -func (i *Extra) ValidateDelta(oldValidators AccountSet, newValidators AccountSet) error { - delta, err := createValidatorSetDelta(oldValidators, newValidators) - if err != nil { - return err - } - - if !i.Validators.Equals(delta) { - return fmt.Errorf("validator set delta is invalid") - } - - return nil -} - // ValidateParentSignatures validates signatures for parent block func (i *Extra) ValidateParentSignatures(blockNumber uint64, consensusBackend polybftBackend, parents []*types.Header, parent *types.Header, parentExtra *Extra, chainID uint64, domain []byte, logger hclog.Logger) error { @@ -236,190 +205,6 @@ func (i *Extra) ValidateParentSignatures(blockNumber uint64, consensusBackend po return nil } -// createValidatorSetDelta calculates ValidatorSetDelta based on the provided old and new validator sets -func createValidatorSetDelta(oldValidatorSet, newValidatorSet AccountSet) (*ValidatorSetDelta, error) { - var addedValidators, updatedValidators AccountSet - - oldValidatorSetMap := make(map[types.Address]*ValidatorMetadata) - removedValidators := map[types.Address]int{} - - for i, validator := range oldValidatorSet { - if (validator.Address != types.Address{}) { - removedValidators[validator.Address] = i - oldValidatorSetMap[validator.Address] = validator - } - } - - for _, newValidator := range newValidatorSet { - // Check if the validator is among both old and new validator set - oldValidator, validatorExists := oldValidatorSetMap[newValidator.Address] - if validatorExists { - if !oldValidator.EqualAddressAndBlsKey(newValidator) { - return nil, fmt.Errorf("validator '%s' found in both old and new validator set, but its BLS keys differ", - newValidator.Address.String()) - } - - // If it is, then discard it from removed validators... - delete(removedValidators, newValidator.Address) - - if !oldValidator.Equals(newValidator) { - updatedValidators = append(updatedValidators, newValidator) - } - } else { - // ...otherwise it is added - addedValidators = append(addedValidators, newValidator) - } - } - - removedValsBitmap := bitmap.Bitmap{} - for _, i := range removedValidators { - removedValsBitmap.Set(uint64(i)) - } - - delta := &ValidatorSetDelta{ - Added: addedValidators, - Updated: updatedValidators, - Removed: removedValsBitmap, - } - - return delta, nil -} - -// ValidatorSetDelta holds information about added and removed validators compared to the previous epoch -type ValidatorSetDelta struct { - // Added is the slice of added validators - Added AccountSet - // Updated is the slice of updated valiadtors - Updated AccountSet - // Removed is a bitmap of the validators removed from the set - Removed bitmap.Bitmap -} - -// Equals checks validator set delta equality -func (d *ValidatorSetDelta) Equals(other *ValidatorSetDelta) bool { - if other == nil { - return false - } - - return d.Added.Equals(other.Added) && - d.Updated.Equals(other.Updated) && - bytes.Equal(d.Removed, other.Removed) -} - -// MarshalRLPWith marshals ValidatorSetDelta to RLP format -func (d *ValidatorSetDelta) MarshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value { - vv := ar.NewArray() - addedValidatorsRaw := ar.NewArray() - updatedValidatorsRaw := ar.NewArray() - - for _, validatorAccount := range d.Added { - addedValidatorsRaw.Set(validatorAccount.MarshalRLPWith(ar)) - } - - for _, validatorAccount := range d.Updated { - updatedValidatorsRaw.Set(validatorAccount.MarshalRLPWith(ar)) - } - - vv.Set(addedValidatorsRaw) // added - vv.Set(updatedValidatorsRaw) // updated - vv.Set(ar.NewCopyBytes(d.Removed)) // removed - - return vv -} - -// UnmarshalRLPWith unmarshals ValidatorSetDelta from RLP format -func (d *ValidatorSetDelta) UnmarshalRLPWith(v *fastrlp.Value) error { - elems, err := v.GetElems() - if err != nil { - return err - } - - if len(elems) == 0 { - return nil - } else if num := len(elems); num != 3 { - return fmt.Errorf("incorrect elements count to decode validator set delta, expected 3 but found %d", num) - } - - // Validators (added) - { - validatorsRaw, err := elems[0].GetElems() - if err != nil { - return fmt.Errorf("array expected for added validators") - } - - d.Added, err = unmarshalValidators(validatorsRaw) - if err != nil { - return err - } - } - - // Validators (updated) - { - validatorsRaw, err := elems[1].GetElems() - if err != nil { - return fmt.Errorf("array expected for updated validators") - } - - d.Updated, err = unmarshalValidators(validatorsRaw) - if err != nil { - return err - } - } - - // Bitmap (removed) - { - dst, err := elems[2].GetBytes(nil) - if err != nil { - return err - } - - d.Removed = bitmap.Bitmap(dst) - } - - return nil -} - -// unmarshalValidators unmarshals RLP encoded validators and returns AccountSet instance -func unmarshalValidators(validatorsRaw []*fastrlp.Value) (AccountSet, error) { - if len(validatorsRaw) == 0 { - return nil, nil - } - - validators := make(AccountSet, len(validatorsRaw)) - - for i, validatorRaw := range validatorsRaw { - acc := &ValidatorMetadata{} - if err := acc.UnmarshalRLPWith(validatorRaw); err != nil { - return nil, err - } - - validators[i] = acc - } - - return validators, nil -} - -// IsEmpty returns indication whether delta is empty (namely added, updated slices and removed bitmap are empty) -func (d *ValidatorSetDelta) IsEmpty() bool { - return len(d.Added) == 0 && - len(d.Updated) == 0 && - d.Removed.Len() == 0 -} - -// Copy creates deep copy of ValidatorSetDelta -func (d *ValidatorSetDelta) Copy() *ValidatorSetDelta { - added := d.Added.Copy() - removed := make([]byte, len(d.Removed)) - copy(removed, d.Removed) - - return &ValidatorSetDelta{Added: added, Removed: removed} -} - -// fmt.Stringer interface implementation -func (d *ValidatorSetDelta) String() string { - return fmt.Sprintf("Added: \n%v Removed: %v\n Updated: \n%v", d.Added, d.Removed, d.Updated) -} - // Signature represents aggregated signatures of signers accompanied with a bitmap // (in order to be able to determine identities of each signer) type Signature struct { @@ -471,13 +256,13 @@ func (s *Signature) UnmarshalRLPWith(v *fastrlp.Value) error { } // Verify is used to verify aggregated signature based on current validator set, message hash and domain -func (s *Signature) Verify(validators AccountSet, hash types.Hash, domain []byte, logger hclog.Logger) error { +func (s *Signature) Verify(validators validator.AccountSet, hash types.Hash, domain []byte, logger hclog.Logger) error { signers, err := validators.GetFilteredValidators(s.Bitmap) if err != nil { return err } - validatorSet := NewValidatorSet(validators, logger) + validatorSet := validator.NewValidatorSet(validators, logger) if !validatorSet.HasQuorum(signers.GetAddressesAsSet()) { return fmt.Errorf("quorum not reached") } @@ -641,7 +426,8 @@ func (c *CheckpointData) ValidateBasic(parentCheckpoint *CheckpointData) error { // Validate encapsulates validation logic for checkpoint data // (with regards to current and next epoch validators) func (c *CheckpointData) Validate(parentCheckpoint *CheckpointData, - currentValidators AccountSet, nextValidators AccountSet) error { + currentValidators validator.AccountSet, nextValidators validator.AccountSet, + exitRootHash types.Hash) error { if err := c.ValidateBasic(parentCheckpoint); err != nil { return err } @@ -674,6 +460,12 @@ func (c *CheckpointData) Validate(parentCheckpoint *CheckpointData, return fmt.Errorf("epoch number should not change for epoch-ending block") } + // exit root hash of proposer and + // validator that validates proposal have to match + if exitRootHash != c.EventRoot { + return fmt.Errorf("exit root hash not as expected") + } + return nil } @@ -689,7 +481,6 @@ func GetIbftExtraClean(extraRaw []byte) ([]byte, error) { Parent: extra.Parent, Validators: extra.Validators, Checkpoint: extra.Checkpoint, - Seal: []byte{}, Committed: &Signature{}, } @@ -697,20 +488,19 @@ func GetIbftExtraClean(extraRaw []byte) ([]byte, error) { } // GetIbftExtra returns the istanbul extra data field from the passed in header -func GetIbftExtra(extraB []byte) (*Extra, error) { - if len(extraB) < ExtraVanity { - return nil, fmt.Errorf("wrong extra size: %d", len(extraB)) +func GetIbftExtra(extraRaw []byte) (*Extra, error) { + if len(extraRaw) < ExtraVanity { + return nil, fmt.Errorf("wrong extra size: %d", len(extraRaw)) } - data := extraB[ExtraVanity:] extra := &Extra{} - if err := extra.UnmarshalRLP(data); err != nil { + if err := extra.UnmarshalRLP(extraRaw); err != nil { return nil, err } if extra.Validators == nil { - extra.Validators = &ValidatorSetDelta{} + extra.Validators = &validator.ValidatorSetDelta{} } return extra, nil diff --git a/consensus/polybft/extra_test.go b/consensus/polybft/extra_test.go index 1476611ff6..53bac6ca83 100644 --- a/consensus/polybft/extra_test.go +++ b/consensus/polybft/extra_test.go @@ -11,7 +11,9 @@ import ( "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" + "github.com/0xPolygon/polygon-edge/crypto" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/assert" @@ -23,11 +25,19 @@ import ( func TestExtra_Encoding(t *testing.T) { t.Parallel() - parentStr := []byte("Here is the parent signature") - committedStr := []byte("Here is the committed signature") - bitmapStr := []byte("Here are the bitmap bytes") + digest := crypto.Keccak256([]byte("Dummy content to sign")) + keys := createRandomTestKeys(t, 2) + parentSig, err := keys[0].Sign(digest) + require.NoError(t, err) + + committedSig, err := keys[1].Sign(digest) + require.NoError(t, err) - addedValidators := newTestValidatorsWithAliases(t, []string{"A", "B", "C"}).getPublicIdentities() + bmp := bitmap.Bitmap{} + bmp.Set(1) + bmp.Set(4) + + addedValidators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C"}).GetPublicIdentities() removedValidators := bitmap.Bitmap{} removedValidators.Set(2) @@ -41,20 +51,19 @@ func TestExtra_Encoding(t *testing.T) { }, { &Extra{ - Validators: &ValidatorSetDelta{}, + Validators: &validator.ValidatorSetDelta{}, Parent: &Signature{}, Committed: &Signature{}, }, }, { &Extra{ - Validators: &ValidatorSetDelta{}, - Seal: []byte{3, 4}, + Validators: &validator.ValidatorSetDelta{}, }, }, { &Extra{ - Validators: &ValidatorSetDelta{ + Validators: &validator.ValidatorSetDelta{ Added: addedValidators, }, Parent: &Signature{}, @@ -63,34 +72,34 @@ func TestExtra_Encoding(t *testing.T) { }, { &Extra{ - Validators: &ValidatorSetDelta{ + Validators: &validator.ValidatorSetDelta{ Removed: removedValidators, }, - Parent: &Signature{AggregatedSignature: parentStr, Bitmap: bitmapStr}, + Parent: &Signature{AggregatedSignature: parentSig, Bitmap: bmp}, Committed: &Signature{}, }, }, { &Extra{ - Validators: &ValidatorSetDelta{ + Validators: &validator.ValidatorSetDelta{ Added: addedValidators, Updated: addedValidators[1:], Removed: removedValidators, }, Parent: &Signature{}, - Committed: &Signature{AggregatedSignature: committedStr, Bitmap: bitmapStr}, + Committed: &Signature{AggregatedSignature: committedSig, Bitmap: bmp}, }, }, { &Extra{ - Parent: &Signature{AggregatedSignature: parentStr, Bitmap: bitmapStr}, - Committed: &Signature{AggregatedSignature: committedStr, Bitmap: bitmapStr}, + Parent: &Signature{AggregatedSignature: parentSig, Bitmap: bmp}, + Committed: &Signature{AggregatedSignature: committedSig, Bitmap: bmp}, }, }, { &Extra{ - Parent: &Signature{AggregatedSignature: parentStr, Bitmap: bitmapStr}, - Committed: &Signature{AggregatedSignature: committedStr, Bitmap: bitmapStr}, + Parent: &Signature{AggregatedSignature: parentSig, Bitmap: bmp}, + Committed: &Signature{AggregatedSignature: committedSig, Bitmap: bmp}, Checkpoint: &CheckpointData{ BlockRound: 0, EpochNumber: 3, @@ -126,7 +135,7 @@ func TestExtra_UnmarshalRLPWith_NegativeCases(t *testing.T) { extra := &Extra{} ar := &fastrlp.Arena{} - require.ErrorContains(t, extra.UnmarshalRLPWith(ar.NewArray()), "incorrect elements count to decode Extra, expected 5 but found 0") + require.ErrorContains(t, extra.UnmarshalRLPWith(ar.NewArray()), "incorrect elements count to decode Extra, expected 4 but found 0") }) t.Run("Incorrect ValidatorSetDelta marshalled", func(t *testing.T) { @@ -150,9 +159,8 @@ func TestExtra_UnmarshalRLPWith_NegativeCases(t *testing.T) { extra := &Extra{} ar := &fastrlp.Arena{} extraMarshalled := ar.NewArray() - deltaMarshalled := new(ValidatorSetDelta).MarshalRLPWith(ar) + deltaMarshalled := new(validator.ValidatorSetDelta).MarshalRLPWith(ar) extraMarshalled.Set(deltaMarshalled) // ValidatorSetDelta - extraMarshalled.Set(ar.NewNull()) // Seal extraMarshalled.Set(ar.NewBytes([]byte{})) // Parent extraMarshalled.Set(ar.NewBytes([]byte{})) // Committed require.Error(t, extra.UnmarshalRLPWith(extraMarshalled)) @@ -164,7 +172,7 @@ func TestExtra_UnmarshalRLPWith_NegativeCases(t *testing.T) { extra := &Extra{} ar := &fastrlp.Arena{} extraMarshalled := ar.NewArray() - deltaMarshalled := new(ValidatorSetDelta).MarshalRLPWith(ar) + deltaMarshalled := new(validator.ValidatorSetDelta).MarshalRLPWith(ar) extraMarshalled.Set(deltaMarshalled) // ValidatorSetDelta extraMarshalled.Set(ar.NewBytes([]byte{})) // Seal // Parent @@ -181,7 +189,7 @@ func TestExtra_UnmarshalRLPWith_NegativeCases(t *testing.T) { extra := &Extra{} ar := &fastrlp.Arena{} extraMarshalled := ar.NewArray() - deltaMarshalled := new(ValidatorSetDelta).MarshalRLPWith(ar) + deltaMarshalled := new(validator.ValidatorSetDelta).MarshalRLPWith(ar) extraMarshalled.Set(deltaMarshalled) // ValidatorSetDelta extraMarshalled.Set(ar.NewBytes([]byte{})) // Seal @@ -204,7 +212,7 @@ func TestExtra_UnmarshalRLPWith_NegativeCases(t *testing.T) { ar := &fastrlp.Arena{} extraMarshalled := ar.NewArray() - deltaMarshalled := new(ValidatorSetDelta).MarshalRLPWith(ar) + deltaMarshalled := new(validator.ValidatorSetDelta).MarshalRLPWith(ar) extraMarshalled.Set(deltaMarshalled) // ValidatorSetDelta extraMarshalled.Set(ar.NewBytes([]byte{})) // Seal @@ -246,7 +254,7 @@ func TestExtra_ValidateFinalizedData_UnhappyPath(t *testing.T) { Hash: types.BytesToHash(generateRandomBytes(t)), } - validators := newTestValidators(t, 6) + validators := validator.NewTestValidators(t, 6) polyBackendMock := new(polybftBackendMock) polyBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(nil, errors.New("validators not found")) @@ -277,9 +285,9 @@ func TestExtra_ValidateFinalizedData_UnhappyPath(t *testing.T) { // failed to verify signatures (quorum not reached) polyBackendMock = new(polybftBackendMock) - polyBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.getPublicIdentities()) + polyBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.GetPublicIdentities()) - noQuorumSignature := createSignature(t, validators.getPrivateIdentities("0", "1"), types.BytesToHash([]byte("FooBar")), bls.DomainCheckpointManager) + noQuorumSignature := createSignature(t, validators.GetPrivateIdentities("0", "1"), types.BytesToHash([]byte("FooBar")), bls.DomainCheckpointManager) extra = &Extra{Committed: noQuorumSignature, Checkpoint: checkpoint} checkpointHash, err := checkpoint.Hash(chainID, headerNum, header.Hash) require.NoError(t, err) @@ -290,7 +298,7 @@ func TestExtra_ValidateFinalizedData_UnhappyPath(t *testing.T) { fmt.Sprintf("failed to verify signatures for block %d (proposal hash %s): quorum not reached", headerNum, checkpointHash)) // incorrect parent extra size - validSignature := createSignature(t, validators.getPrivateIdentities(), checkpointHash, bls.DomainCheckpointManager) + validSignature := createSignature(t, validators.GetPrivateIdentities(), checkpointHash, bls.DomainCheckpointManager) extra = &Extra{Committed: validSignature, Checkpoint: checkpoint} err = extra.ValidateFinalizedData( header, parent, nil, chainID, polyBackendMock, bls.DomainCheckpointManager, hclog.NewNullLogger()) @@ -321,9 +329,9 @@ func TestExtra_ValidateParentSignatures(t *testing.T) { require.ErrorContains(t, err, fmt.Sprintf("failed to verify signatures for parent of block %d because signatures are not present", headerNum)) // validators not found - validators := newTestValidators(t, 5) + validators := validator.NewTestValidators(t, 5) incorrectHash := types.BytesToHash([]byte("Hello World")) - invalidSig := createSignature(t, validators.getPrivateIdentities(), incorrectHash, bls.DomainCheckpointManager) + invalidSig := createSignature(t, validators.GetPrivateIdentities(), incorrectHash, bls.DomainCheckpointManager) extra = &Extra{Parent: invalidSig} err = extra.ValidateParentSignatures( headerNum, polyBackendMock, nil, nil, nil, chainID, bls.DomainCheckpointManager, hclog.NewNullLogger()) @@ -332,7 +340,7 @@ func TestExtra_ValidateParentSignatures(t *testing.T) { // incorrect hash is signed polyBackendMock = new(polybftBackendMock) - polyBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.getPublicIdentities()) + polyBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.GetPublicIdentities()) parent := &types.Header{Number: headerNum - 1, Hash: types.BytesToHash(generateRandomBytes(t))} parentCheckpoint := &CheckpointData{EpochNumber: 3, BlockRound: 5} @@ -347,7 +355,7 @@ func TestExtra_ValidateParentSignatures(t *testing.T) { fmt.Sprintf("failed to verify signatures for parent of block %d (proposal hash: %s): could not verify aggregated signature", headerNum, parentCheckpointHash)) // valid signature provided - validSig := createSignature(t, validators.getPrivateIdentities(), parentCheckpointHash, bls.DomainCheckpointManager) + validSig := createSignature(t, validators.GetPrivateIdentities(), parentCheckpointHash, bls.DomainCheckpointManager) extra = &Extra{Parent: validSig} err = extra.ValidateParentSignatures( headerNum, polyBackendMock, nil, parent, parentExtra, chainID, bls.DomainCheckpointManager, hclog.NewNullLogger()) @@ -363,18 +371,18 @@ func TestSignature_Verify(t *testing.T) { numValidators := 100 msgHash := types.Hash{0x1} - vals := newTestValidators(t, numValidators) - validatorsMetadata := vals.getPublicIdentities() - validatorSet := vals.toValidatorSet() + vals := validator.NewTestValidators(t, numValidators) + validatorsMetadata := vals.GetPublicIdentities() + validatorSet := vals.ToValidatorSet() var signatures bls.Signatures bitmap := bitmap.Bitmap{} signers := make(map[types.Address]struct{}, len(validatorsMetadata)) - for i, val := range vals.getValidators() { + for i, val := range vals.GetValidators() { bitmap.Set(uint64(i)) - tempSign, err := val.account.Bls.Sign(msgHash[:], bls.DomainCheckpointManager) + tempSign, err := val.Account.Bls.Sign(msgHash[:], bls.DomainCheckpointManager) require.NoError(t, err) signatures = append(signatures, tempSign) @@ -400,7 +408,7 @@ func TestSignature_Verify(t *testing.T) { t.Run("Invalid bitmap provided", func(t *testing.T) { t.Parallel() - validatorSet := newTestValidators(t, 3).getPublicIdentities() + validatorSet := validator.NewTestValidators(t, 3).GetPublicIdentities() bmp := bitmap.Bitmap{} // Make bitmap invalid, by setting some flag larger than length of validator set to 1 @@ -448,7 +456,7 @@ func TestSignature_VerifyRandom(t *testing.T) { t.Parallel() numValidators := 100 - vals := newTestValidators(t, numValidators) + vals := validator.NewTestValidators(t, numValidators) msgHash := types.Hash{0x1} var signature bls.Signatures @@ -456,12 +464,12 @@ func TestSignature_VerifyRandom(t *testing.T) { bitmap := bitmap.Bitmap{} valIndxsRnd := mrand.Perm(numValidators)[:numValidators*2/3+1] - accounts := vals.getValidators() + accounts := vals.GetValidators() for _, index := range valIndxsRnd { bitmap.Set(uint64(index)) - tempSign, err := accounts[index].account.Bls.Sign(msgHash[:], bls.DomainCheckpointManager) + tempSign, err := accounts[index].Account.Bls.Sign(msgHash[:], bls.DomainCheckpointManager) require.NoError(t, err) signature = append(signature, tempSign) @@ -475,167 +483,10 @@ func TestSignature_VerifyRandom(t *testing.T) { Bitmap: bitmap, } - err = s.Verify(vals.getPublicIdentities(), msgHash, bls.DomainCheckpointManager, hclog.NewNullLogger()) + err = s.Verify(vals.GetPublicIdentities(), msgHash, bls.DomainCheckpointManager, hclog.NewNullLogger()) assert.NoError(t, err) } -func TestExtra_CreateValidatorSetDelta_Cases(t *testing.T) { - t.Parallel() - - cases := []struct { - name string - oldSet []string - newSet []string - added []string - updated []string - removed []uint64 - }{ - { - "Simple", - []string{"A", "B", "C", "E", "F"}, - []string{"B", "E", "H"}, - []string{"H"}, - []string{"B", "E"}, - []uint64{0, 2, 4}, - }, - } - - for _, c := range cases { - c := c - t.Run(c.name, func(t *testing.T) { - t.Parallel() - - vals := newTestValidatorsWithAliases(t, []string{}) - - for _, name := range c.oldSet { - vals.create(t, name, 1) - } - for _, name := range c.newSet { - vals.create(t, name, 1) - } - - oldValidatorSet := vals.getPublicIdentities(c.oldSet...) - // update voting power to random value - maxVotingPower := big.NewInt(100) - for _, name := range c.updated { - v := vals.getValidator(name) - vp, err := rand.Int(rand.Reader, maxVotingPower) - require.NoError(t, err) - // make sure generated voting power is different than the original one - v.votingPower += vp.Uint64() + 1 - } - newValidatorSet := vals.getPublicIdentities(c.newSet...) - - delta, err := createValidatorSetDelta(oldValidatorSet, newValidatorSet) - require.NoError(t, err) - - // added validators - require.Len(t, delta.Added, len(c.added)) - for i, name := range c.added { - require.Equal(t, delta.Added[i].Address, vals.getValidator(name).Address()) - } - - // removed validators - for _, i := range c.removed { - require.True(t, delta.Removed.IsSet(i)) - } - - // updated validators - require.Len(t, delta.Updated, len(c.updated)) - for i, name := range c.updated { - require.Equal(t, delta.Updated[i].Address, vals.getValidator(name).Address()) - } - }) - } -} - -func TestExtra_CreateValidatorSetDelta_BlsDiffer(t *testing.T) { - t.Parallel() - - vals := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) - oldValidatorSet := vals.getPublicIdentities("A", "B", "C", "D") - - // change the public bls key of 'B' - newValidatorSet := vals.getPublicIdentities("B", "E", "F") - privateKey, err := bls.GenerateBlsKey() - require.NoError(t, err) - - newValidatorSet[0].BlsKey = privateKey.PublicKey() - - _, err = createValidatorSetDelta(oldValidatorSet, newValidatorSet) - require.Error(t, err) -} - -func TestExtra_ValidateDelta(t *testing.T) { - t.Parallel() - - cases := []struct { - name string - oldValidators []string - originalNewValidators []string - changedNewValidators []string - updatedVotingPowers []*big.Int - expectError bool - }{ - { - name: "Valid delta provided", - oldValidators: []string{"A", "B", "F"}, - originalNewValidators: []string{"B", "E", "F"}, - expectError: false, - }, - { - name: "Different added validators", - oldValidators: []string{"A", "B", "F"}, - originalNewValidators: []string{"A", "B", "F", "D"}, - changedNewValidators: []string{"A", "B", "F", "E"}, - expectError: true, - }, - { - name: "Different removed validators", - oldValidators: []string{"A", "B", "F"}, - originalNewValidators: []string{"A", "B"}, - changedNewValidators: []string{"A", "F"}, - expectError: true, - }, - { - name: "Different updated validators", - oldValidators: []string{"A", "B", "F"}, - originalNewValidators: []string{"A", "B", "F"}, - changedNewValidators: []string{"A", "B", "F"}, - updatedVotingPowers: []*big.Int{big.NewInt(100)}, - expectError: true, - }, - } - - for _, c := range cases { - c := c - t.Run(c.name, func(t *testing.T) { - t.Parallel() - - vals := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) - oldValidators := vals.getPublicIdentities(c.oldValidators...) - newValidators := vals.getPublicIdentities(c.originalNewValidators...) - for i, votingPower := range c.updatedVotingPowers { - newValidators[i].VotingPower = votingPower - } - - delta, err := createValidatorSetDelta(oldValidators, newValidators) - require.NoError(t, err) - - extra := &Extra{Validators: delta} - - if c.changedNewValidators != nil { - newValidators = vals.getPublicIdentities(c.changedNewValidators...) - } - - if c.expectError { - require.Error(t, extra.ValidateDelta(oldValidators, newValidators)) - } else { - require.NoError(t, extra.ValidateDelta(oldValidators, newValidators)) - } - }) - } -} func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { t.Parallel() @@ -643,21 +494,19 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { t.Parallel() const validatorsCount = 7 - vals := newTestValidators(t, validatorsCount) - - polyBftConfig := PolyBFTConfig{InitialValidatorSet: vals.getParamValidators()} + vals := validator.NewTestValidators(t, validatorsCount) - delta := &ValidatorSetDelta{ - Added: make(AccountSet, validatorsCount), + delta := &validator.ValidatorSetDelta{ + Added: make(validator.AccountSet, validatorsCount), Removed: bitmap.Bitmap{}, } var i int - for _, validator := range vals.validators { - delta.Added[i] = &ValidatorMetadata{ - Address: types.Address(validator.account.Ecdsa.Address()), - BlsKey: validator.account.Bls.PublicKey(), - VotingPower: new(big.Int).SetUint64(validator.votingPower), + for _, val := range vals.Validators { + delta.Added[i] = &validator.ValidatorMetadata{ + Address: types.Address(val.Account.Ecdsa.Address()), + BlsKey: val.Account.Bls.PublicKey(), + VotingPower: new(big.Int).SetUint64(val.VotingPower), } i++ } @@ -665,10 +514,7 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { extra := Extra{Validators: delta} genesis := &chain.Genesis{ - Config: &chain.Params{Engine: map[string]interface{}{ - "polybft": polyBftConfig, - }}, - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + ExtraData: extra.MarshalRLPTo(nil), } genesisExtra, err := GetIbftExtra(genesis.ExtraData) @@ -680,13 +526,7 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { t.Run("Invalid Extra data", func(t *testing.T) { t.Parallel() - validators := newTestValidators(t, 5) - polyBftConfig := PolyBFTConfig{InitialValidatorSet: validators.getParamValidators()} - genesis := &chain.Genesis{ - Config: &chain.Params{Engine: map[string]interface{}{ - "polybft": polyBftConfig, - }}, ExtraData: append(make([]byte, ExtraVanity), []byte{0x2, 0x3}...), } @@ -696,143 +536,56 @@ func TestExtra_InitGenesisValidatorsDelta(t *testing.T) { }) } -func TestValidatorSetDelta_Copy(t *testing.T) { +func Test_GetIbftExtraClean(t *testing.T) { t.Parallel() - const ( - originalValidatorsCount = 10 - addedValidatorsCount = 2 - ) - - oldValidatorSet := newTestValidators(t, originalValidatorsCount).getPublicIdentities() - newValidatorSet := oldValidatorSet[:len(oldValidatorSet)-2] - originalDelta, err := createValidatorSetDelta(oldValidatorSet, newValidatorSet) + key, err := wallet.GenerateAccount() require.NoError(t, err) - require.NotNil(t, originalDelta) - require.Empty(t, originalDelta.Added) - - copiedDelta := originalDelta.Copy() - require.NotNil(t, copiedDelta) - require.NotSame(t, originalDelta, copiedDelta) - require.NotEqual(t, originalDelta, copiedDelta) - require.Empty(t, copiedDelta.Added) - require.Equal(t, copiedDelta.Removed.Len(), originalDelta.Removed.Len()) - - newValidators := newTestValidators(t, addedValidatorsCount).getPublicIdentities() - copiedDelta.Added = append(copiedDelta.Added, newValidators...) - require.Empty(t, originalDelta.Added) - require.Len(t, copiedDelta.Added, addedValidatorsCount) - require.Equal(t, copiedDelta.Removed.Len(), originalDelta.Removed.Len()) -} - -func TestValidatorSetDelta_UnmarshalRLPWith_NegativeCases(t *testing.T) { - t.Parallel() - t.Run("Incorrect RLP value type provided", func(t *testing.T) { - t.Parallel() - - ar := &fastrlp.Arena{} - delta := &ValidatorSetDelta{} - require.ErrorContains(t, delta.UnmarshalRLPWith(ar.NewNull()), "value is not of type array") - }) - - t.Run("Empty RLP array provided", func(t *testing.T) { - t.Parallel() - - ar := &fastrlp.Arena{} - delta := &ValidatorSetDelta{} - require.NoError(t, delta.UnmarshalRLPWith(ar.NewArray())) - }) - - t.Run("Incorrect RLP array size", func(t *testing.T) { - t.Parallel() - - ar := &fastrlp.Arena{} - deltaMarshalled := ar.NewArray() - deltaMarshalled.Set(ar.NewBytes([]byte{0x59})) - deltaMarshalled.Set(ar.NewBytes([]byte{0x33})) - deltaMarshalled.Set(ar.NewBytes([]byte{0x26})) - deltaMarshalled.Set(ar.NewBytes([]byte{0x74})) - delta := &ValidatorSetDelta{} - require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "incorrect elements count to decode validator set delta, expected 3 but found 4") - }) - - t.Run("Incorrect RLP value type for Added field", func(t *testing.T) { - t.Parallel() - - ar := &fastrlp.Arena{} - deltaMarshalled := ar.NewArray() - deltaMarshalled.Set(ar.NewBytes([]byte{0x59})) - deltaMarshalled.Set(ar.NewBytes([]byte{0x33})) - deltaMarshalled.Set(ar.NewBytes([]byte{0x27})) - delta := &ValidatorSetDelta{} - require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "array expected for added validators") - }) - - t.Run("Incorrect RLP value type for ValidatorMetadata in Added field", func(t *testing.T) { - t.Parallel() - - ar := &fastrlp.Arena{} - deltaMarshalled := ar.NewArray() - addedArray := ar.NewArray() - addedArray.Set(ar.NewNull()) - deltaMarshalled.Set(addedArray) - deltaMarshalled.Set(ar.NewNullArray()) - deltaMarshalled.Set(ar.NewNull()) - delta := &ValidatorSetDelta{} - require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "value is not of type array") - }) - - t.Run("Incorrect RLP value type for Removed field", func(t *testing.T) { - t.Parallel() - - ar := &fastrlp.Arena{} - deltaMarshalled := ar.NewArray() - addedValidators := newTestValidators(t, 3).getPublicIdentities() - addedArray := ar.NewArray() - updatedArray := ar.NewArray() - for _, validator := range addedValidators { - addedArray.Set(validator.MarshalRLPWith(ar)) - } - for _, validator := range addedValidators { - votingPower, err := rand.Int(rand.Reader, big.NewInt(100)) - require.NoError(t, err) - - validator.VotingPower = new(big.Int).Set(votingPower) - updatedArray.Set(validator.MarshalRLPWith(ar)) - } - deltaMarshalled.Set(addedArray) - deltaMarshalled.Set(updatedArray) - deltaMarshalled.Set(ar.NewNull()) - delta := &ValidatorSetDelta{} - require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "value is not of type bytes") - }) - - t.Run("Incorrect RLP value type for Updated field", func(t *testing.T) { - t.Parallel() - - ar := &fastrlp.Arena{} - deltaMarshalled := ar.NewArray() - deltaMarshalled.Set(ar.NewArray()) - deltaMarshalled.Set(ar.NewBytes([]byte{0x33})) - deltaMarshalled.Set(ar.NewNull()) - delta := &ValidatorSetDelta{} - require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "array expected for updated validators") - }) + extra := &Extra{ + Validators: &validator.ValidatorSetDelta{ + Added: validator.AccountSet{ + &validator.ValidatorMetadata{ + Address: types.BytesToAddress([]byte{11, 22}), + BlsKey: key.Bls.PublicKey(), + VotingPower: new(big.Int).SetUint64(1000), + IsActive: true, + }, + }, + }, + Committed: &Signature{ + AggregatedSignature: []byte{23, 24}, + Bitmap: []byte{11}, + }, + Parent: &Signature{ + AggregatedSignature: []byte{0, 1}, + Bitmap: []byte{1}, + }, + Checkpoint: &CheckpointData{ + BlockRound: 1, + EpochNumber: 1, + CurrentValidatorsHash: types.BytesToHash([]byte{2, 3}), + NextValidatorsHash: types.BytesToHash([]byte{4, 5}), + EventRoot: types.BytesToHash([]byte{6, 7}), + }, + } - t.Run("Incorrect RLP value type for ValidatorMetadata in Updated field", func(t *testing.T) { - t.Parallel() + extraClean, err := GetIbftExtraClean(extra.MarshalRLPTo(nil)) + require.NoError(t, err) - ar := &fastrlp.Arena{} - deltaMarshalled := ar.NewArray() - updatedArray := ar.NewArray() - updatedArray.Set(ar.NewNull()) - deltaMarshalled.Set(ar.NewArray()) - deltaMarshalled.Set(updatedArray) - deltaMarshalled.Set(ar.NewNull()) - delta := &ValidatorSetDelta{} - require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "value is not of type array") - }) + extraTwo := &Extra{} + require.NoError(t, extraTwo.UnmarshalRLP(extraClean)) + require.True(t, extra.Validators.Equals(extra.Validators)) + require.Equal(t, extra.Checkpoint.BlockRound, extraTwo.Checkpoint.BlockRound) + require.Equal(t, extra.Checkpoint.EpochNumber, extraTwo.Checkpoint.EpochNumber) + require.Equal(t, extra.Checkpoint.CurrentValidatorsHash, extraTwo.Checkpoint.CurrentValidatorsHash) + require.Equal(t, extra.Checkpoint.NextValidatorsHash, extraTwo.Checkpoint.NextValidatorsHash) + require.Equal(t, extra.Checkpoint.NextValidatorsHash, extraTwo.Checkpoint.NextValidatorsHash) + require.Equal(t, extra.Parent.AggregatedSignature, extraTwo.Parent.AggregatedSignature) + require.Equal(t, extra.Parent.Bitmap, extraTwo.Parent.Bitmap) + + require.Nil(t, extraTwo.Committed.AggregatedSignature) + require.Nil(t, extraTwo.Committed.Bitmap) } func Test_GetIbftExtraClean_Fail(t *testing.T) { @@ -876,8 +629,8 @@ func TestCheckpointData_Hash(t *testing.T) { func TestCheckpointData_Validate(t *testing.T) { t.Parallel() - currentValidators := newTestValidators(t, 5).getPublicIdentities() - nextValidators := newTestValidators(t, 3).getPublicIdentities() + currentValidators := validator.NewTestValidators(t, 5).GetPublicIdentities() + nextValidators := validator.NewTestValidators(t, 3).GetPublicIdentities() currentValidatorsHash, err := currentValidators.Hash() require.NoError(t, err) @@ -889,10 +642,11 @@ func TestCheckpointData_Validate(t *testing.T) { name string parentEpochNumber uint64 epochNumber uint64 - currentValidators AccountSet - nextValidators AccountSet + currentValidators validator.AccountSet + nextValidators validator.AccountSet currentValidatorsHash types.Hash nextValidatorsHash types.Hash + exitRootHash types.Hash errString string }{ { @@ -960,6 +714,17 @@ func TestCheckpointData_Validate(t *testing.T) { nextValidatorsHash: nextValidatorsHash, errString: "epoch number should not change for epoch-ending block", }, + { + name: "Invalid exit root hash", + parentEpochNumber: 2, + epochNumber: 2, + currentValidators: currentValidators, + nextValidators: currentValidators, + currentValidatorsHash: currentValidatorsHash, + nextValidatorsHash: currentValidatorsHash, + exitRootHash: types.BytesToHash([]byte{0, 1, 2, 3, 4, 5, 6, 7}), + errString: "exit root hash not as expected", + }, } for _, c := range cases { @@ -970,9 +735,10 @@ func TestCheckpointData_Validate(t *testing.T) { EpochNumber: c.epochNumber, CurrentValidatorsHash: c.currentValidatorsHash, NextValidatorsHash: c.nextValidatorsHash, + EventRoot: c.exitRootHash, } parentCheckpoint := &CheckpointData{EpochNumber: c.parentEpochNumber} - err := checkpoint.Validate(parentCheckpoint, c.currentValidators, c.nextValidators) + err := checkpoint.Validate(parentCheckpoint, c.currentValidators, c.nextValidators, types.ZeroHash) if c.errString != "" { require.ErrorContains(t, err, c.errString) @@ -986,11 +752,11 @@ func TestCheckpointData_Validate(t *testing.T) { func TestCheckpointData_Copy(t *testing.T) { t.Parallel() - validatorAccs := newTestValidators(t, 5) - currentValidatorsHash, err := validatorAccs.getPublicIdentities("0", "1", "2").Hash() + validatorAccs := validator.NewTestValidators(t, 5) + currentValidatorsHash, err := validatorAccs.GetPublicIdentities("0", "1", "2").Hash() require.NoError(t, err) - nextValidatorsHash, err := validatorAccs.getPublicIdentities("1", "3", "4").Hash() + nextValidatorsHash, err := validatorAccs.GetPublicIdentities("1", "3", "4").Hash() require.NoError(t, err) eventRoot := generateRandomBytes(t) diff --git a/consensus/polybft/fsm.go b/consensus/polybft/fsm.go index 8ad9aa66a2..90fe2eb5b8 100644 --- a/consensus/polybft/fsm.go +++ b/consensus/polybft/fsm.go @@ -5,16 +5,19 @@ import ( "errors" "fmt" "math/big" + "time" "github.com/0xPolygon/go-ibft/messages" "github.com/0xPolygon/go-ibft/messages/proto" "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/state" "github.com/0xPolygon/polygon-edge/types" + "github.com/armon/go-metrics" hcf "github.com/hashicorp/go-hclog" ) @@ -30,9 +33,18 @@ type blockBuilder interface { var ( errCommitEpochTxDoesNotExist = errors.New("commit epoch transaction is not found in the epoch ending block") errCommitEpochTxNotExpected = errors.New("didn't expect commit epoch transaction in a non epoch ending block") - errCommitEpochTxSingleExpected = errors.New("only one commit epoch transaction is allowed in an epoch ending block") - errProposalDontMatch = errors.New("failed to insert proposal, because the validated proposal " + + errCommitEpochTxSingleExpected = errors.New("only one commit epoch transaction is allowed " + + "in an epoch ending block") + errDistributeRewardsTxDoesNotExist = errors.New("distribute rewards transaction is " + + "not found in the epoch ending block") + errDistributeRewardsTxNotExpected = errors.New("didn't expect distribute rewards transaction " + + "in a non epoch ending block") + errDistributeRewardsTxSingleExpected = errors.New("only one distribute rewards transaction is " + + "allowed in an epoch ending block") + errProposalDontMatch = errors.New("failed to insert proposal, because the validated proposal " + "is either nil or it does not match the received one") + errValidatorSetDeltaMismatch = errors.New("validator set delta mismatch") + errValidatorsUpdateInNonEpochEnding = errors.New("trying to update validator set in a non epoch ending block") ) type fsm struct { @@ -49,7 +61,7 @@ type fsm struct { polybftBackend polybftBackend // validators is the list of validators for this round - validators ValidatorSet + validators validator.ValidatorSet // proposerSnapshot keeps information about new proposer proposerSnapshot *ProposerSnapshot @@ -60,10 +72,14 @@ type fsm struct { // epochNumber denotes current epoch number epochNumber uint64 - // commitEpochInput holds info about validators performance during single epoch - // (namely how many times each validator signed block during epoch). + // commitEpochInput holds info about a single epoch // It is populated only for epoch-ending blocks. - commitEpochInput *contractsapi.CommitEpochChildValidatorSetFn + commitEpochInput *contractsapi.CommitEpochValidatorSetFn + + // distributeRewardsInput holds info about validators work in a single epoch + // mainly, how many blocks they signed during given epoch + // It is populated only for epoch-ending blocks. + distributeRewardsInput *contractsapi.DistributeRewardForRewardPoolFn // isEndOfEpoch indicates if epoch reached its end isEndOfEpoch bool @@ -82,10 +98,17 @@ type fsm struct { // exitEventRootHash is the calculated root hash for given checkpoint block exitEventRootHash types.Hash + + // newValidatorsDelta carries the updates of validator set on epoch ending block + newValidatorsDelta *validator.ValidatorSetDelta } // BuildProposal builds a proposal for the current round (used if proposer) func (f *fsm) BuildProposal(currentRound uint64) ([]byte, error) { + start := time.Now().UTC() + defer metrics.SetGauge([]string{consensusMetricsPrefix, "block_building_time"}, + float32(time.Now().UTC().Sub(start).Seconds())) + parent := f.parent extraParent, err := GetIbftExtra(parent.ExtraData) @@ -93,8 +116,6 @@ func (f *fsm) BuildProposal(currentRound uint64) ([]byte, error) { return nil, err } - //nolint:godox - // TODO: we will need to revisit once slashing is implemented (to be fixed in EVM-519) extra := &Extra{Parent: extraParent.Committed} // for non-epoch ending blocks, currentValidatorsHash is the same as the nextValidatorsHash nextValidators := f.validators.Accounts() @@ -112,6 +133,15 @@ func (f *fsm) BuildProposal(currentRound uint64) ([]byte, error) { if err := f.blockBuilder.WriteTx(tx); err != nil { return nil, fmt.Errorf("failed to apply commit epoch transaction: %w", err) } + + tx, err = f.createDistributeRewardsTx() + if err != nil { + return nil, err + } + + if err := f.blockBuilder.WriteTx(tx); err != nil { + return nil, fmt.Errorf("failed to apply distribute rewards transaction: %w", err) + } } if f.config.IsBridgeEnabled() { @@ -123,26 +153,13 @@ func (f *fsm) BuildProposal(currentRound uint64) ([]byte, error) { // fill the block with transactions f.blockBuilder.Fill() - // update extra validators if needed, but only after all transactions has been written - // each transaction can update state and therefore change validators stake for example if f.isEndOfEpoch { - nextValidators, err = f.getCurrentValidators(f.blockBuilder.GetState()) + nextValidators, err = nextValidators.ApplyDelta(f.newValidatorsDelta) if err != nil { return nil, err } - validatorsDelta, err := createValidatorSetDelta(f.validators.Accounts(), nextValidators) - if err != nil { - return nil, fmt.Errorf("failed to create validator set delta: %w", err) - } - - extra.Validators = validatorsDelta - f.logger.Trace("[FSM Build Proposal]", "Validators Delta", validatorsDelta) - - nextValidators, err = f.getValidatorsTransition(validatorsDelta) - if err != nil { - return nil, err - } + extra.Validators = f.newValidatorsDelta } currentValidatorsHash, err := f.validators.Accounts().Hash() @@ -167,7 +184,7 @@ func (f *fsm) BuildProposal(currentRound uint64) ([]byte, error) { "Next validators hash", nextValidatorsHash) stateBlock, err := f.blockBuilder.Build(func(h *types.Header) { - h.ExtraData = append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...) + h.ExtraData = extra.MarshalRLPTo(nil) h.MixHash = PolyBFTMixDigest }) @@ -218,23 +235,13 @@ func (f *fsm) createBridgeCommitmentTx() (*types.Transaction, error) { } // getValidatorsTransition applies delta to the current validators, -// as ChildValidatorSet SC returns validators in different order than the one kept on the Edge -func (f *fsm) getValidatorsTransition(delta *ValidatorSetDelta) (AccountSet, error) { +func (f *fsm) getValidatorsTransition(delta *validator.ValidatorSetDelta) (validator.AccountSet, error) { nextValidators, err := f.validators.Accounts().ApplyDelta(delta) if err != nil { return nil, err } - if f.logger.IsDebug() { - var buf bytes.Buffer - for _, v := range nextValidators { - if _, err := buf.WriteString(fmt.Sprintf("%s\n", v.String())); err != nil { - return nil, err - } - } - - f.logger.Debug("getValidatorsTransition", "Next validators", buf.String()) - } + f.logger.Debug("getValidatorsTransition", "Next validators", nextValidators) return nextValidators, nil } @@ -250,6 +257,17 @@ func (f *fsm) createCommitEpochTx() (*types.Transaction, error) { return createStateTransactionWithData(contracts.ValidatorSetContract, input), nil } +// createDistributeRewardsTx create a StateTransaction, which invokes RewardPool smart contract +// and sends all the necessary metadata to it. +func (f *fsm) createDistributeRewardsTx() (*types.Transaction, error) { + input, err := f.distributeRewardsInput.EncodeAbi() + if err != nil { + return nil, err + } + + return createStateTransactionWithData(contracts.RewardPoolContract, input), nil +} + // ValidateCommit is used to validate that a given commit is valid func (f *fsm) ValidateCommit(signer []byte, seal []byte, proposalHash []byte) error { from := types.BytesToAddress(signer) @@ -279,7 +297,7 @@ func (f *fsm) Validate(proposal []byte) error { } // validate header fields - if err := validateHeaderFields(f.parent, block.Header); err != nil { + if err := validateHeaderFields(f.parent, block.Header, f.config.BlockTimeDrift); err != nil { return fmt.Errorf( "failed to validate header (parent header# %d, current header#%d): %w", f.parent.Number, @@ -316,25 +334,26 @@ func (f *fsm) Validate(proposal []byte) error { } currentValidators := f.validators.Accounts() - nextValidators := f.validators.Accounts() - validateExtraData := func(transition *state.Transition) error { - if f.isEndOfEpoch { - if nextValidators, err = f.getCurrentValidators(transition); err != nil { - return err - } - } - - if err := extra.ValidateDelta(currentValidators, nextValidators); err != nil { - return err + // validate validators delta + if f.isEndOfEpoch { + if !extra.Validators.Equals(f.newValidatorsDelta) { + return errValidatorSetDeltaMismatch } + } else if !extra.Validators.IsEmpty() { + // delta should be empty in non epoch ending blocks + return errValidatorsUpdateInNonEpochEnding + } - nextValidators, err = f.getValidatorsTransition(extra.Validators) - if err != nil { - return err - } + nextValidators, err := f.getValidatorsTransition(extra.Validators) + if err != nil { + return err + } - return extra.Checkpoint.Validate(parentExtra.Checkpoint, currentValidators, nextValidators) + // validate checkpoint data + if err := extra.Checkpoint.Validate(parentExtra.Checkpoint, + currentValidators, nextValidators, f.exitEventRootHash); err != nil { + return err } if f.logger.IsTrace() && block.Number() > 1 { @@ -346,7 +365,7 @@ func (f *fsm) Validate(proposal []byte) error { f.logger.Trace("[FSM Validate]", "Block", block.Number(), "parent validators", validators) } - stateBlock, err := f.backend.ProcessBlock(f.parent, &block, validateExtraData) + stateBlock, err := f.backend.ProcessBlock(f.parent, &block) if err != nil { return err } @@ -392,8 +411,9 @@ func (f *fsm) ValidateSender(msg *proto.Message) error { func (f *fsm) VerifyStateTransactions(transactions []*types.Transaction) error { var ( - commitmentTxExists bool - commitEpochTxExists bool + commitmentTxExists bool + commitEpochTxExists bool + distributeRewardsTxExists bool ) for _, tx := range transactions { @@ -401,7 +421,7 @@ func (f *fsm) VerifyStateTransactions(transactions []*types.Transaction) error { continue } - decodedStateTx, err := decodeStateTransaction(tx.Input) // used to be Data + decodedStateTx, err := decodeStateTransaction(tx.Input) if err != nil { return fmt.Errorf("unknown state transaction: tx = %v, err = %w", tx.Hash, err) } @@ -409,39 +429,19 @@ func (f *fsm) VerifyStateTransactions(transactions []*types.Transaction) error { switch stateTxData := decodedStateTx.(type) { case *CommitmentMessageSigned: if !f.isEndOfSprint { - return fmt.Errorf("found commitment tx in block which should not contain it: tx = %v", tx.Hash) + return fmt.Errorf("found commitment tx in block which should not contain it (tx hash=%s)", tx.Hash) } if commitmentTxExists { - return fmt.Errorf("only one commitment tx is allowed per block: %v", tx.Hash) + return fmt.Errorf("only one commitment tx is allowed per block (tx hash=%s)", tx.Hash) } commitmentTxExists = true - signers, err := f.validators.Accounts().GetFilteredValidators(stateTxData.AggSignature.Bitmap) - if err != nil { - return fmt.Errorf("error for state transaction while retrieving signers: tx = %v, error = %w", tx.Hash, err) - } - - if !f.validators.HasQuorum(signers.GetAddressesAsSet()) { - return fmt.Errorf("quorum size not reached for state tx: %v", tx.Hash) - } - - aggs, err := bls.UnmarshalSignature(stateTxData.AggSignature.AggregatedSignature) - if err != nil { - return fmt.Errorf("error for state transaction while unmarshaling signature: tx = %v, error = %w", tx.Hash, err) - } - - hash, err := stateTxData.Hash() - if err != nil { + if err = verifyBridgeCommitmentTx(tx.Hash, stateTxData, f.validators); err != nil { return err } - - verified := aggs.VerifyAggregated(signers.GetBlsKeys(), hash.Bytes(), bls.DomainStateReceiver) - if !verified { - return fmt.Errorf("invalid signature for tx = %v", tx.Hash) - } - case *contractsapi.CommitEpochChildValidatorSetFn: + case *contractsapi.CommitEpochValidatorSetFn: if commitEpochTxExists { // if we already validated commit epoch tx, // that means someone added more than one commit epoch tx to block, @@ -454,15 +454,36 @@ func (f *fsm) VerifyStateTransactions(transactions []*types.Transaction) error { if err := f.verifyCommitEpochTx(tx); err != nil { return fmt.Errorf("error while verifying commit epoch transaction. error: %w", err) } + case *contractsapi.DistributeRewardForRewardPoolFn: + if distributeRewardsTxExists { + // if we already validated distribute rewards tx, + // that means someone added more than one distribute rewards tx to block, + // which is invalid + return errDistributeRewardsTxSingleExpected + } + + distributeRewardsTxExists = true + + if err := f.verifyDistributeRewardsTx(tx); err != nil { + return fmt.Errorf("error while verifying distribute rewards transaction. error: %w", err) + } default: return fmt.Errorf("invalid state transaction data type: %v", stateTxData) } } - if f.isEndOfEpoch && !commitEpochTxExists { - // this is a check if commit epoch transaction is not in the list of transactions at all - // but it should be - return errCommitEpochTxDoesNotExist + if f.isEndOfEpoch { + if !commitEpochTxExists { + // this is a check if commit epoch transaction is not in the list of transactions at all + // but it should be + return errCommitEpochTxDoesNotExist + } + + if !distributeRewardsTxExists { + // this is a check if distribute rewards transaction is not in the list of transactions at all + // but it should be + return errDistributeRewardsTxDoesNotExist + } } return nil @@ -532,7 +553,7 @@ func (f *fsm) Insert(proposal []byte, committedSeals []*messages.CommittedSeal) } // Write extra data to header - newBlock.Block.Header.ExtraData = append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...) + newBlock.Block.Header.ExtraData = extra.MarshalRLPTo(nil) if err := f.backend.CommitBlock(newBlock); err != nil { return nil, err @@ -547,23 +568,10 @@ func (f *fsm) Height() uint64 { } // ValidatorSet returns the validator set for the current round -func (f *fsm) ValidatorSet() ValidatorSet { +func (f *fsm) ValidatorSet() validator.ValidatorSet { return f.validators } -// getCurrentValidators queries smart contract on the given block height and returns currently active validator set -func (f *fsm) getCurrentValidators(pendingBlockState *state.Transition) (AccountSet, error) { - provider := f.backend.GetStateProvider(pendingBlockState) - systemState := f.backend.GetSystemState(provider) - - newValidators, err := systemState.GetValidatorSet() - if err != nil { - return nil, fmt.Errorf("failed to retrieve validator set for current block: %w", err) - } - - return newValidators, nil -} - // verifyCommitEpochTx creates commit epoch transaction and compares its hash with the one extracted from the block. func (f *fsm) verifyCommitEpochTx(commitEpochTx *types.Transaction) error { if f.isEndOfEpoch { @@ -586,7 +594,65 @@ func (f *fsm) verifyCommitEpochTx(commitEpochTx *types.Transaction) error { return errCommitEpochTxNotExpected } -func validateHeaderFields(parent *types.Header, header *types.Header) error { +// verifyDistributeRewardsTx creates distribute rewards transaction +// and compares its hash with the one extracted from the block. +func (f *fsm) verifyDistributeRewardsTx(distributeRewardsTx *types.Transaction) error { + if f.isEndOfEpoch { + localDistributeRewardsTx, err := f.createDistributeRewardsTx() + if err != nil { + return err + } + + if distributeRewardsTx.Hash != localDistributeRewardsTx.Hash { + return fmt.Errorf( + "invalid distribute rewards transaction. Expected '%s', but got '%s' distribute rewards hash", + localDistributeRewardsTx.Hash, + distributeRewardsTx.Hash, + ) + } + + return nil + } + + return errDistributeRewardsTxNotExpected +} + +// verifyBridgeCommitmentTx validates bridge commitment transaction +func verifyBridgeCommitmentTx(txHash types.Hash, + commitment *CommitmentMessageSigned, + validators validator.ValidatorSet) error { + signers, err := validators.Accounts().GetFilteredValidators(commitment.AggSignature.Bitmap) + if err != nil { + return fmt.Errorf("failed to retrieve signers for state tx (%s): %w", txHash, err) + } + + if !validators.HasQuorum(signers.GetAddressesAsSet()) { + return fmt.Errorf("quorum size not reached for state tx (%s)", txHash) + } + + commitmentHash, err := commitment.Hash() + if err != nil { + return err + } + + signature, err := bls.UnmarshalSignature(commitment.AggSignature.AggregatedSignature) + if err != nil { + return fmt.Errorf("error for state tx (%s) while unmarshaling signature: %w", txHash, err) + } + + verified := signature.VerifyAggregated(signers.GetBlsKeys(), commitmentHash.Bytes(), bls.DomainStateReceiver) + if !verified { + return fmt.Errorf("invalid signature for state tx (%s)", txHash) + } + + return nil +} + +func validateHeaderFields(parent *types.Header, header *types.Header, blockTimeDrift uint64) error { + // header extra data must be higher or equal to ExtraVanity = 32 in order to be compliant with Ethereum blocks + if len(header.ExtraData) < ExtraVanity { + return fmt.Errorf("extra-data shorter than %d bytes (%d)", ExtraVanity, len(header.ExtraData)) + } // verify parent hash if parent.Hash != header.ParentHash { return fmt.Errorf("incorrect header parent hash (parent=%s, header parent=%s)", parent.Hash, header.ParentHash) @@ -595,6 +661,19 @@ func validateHeaderFields(parent *types.Header, header *types.Header) error { if header.Number != parent.Number+1 { return fmt.Errorf("invalid number") } + // verify time is from the future + if header.Timestamp > (uint64(time.Now().UTC().Unix()) + blockTimeDrift) { + return fmt.Errorf("block from the future. block timestamp: %s, configured block time drift %d seconds", + time.Unix(int64(header.Timestamp), 0).Format(time.RFC3339), blockTimeDrift) + } + // verify header nonce is zero + if header.Nonce != types.ZeroNonce { + return fmt.Errorf("invalid nonce") + } + // verify that the gasUsed is <= gasLimit + if header.GasUsed > header.GasLimit { + return fmt.Errorf("invalid gas limit: have %v, max %v", header.GasUsed, header.GasLimit) + } // verify time has passed if header.Timestamp <= parent.Timestamp { return fmt.Errorf("timestamp older than parent") diff --git a/consensus/polybft/fsm_test.go b/consensus/polybft/fsm_test.go index 5faf7f54c3..0d71d15413 100644 --- a/consensus/polybft/fsm_test.go +++ b/consensus/polybft/fsm_test.go @@ -14,9 +14,9 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" - "github.com/0xPolygon/polygon-edge/state" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/assert" @@ -27,35 +27,58 @@ import ( func TestFSM_ValidateHeader(t *testing.T) { t.Parallel() + blockTimeDrift := uint64(1) + extra := createTestExtra(validator.AccountSet{}, validator.AccountSet{}, 0, 0, 0) parent := &types.Header{Number: 0, Hash: types.BytesToHash([]byte{1, 2, 3})} header := &types.Header{Number: 0} + // extra data + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "extra-data shorter than") + header.ExtraData = extra + // parent hash - require.ErrorContains(t, validateHeaderFields(parent, header), "incorrect header parent hash") + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "incorrect header parent hash") header.ParentHash = parent.Hash // sequence number - require.ErrorContains(t, validateHeaderFields(parent, header), "invalid number") + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "invalid number") header.Number = 1 // failed timestamp - require.ErrorContains(t, validateHeaderFields(parent, header), "timestamp older than parent") + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "timestamp older than parent") header.Timestamp = 10 + // failed nonce + header.SetNonce(1) + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "invalid nonce") + + header.SetNonce(0) + + // failed gas + header.GasLimit = 10 + header.GasUsed = 11 + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "invalid gas limit") + header.GasLimit = 10 + header.GasUsed = 10 + // mix digest - require.ErrorContains(t, validateHeaderFields(parent, header), "mix digest is not correct") + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "mix digest is not correct") header.MixHash = PolyBFTMixDigest // difficulty header.Difficulty = 0 - require.ErrorContains(t, validateHeaderFields(parent, header), "difficulty should be greater than zero") + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "difficulty should be greater than zero") header.Difficulty = 1 header.Hash = types.BytesToHash([]byte{11, 22, 33}) - require.ErrorContains(t, validateHeaderFields(parent, header), "invalid header hash") + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "invalid header hash") + header.Timestamp = uint64(time.Now().UTC().Unix() + 150) + require.ErrorContains(t, validateHeaderFields(parent, header, blockTimeDrift), "block from the future") + + header.Timestamp = uint64(time.Now().UTC().Unix()) header.ComputeHash() - require.NoError(t, validateHeaderFields(parent, header)) + require.NoError(t, validateHeaderFields(parent, header, blockTimeDrift)) } func TestFSM_verifyCommitEpochTx(t *testing.T) { @@ -63,7 +86,7 @@ func TestFSM_verifyCommitEpochTx(t *testing.T) { fsm := &fsm{ isEndOfEpoch: true, - commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10), + commitEpochInput: createTestCommitEpochInput(t, 0, 10), } // include commit epoch transaction to the epoch ending block @@ -104,9 +127,9 @@ func TestFSM_BuildProposal_WithoutCommitEpochTxGood(t *testing.T) { eventRoot := types.ZeroHash - validators := newTestValidators(t, accountCount) - validatorSet := validators.getPublicIdentities() - extra := createTestExtra(validatorSet, AccountSet{}, accountCount-1, committedCount, parentCount) + validators := validator.NewTestValidators(t, accountCount) + validatorSet := validators.GetPublicIdentities() + extra := createTestExtra(validatorSet, validator.AccountSet{}, accountCount-1, committedCount, parentCount) parent := &types.Header{Number: parentBlockNumber, ExtraData: extra} parent.ComputeHash() @@ -117,13 +140,13 @@ func TestFSM_BuildProposal_WithoutCommitEpochTxGood(t *testing.T) { runtime := &consensusRuntime{ logger: hclog.NewNullLogger(), config: &runtimeConfig{ - Key: wallet.NewKey(validators.getPrivateIdentities()[0]), + Key: wallet.NewKey(validators.GetPrivateIdentities()[0]), blockchain: blockchainMock, }, } fsm := &fsm{parent: parent, blockBuilder: mBlockBuilder, config: &PolyBFTConfig{}, backend: blockchainMock, - validators: validators.toValidatorSet(), exitEventRootHash: eventRoot, logger: hclog.NewNullLogger()} + validators: validators.ToValidatorSet(), exitEventRootHash: eventRoot, logger: hclog.NewNullLogger()} proposal, err := fsm.BuildProposal(currentRound) assert.NoError(t, err) @@ -169,40 +192,33 @@ func TestFSM_BuildProposal_WithCommitEpochTxGood(t *testing.T) { eventRoot := types.ZeroHash - validators := newTestValidators(t, accountCount) - extra := createTestExtra(validators.getPublicIdentities(), AccountSet{}, accountCount-1, committedCount, parentCount) + validators := validator.NewTestValidators(t, accountCount) + extra := createTestExtra(validators.GetPublicIdentities(), validator.AccountSet{}, accountCount-1, committedCount, parentCount) parent := &types.Header{Number: parentBlockNumber, ExtraData: extra} parent.ComputeHash() stateBlock := createDummyStateBlock(parentBlockNumber+1, parent.Hash, extra) - transition := &state.Transition{} mBlockBuilder := newBlockBuilderMock(stateBlock) - mBlockBuilder.On("WriteTx", mock.Anything).Return(error(nil)).Once() - mBlockBuilder.On("GetState").Return(transition).Once() - - systemStateMock := new(systemStateMock) - systemStateMock.On("GetValidatorSet").Return(nil).Once() + mBlockBuilder.On("WriteTx", mock.Anything).Return(error(nil)).Twice() blockChainMock := new(blockchainMock) - blockChainMock.On("GetStateProvider", mock.Anything). - Return(NewStateProvider(transition)).Once() - blockChainMock.On("GetSystemState", mock.Anything).Return(systemStateMock).Once() runtime := &consensusRuntime{ logger: hclog.NewNullLogger(), config: &runtimeConfig{ - Key: wallet.NewKey(validators.getPrivateIdentities()[0]), + Key: wallet.NewKey(validators.GetPrivateIdentities()[0]), blockchain: blockChainMock, }, } fsm := &fsm{parent: parent, blockBuilder: mBlockBuilder, config: &PolyBFTConfig{}, backend: blockChainMock, - isEndOfEpoch: true, - validators: validators.toValidatorSet(), - commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10), - exitEventRootHash: eventRoot, - logger: hclog.NewNullLogger(), + isEndOfEpoch: true, + validators: validators.ToValidatorSet(), + commitEpochInput: createTestCommitEpochInput(t, 0, 10), + distributeRewardsInput: createTestDistributeRewardsInput(t, 0, nil, 10), + exitEventRootHash: eventRoot, + logger: hclog.NewNullLogger(), } proposal, err := fsm.BuildProposal(currentRound) @@ -214,10 +230,10 @@ func TestFSM_BuildProposal_WithCommitEpochTxGood(t *testing.T) { assert.Equal(t, stateBlock.Block.MarshalRLP(), proposal) - currentValidatorsHash, err := validators.getPublicIdentities().Hash() + currentValidatorsHash, err := validators.GetPublicIdentities().Hash() require.NoError(t, err) - nextValidatorsHash, err := AccountSet{}.Hash() + nextValidatorsHash, err := validators.ToValidatorSet().Accounts().Hash() require.NoError(t, err) checkpoint := &CheckpointData{ @@ -235,8 +251,6 @@ func TestFSM_BuildProposal_WithCommitEpochTxGood(t *testing.T) { require.Equal(t, checkpointHash.Bytes(), msg.GetPreprepareData().ProposalHash) mBlockBuilder.AssertExpectations(t) - systemStateMock.AssertExpectations(t) - blockChainMock.AssertExpectations(t) } func TestFSM_BuildProposal_EpochEndingBlock_FailedToApplyStateTx(t *testing.T) { @@ -249,8 +263,8 @@ func TestFSM_BuildProposal_EpochEndingBlock_FailedToApplyStateTx(t *testing.T) { parentBlockNumber = 1023 ) - validators := newTestValidators(t, accountCount) - extra := createTestExtra(validators.getPublicIdentities(), AccountSet{}, accountCount-1, committedCount, parentCount) + validators := validator.NewTestValidators(t, accountCount) + extra := createTestExtra(validators.GetPublicIdentities(), validator.AccountSet{}, accountCount-1, committedCount, parentCount) parent := &types.Header{Number: parentBlockNumber, ExtraData: extra} @@ -258,12 +272,12 @@ func TestFSM_BuildProposal_EpochEndingBlock_FailedToApplyStateTx(t *testing.T) { mBlockBuilder.On("WriteTx", mock.Anything).Return(errors.New("error")).Once() mBlockBuilder.On("Reset").Return(error(nil)).Once() - validatorSet := NewValidatorSet(validators.getPublicIdentities(), hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validators.GetPublicIdentities(), hclog.NewNullLogger()) fsm := &fsm{parent: parent, blockBuilder: mBlockBuilder, backend: &blockchainMock{}, isEndOfEpoch: true, validators: validatorSet, - commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10), + commitEpochInput: createTestCommitEpochInput(t, 0, 10), exitEventRootHash: types.ZeroHash, } @@ -282,40 +296,48 @@ func TestFSM_BuildProposal_EpochEndingBlock_ValidatorsDeltaExists(t *testing.T) parentBlockNumber = 49 ) - validators := newTestValidators(t, validatorsCount).getPublicIdentities() - extra := createTestExtra(validators, AccountSet{}, validatorsCount-1, signaturesCount, signaturesCount) - parent := &types.Header{Number: parentBlockNumber, ExtraData: extra} + validators := validator.NewTestValidators(t, validatorsCount).GetPublicIdentities() + extra := createTestExtraObject(validators, validator.AccountSet{}, validatorsCount-1, signaturesCount, signaturesCount) + extra.Validators = nil + + extraData := extra.MarshalRLPTo(nil) + parent := &types.Header{Number: parentBlockNumber, ExtraData: extraData} parent.ComputeHash() - stateBlock := createDummyStateBlock(parentBlockNumber+1, parent.Hash, extra) + stateBlock := createDummyStateBlock(parentBlockNumber+1, parent.Hash, extraData) - transition := &state.Transition{} blockBuilderMock := newBlockBuilderMock(stateBlock) - blockBuilderMock.On("WriteTx", mock.Anything).Return(error(nil)).Once() - blockBuilderMock.On("GetState").Return(transition).Once() + blockBuilderMock.On("WriteTx", mock.Anything).Return(error(nil)).Twice() + + addedValidators := validator.NewTestValidators(t, 2).GetPublicIdentities() + removedValidators := [3]uint64{3, 4, 5} + removedBitmap := &bitmap.Bitmap{} - newValidators := validators[:remainingValidatorsCount].Copy() - addedValidators := newTestValidators(t, 2).getPublicIdentities() - newValidators = append(newValidators, addedValidators...) - systemStateMock := new(systemStateMock) - systemStateMock.On("GetValidatorSet").Return(newValidators).Once() + for _, i := range removedValidators { + removedBitmap.Set(i) + } + + newDelta := &validator.ValidatorSetDelta{ + Added: addedValidators, + Updated: validator.AccountSet{}, + Removed: *removedBitmap, + } blockChainMock := new(blockchainMock) - blockChainMock.On("GetStateProvider", mock.Anything). - Return(NewStateProvider(transition)).Once() - blockChainMock.On("GetSystemState", mock.Anything, mock.Anything).Return(systemStateMock).Once() - validatorSet := NewValidatorSet(validators, hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validators, hclog.NewNullLogger()) fsm := &fsm{ - parent: parent, - blockBuilder: blockBuilderMock, - config: &PolyBFTConfig{}, - backend: blockChainMock, - isEndOfEpoch: true, - validators: validatorSet, - commitEpochInput: createTestCommitEpochInput(t, 0, validators, 10), - exitEventRootHash: types.ZeroHash, - logger: hclog.NewNullLogger(), + parent: parent, + blockBuilder: blockBuilderMock, + config: &PolyBFTConfig{}, + backend: blockChainMock, + isEndOfEpoch: true, + validators: validatorSet, + commitEpochInput: createTestCommitEpochInput(t, 0, 10), + distributeRewardsInput: createTestDistributeRewardsInput(t, 0, validators, 10), + exitEventRootHash: types.ZeroHash, + logger: hclog.NewNullLogger(), + newValidatorsDelta: newDelta, } proposal, err := fsm.BuildProposal(0) @@ -327,8 +349,6 @@ func TestFSM_BuildProposal_EpochEndingBlock_ValidatorsDeltaExists(t *testing.T) assert.Len(t, blockExtra.Validators.Added, 2) assert.False(t, blockExtra.Validators.IsEmpty()) - removedValidators := [3]uint64{3, 4, 5} - for _, addedValidator := range addedValidators { assert.True(t, blockExtra.Validators.Added.ContainsAddress(addedValidator.Address)) } @@ -342,7 +362,6 @@ func TestFSM_BuildProposal_EpochEndingBlock_ValidatorsDeltaExists(t *testing.T) } blockBuilderMock.AssertExpectations(t) - systemStateMock.AssertExpectations(t) blockChainMock.AssertExpectations(t) } @@ -355,8 +374,8 @@ func TestFSM_BuildProposal_NonEpochEndingBlock_ValidatorsDeltaEmpty(t *testing.T parentBlockNumber = 9 ) - testValidators := newTestValidators(t, accountCount) - extra := createTestExtra(testValidators.getPublicIdentities(), AccountSet{}, accountCount-1, signaturesCount, signaturesCount) + testValidators := validator.NewTestValidators(t, accountCount) + extra := createTestExtra(testValidators.GetPublicIdentities(), validator.AccountSet{}, accountCount-1, signaturesCount, signaturesCount) parent := &types.Header{Number: parentBlockNumber, ExtraData: extra} parent.ComputeHash() stateBlock := createDummyStateBlock(parentBlockNumber+1, parent.Hash, extra) @@ -366,11 +385,9 @@ func TestFSM_BuildProposal_NonEpochEndingBlock_ValidatorsDeltaEmpty(t *testing.T blockBuilderMock.On("Fill").Once() blockBuilderMock.On("Reset").Return(error(nil)).Once() - systemStateMock := new(systemStateMock) - fsm := &fsm{parent: parent, blockBuilder: blockBuilderMock, config: &PolyBFTConfig{}, backend: &blockchainMock{}, - isEndOfEpoch: false, validators: testValidators.toValidatorSet(), + isEndOfEpoch: false, validators: testValidators.ToValidatorSet(), exitEventRootHash: types.ZeroHash, logger: hclog.NewNullLogger()} proposal, err := fsm.BuildProposal(0) @@ -382,10 +399,9 @@ func TestFSM_BuildProposal_NonEpochEndingBlock_ValidatorsDeltaEmpty(t *testing.T assert.True(t, blockExtra.Validators.IsEmpty()) blockBuilderMock.AssertExpectations(t) - systemStateMock.AssertNotCalled(t, "GetValidatorSet") } -func TestFSM_BuildProposal_EpochEndingBlock_FailToCreateValidatorsDelta(t *testing.T) { +func TestFSM_BuildProposal_EpochEndingBlock_FailToGetNextValidatorsHash(t *testing.T) { t.Parallel() const ( @@ -394,51 +410,46 @@ func TestFSM_BuildProposal_EpochEndingBlock_FailToCreateValidatorsDelta(t *testi parentBlockNumber = 49 ) - testValidators := newTestValidators(t, accountCount) - allAccounts := testValidators.getPublicIdentities() - extra := createTestExtra(allAccounts, AccountSet{}, accountCount-1, signaturesCount, signaturesCount) + testValidators := validator.NewTestValidators(t, accountCount) + allAccounts := testValidators.GetPublicIdentities() + extra := createTestExtraObject(allAccounts, validator.AccountSet{}, accountCount-1, signaturesCount, signaturesCount) + extra.Validators = nil - parent := &types.Header{Number: parentBlockNumber, ExtraData: extra} + newValidatorDelta := &validator.ValidatorSetDelta{ + // this will prompt an error since all the validators are already in the validator set + Added: testValidators.ToValidatorSet().Accounts(), + } + + parent := &types.Header{Number: parentBlockNumber, ExtraData: extra.MarshalRLPTo(nil)} - transition := &state.Transition{} blockBuilderMock := new(blockBuilderMock) - blockBuilderMock.On("WriteTx", mock.Anything).Return(error(nil)).Once() - blockBuilderMock.On("GetState").Return(transition).Once() + blockBuilderMock.On("WriteTx", mock.Anything).Return(error(nil)).Twice() blockBuilderMock.On("Reset").Return(error(nil)).Once() blockBuilderMock.On("Fill").Once() - systemStateMock := new(systemStateMock) - systemStateMock.On("GetValidatorSet").Return(nil, errors.New("failed to get validators set")).Once() - - blockChainMock := new(blockchainMock) - blockChainMock.On("GetStateProvider", mock.Anything). - Return(NewStateProvider(transition)).Once() - blockChainMock.On("GetSystemState", mock.Anything, mock.Anything).Return(systemStateMock).Once() - fsm := &fsm{parent: parent, - blockBuilder: blockBuilderMock, - config: &PolyBFTConfig{}, - backend: blockChainMock, - isEndOfEpoch: true, - validators: testValidators.toValidatorSet(), - commitEpochInput: createTestCommitEpochInput(t, 0, allAccounts, 10), - exitEventRootHash: types.ZeroHash, + blockBuilder: blockBuilderMock, + config: &PolyBFTConfig{}, + isEndOfEpoch: true, + validators: testValidators.ToValidatorSet(), + commitEpochInput: createTestCommitEpochInput(t, 0, 10), + distributeRewardsInput: createTestDistributeRewardsInput(t, 0, allAccounts, 10), + exitEventRootHash: types.ZeroHash, + newValidatorsDelta: newValidatorDelta, } proposal, err := fsm.BuildProposal(0) - assert.ErrorContains(t, err, "failed to retrieve validator set for current block: failed to get validators set") + assert.ErrorContains(t, err, "already present in the validators snapshot") assert.Nil(t, proposal) blockBuilderMock.AssertNotCalled(t, "Build") blockBuilderMock.AssertExpectations(t) - systemStateMock.AssertExpectations(t) - blockChainMock.AssertExpectations(t) } func TestFSM_VerifyStateTransactions_MiddleOfEpochWithTransaction(t *testing.T) { t.Parallel() - fsm := &fsm{commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10)} + fsm := &fsm{commitEpochInput: createTestCommitEpochInput(t, 0, 10)} tx, err := fsm.createCommitEpochTx() assert.NoError(t, err) err = fsm.VerifyStateTransactions([]*types.Transaction{tx}) @@ -448,7 +459,7 @@ func TestFSM_VerifyStateTransactions_MiddleOfEpochWithTransaction(t *testing.T) func TestFSM_VerifyStateTransactions_MiddleOfEpochWithoutTransaction(t *testing.T) { t.Parallel() - fsm := &fsm{commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10)} + fsm := &fsm{commitEpochInput: createTestCommitEpochInput(t, 0, 10)} err := fsm.VerifyStateTransactions([]*types.Transaction{}) assert.NoError(t, err) } @@ -456,7 +467,7 @@ func TestFSM_VerifyStateTransactions_MiddleOfEpochWithoutTransaction(t *testing. func TestFSM_VerifyStateTransactions_EndOfEpochWithoutTransaction(t *testing.T) { t.Parallel() - fsm := &fsm{isEndOfEpoch: true, commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10)} + fsm := &fsm{isEndOfEpoch: true, commitEpochInput: createTestCommitEpochInput(t, 0, 10)} assert.EqualError(t, fsm.VerifyStateTransactions([]*types.Transaction{}), "commit epoch transaction is not found in the epoch ending block") } @@ -464,8 +475,8 @@ func TestFSM_VerifyStateTransactions_EndOfEpochWithoutTransaction(t *testing.T) func TestFSM_VerifyStateTransactions_EndOfEpochWrongCommitEpochTx(t *testing.T) { t.Parallel() - fsm := &fsm{isEndOfEpoch: true, commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10)} - commitEpochInput, err := createTestCommitEpochInput(t, 0, nil, 5).EncodeAbi() + fsm := &fsm{isEndOfEpoch: true, commitEpochInput: createTestCommitEpochInput(t, 0, 10)} + commitEpochInput, err := createTestCommitEpochInput(t, 1, 5).EncodeAbi() require.NoError(t, err) commitEpochTx := createStateTransactionWithData(contracts.ValidatorSetContract, commitEpochInput) @@ -489,14 +500,14 @@ func TestFSM_VerifyStateTransactions_EndOfEpochMoreThanOneCommitEpochTx(t *testi t.Parallel() txs := make([]*types.Transaction, 2) - fsm := &fsm{isEndOfEpoch: true, commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10)} + fsm := &fsm{isEndOfEpoch: true, commitEpochInput: createTestCommitEpochInput(t, 0, 10)} commitEpochTxOne, err := fsm.createCommitEpochTx() require.NoError(t, err) txs[0] = commitEpochTxOne - commitEpochTxTwo := createTestCommitEpochInput(t, 0, nil, 100) + commitEpochTxTwo := createTestCommitEpochInput(t, 0, 100) input, err := commitEpochTxTwo.EncodeAbi() require.NoError(t, err) @@ -508,44 +519,49 @@ func TestFSM_VerifyStateTransactions_EndOfEpochMoreThanOneCommitEpochTx(t *testi func TestFSM_VerifyStateTransactions_StateTransactionPass(t *testing.T) { t.Parallel() - validators := newTestValidators(t, 5) + validators := validator.NewTestValidators(t, 5) - validatorSet := NewValidatorSet(validators.getPublicIdentities(), hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validators.GetPublicIdentities(), hclog.NewNullLogger()) fsm := &fsm{ - isEndOfEpoch: true, - isEndOfSprint: true, - validators: validatorSet, - commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10), - logger: hclog.NewNullLogger(), + isEndOfEpoch: true, + isEndOfSprint: true, + validators: validatorSet, + commitEpochInput: createTestCommitEpochInput(t, 0, 10), + distributeRewardsInput: createTestDistributeRewardsInput(t, 0, validators.GetPublicIdentities(), 10), + logger: hclog.NewNullLogger(), } // add commit epoch commitEpochTx to the end of transactions list commitEpochTx, err := fsm.createCommitEpochTx() require.NoError(t, err) - err = fsm.VerifyStateTransactions([]*types.Transaction{commitEpochTx}) + distributeRewardsTx, err := fsm.createDistributeRewardsTx() + require.NoError(t, err) + + err = fsm.VerifyStateTransactions([]*types.Transaction{commitEpochTx, distributeRewardsTx}) require.NoError(t, err) } func TestFSM_VerifyStateTransactions_StateTransactionQuorumNotReached(t *testing.T) { t.Parallel() - validators := newTestValidators(t, 5) - commitment := createTestCommitment(t, validators.getPrivateIdentities()) + validators := validator.NewTestValidators(t, 5) + commitment := createTestCommitment(t, validators.GetPrivateIdentities()) commitment.AggSignature = Signature{ AggregatedSignature: []byte{1, 2}, Bitmap: []byte{}, } - validatorSet := NewValidatorSet(validators.getPublicIdentities(), hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validators.GetPublicIdentities(), hclog.NewNullLogger()) fsm := &fsm{ isEndOfEpoch: true, isEndOfSprint: true, validators: validatorSet, proposerCommitmentToRegister: commitment, - commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10), + commitEpochInput: createTestCommitEpochInput(t, 0, 10), + distributeRewardsInput: createTestDistributeRewardsInput(t, 0, nil, 10), logger: hclog.NewNullLogger(), } @@ -565,13 +581,13 @@ func TestFSM_VerifyStateTransactions_StateTransactionQuorumNotReached(t *testing func TestFSM_VerifyStateTransactions_StateTransactionInvalidSignature(t *testing.T) { t.Parallel() - validators := newTestValidators(t, 5) - commitment := createTestCommitment(t, validators.getPrivateIdentities()) - nonValidators := newTestValidators(t, 3) + validators := validator.NewTestValidators(t, 5) + commitment := createTestCommitment(t, validators.GetPrivateIdentities()) + nonValidators := validator.NewTestValidators(t, 3) aggregatedSigs := bls.Signatures{} - nonValidators.iterAcct(nil, func(t *testValidator) { - aggregatedSigs = append(aggregatedSigs, t.mustSign([]byte("dummyHash"), bls.DomainStateReceiver)) + nonValidators.IterAcct(nil, func(t *validator.TestValidator) { + aggregatedSigs = append(aggregatedSigs, t.MustSign([]byte("dummyHash"), bls.DomainStateReceiver)) }) sig, err := aggregatedSigs.Aggregate().Marshal() @@ -579,14 +595,15 @@ func TestFSM_VerifyStateTransactions_StateTransactionInvalidSignature(t *testing commitment.AggSignature.AggregatedSignature = sig - validatorSet := NewValidatorSet(validators.getPublicIdentities(), hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validators.GetPublicIdentities(), hclog.NewNullLogger()) fsm := &fsm{ isEndOfEpoch: true, isEndOfSprint: true, validators: validatorSet, proposerCommitmentToRegister: commitment, - commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10), + commitEpochInput: createTestCommitEpochInput(t, 0, 10), + distributeRewardsInput: createTestDistributeRewardsInput(t, 0, nil, 10), logger: hclog.NewNullLogger(), } @@ -609,17 +626,17 @@ func TestFSM_ValidateCommit_WrongValidator(t *testing.T) { parentBlockNumber = 10 ) - validators := newTestValidators(t, accountsCount) + validators := validator.NewTestValidators(t, accountsCount) parent := &types.Header{ Number: parentBlockNumber, - ExtraData: createTestExtra(validators.getPublicIdentities(), AccountSet{}, 5, 3, 3), + ExtraData: createTestExtra(validators.GetPublicIdentities(), validator.AccountSet{}, 5, 3, 3), } parent.ComputeHash() stateBlock := createDummyStateBlock(parentBlockNumber+1, parent.Hash, parent.ExtraData) mBlockBuilder := newBlockBuilderMock(stateBlock) fsm := &fsm{parent: parent, blockBuilder: mBlockBuilder, config: &PolyBFTConfig{}, backend: &blockchainMock{}, - validators: validators.toValidatorSet(), logger: hclog.NewNullLogger(), exitEventRootHash: types.ZeroHash} + validators: validators.ToValidatorSet(), logger: hclog.NewNullLogger(), exitEventRootHash: types.ZeroHash} _, err := fsm.BuildProposal(0) require.NoError(t, err) @@ -636,27 +653,27 @@ func TestFSM_ValidateCommit_InvalidHash(t *testing.T) { parentBlockNumber = 10 ) - validators := newTestValidators(t, accountsCount) + validators := validator.NewTestValidators(t, accountsCount) parent := &types.Header{ Number: parentBlockNumber, - ExtraData: createTestExtra(validators.getPublicIdentities(), AccountSet{}, 5, 3, 3), + ExtraData: createTestExtra(validators.GetPublicIdentities(), validator.AccountSet{}, 5, 3, 3), } parent.ComputeHash() stateBlock := createDummyStateBlock(parentBlockNumber+1, parent.Hash, parent.ExtraData) mBlockBuilder := newBlockBuilderMock(stateBlock) fsm := &fsm{parent: parent, blockBuilder: mBlockBuilder, config: &PolyBFTConfig{}, backend: &blockchainMock{}, - validators: validators.toValidatorSet(), exitEventRootHash: types.ZeroHash, logger: hclog.NewNullLogger()} + validators: validators.ToValidatorSet(), exitEventRootHash: types.ZeroHash, logger: hclog.NewNullLogger()} _, err := fsm.BuildProposal(0) require.NoError(t, err) - nonValidatorAcc := newTestValidator(t, "non_validator", 1) - wrongSignature, err := nonValidatorAcc.mustSign([]byte("Foo"), bls.DomainCheckpointManager).Marshal() + nonValidatorAcc := validator.NewTestValidator(t, "non_validator", 1) + wrongSignature, err := nonValidatorAcc.MustSign([]byte("Foo"), bls.DomainCheckpointManager).Marshal() require.NoError(t, err) - err = fsm.ValidateCommit(validators.getValidator("0").Address().Bytes(), wrongSignature, []byte{}) + err = fsm.ValidateCommit(validators.GetValidator("0").Address().Bytes(), wrongSignature, []byte{}) require.ErrorContains(t, err, "incorrect commit signature from") } @@ -665,15 +682,15 @@ func TestFSM_ValidateCommit_Good(t *testing.T) { const parentBlockNumber = 10 - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}) - validatorsMetadata := validators.getPublicIdentities() + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}) + validatorsMetadata := validators.GetPublicIdentities() - parent := &types.Header{Number: parentBlockNumber, ExtraData: createTestExtra(validatorsMetadata, AccountSet{}, 5, 3, 3)} + parent := &types.Header{Number: parentBlockNumber, ExtraData: createTestExtra(validatorsMetadata, validator.AccountSet{}, 5, 3, 3)} parent.ComputeHash() stateBlock := createDummyStateBlock(parentBlockNumber+1, parent.Hash, parent.ExtraData) mBlockBuilder := newBlockBuilderMock(stateBlock) - validatorSet := NewValidatorSet(validatorsMetadata, hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validatorsMetadata, hclog.NewNullLogger()) fsm := &fsm{parent: parent, blockBuilder: mBlockBuilder, config: &PolyBFTConfig{}, backend: &blockchainMock{}, validators: validatorSet, @@ -686,13 +703,240 @@ func TestFSM_ValidateCommit_Good(t *testing.T) { block := types.Block{} require.NoError(t, block.UnmarshalRLP(proposal)) - validator := validators.getValidator("A") - seal, err := validator.mustSign(block.Hash().Bytes(), bls.DomainCheckpointManager).Marshal() + validator := validators.GetValidator("A") + seal, err := validator.MustSign(block.Hash().Bytes(), bls.DomainCheckpointManager).Marshal() require.NoError(t, err) err = fsm.ValidateCommit(validator.Key().Address().Bytes(), seal, block.Hash().Bytes()) require.NoError(t, err) } +func TestFSM_Validate_ExitEventRootNotExpected(t *testing.T) { + t.Parallel() + + const ( + accountsCount = 5 + parentBlockNumber = 25 + signaturesCount = 3 + ) + + validators := validator.NewTestValidators(t, accountsCount) + parentExtra := createTestExtraObject(validators.GetPublicIdentities(), validator.AccountSet{}, 4, signaturesCount, signaturesCount) + parentExtra.Validators = nil + + parent := &types.Header{ + Number: parentBlockNumber, + ExtraData: parentExtra.MarshalRLPTo(nil), + } + parent.ComputeHash() + + polybftBackendMock := new(polybftBackendMock) + polybftBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.GetPublicIdentities(), nil).Once() + + extra := createTestExtraObject(validators.GetPublicIdentities(), validator.AccountSet{}, 4, signaturesCount, signaturesCount) + extra.Validators = nil + parentCheckpointHash, err := extra.Checkpoint.Hash(0, parentBlockNumber, parent.Hash) + require.NoError(t, err) + + currentValSetHash, err := validators.GetPublicIdentities().Hash() + require.NoError(t, err) + + extra.Parent = createSignature(t, validators.GetPrivateIdentities(), parentCheckpointHash, bls.DomainCheckpointManager) + extra.Checkpoint.EpochNumber = 1 + extra.Checkpoint.CurrentValidatorsHash = currentValSetHash + extra.Checkpoint.NextValidatorsHash = currentValSetHash + + stateBlock := createDummyStateBlock(parent.Number+1, types.Hash{100, 15}, extra.MarshalRLPTo(nil)) + + proposalHash, err := extra.Checkpoint.Hash(0, stateBlock.Block.Number(), stateBlock.Block.Hash()) + require.NoError(t, err) + + stateBlock.Block.Header.Hash = proposalHash + stateBlock.Block.Header.ParentHash = parent.Hash + stateBlock.Block.Header.Timestamp = uint64(time.Now().UTC().Unix()) + stateBlock.Block.Transactions = []*types.Transaction{} + + proposal := stateBlock.Block.MarshalRLP() + + fsm := &fsm{ + parent: parent, + backend: new(blockchainMock), + validators: validators.ToValidatorSet(), + logger: hclog.NewNullLogger(), + polybftBackend: polybftBackendMock, + config: &PolyBFTConfig{BlockTimeDrift: 1}, + exitEventRootHash: types.BytesToHash([]byte{0, 1, 2, 3, 4}), // expect this to be in proposal extra + } + + err = fsm.Validate(proposal) + require.ErrorContains(t, err, "exit root hash not as expected") + + polybftBackendMock.AssertExpectations(t) +} + +func TestFSM_Validate_EpochEndingBlock_MismatchInDeltas(t *testing.T) { + t.Parallel() + + const ( + accountsCount = 5 + parentBlockNumber = 25 + signaturesCount = 3 + ) + + validators := validator.NewTestValidators(t, accountsCount) + parentExtra := createTestExtraObject(validators.GetPublicIdentities(), validator.AccountSet{}, 4, signaturesCount, signaturesCount) + parentExtra.Validators = nil + + parent := &types.Header{ + Number: parentBlockNumber, + ExtraData: parentExtra.MarshalRLPTo(nil), + } + parent.ComputeHash() + + polybftBackendMock := new(polybftBackendMock) + polybftBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.GetPublicIdentities(), nil).Once() + + extra := createTestExtraObject(validators.GetPublicIdentities(), validator.AccountSet{}, 4, signaturesCount, signaturesCount) + parentCheckpointHash, err := extra.Checkpoint.Hash(0, parentBlockNumber, parent.Hash) + require.NoError(t, err) + + extra.Validators = nil // this will cause test to fail + extra.Parent = createSignature(t, validators.GetPrivateIdentities(), parentCheckpointHash, bls.DomainCheckpointManager) + + stateBlock := createDummyStateBlock(parent.Number+1, types.Hash{100, 15}, extra.MarshalRLPTo(nil)) + + proposalHash, err := new(CheckpointData).Hash(0, stateBlock.Block.Number(), stateBlock.Block.Hash()) + require.NoError(t, err) + + commitEpoch := createTestCommitEpochInput(t, 1, 10) + commitEpochTxInput, err := commitEpoch.EncodeAbi() + require.NoError(t, err) + + distributeRewards := createTestDistributeRewardsInput(t, 1, validators.GetPublicIdentities(), 10) + distributeRewardsTxInput, err := distributeRewards.EncodeAbi() + require.NoError(t, err) + + stateBlock.Block.Header.Hash = proposalHash + stateBlock.Block.Header.ParentHash = parent.Hash + stateBlock.Block.Header.Timestamp = uint64(time.Now().UTC().Unix()) + stateBlock.Block.Transactions = []*types.Transaction{ + createStateTransactionWithData(contracts.ValidatorSetContract, commitEpochTxInput), + createStateTransactionWithData(contracts.RewardPoolContract, distributeRewardsTxInput), + } + + proposal := stateBlock.Block.MarshalRLP() + + blockchainMock := new(blockchainMock) + blockchainMock.On("ProcessBlock", mock.Anything, mock.Anything). + Return(stateBlock, error(nil)). + Maybe() + + // a new validator is added to delta which proposers block does not have + privateKey, err := bls.GenerateBlsKey() + require.NoError(t, err) + + newValidatorDelta := &validator.ValidatorSetDelta{ + Added: validator.AccountSet{&validator.ValidatorMetadata{ + Address: types.BytesToAddress([]byte{0, 1, 2, 3}), + BlsKey: privateKey.PublicKey(), + VotingPower: new(big.Int).SetUint64(1), + IsActive: true, + }}, + } + + fsm := &fsm{ + parent: parent, + backend: blockchainMock, + validators: validators.ToValidatorSet(), + logger: hclog.NewNullLogger(), + isEndOfEpoch: true, + commitEpochInput: commitEpoch, + distributeRewardsInput: distributeRewards, + polybftBackend: polybftBackendMock, + newValidatorsDelta: newValidatorDelta, + config: &PolyBFTConfig{BlockTimeDrift: 1}, + } + + err = fsm.Validate(proposal) + require.ErrorIs(t, err, errValidatorSetDeltaMismatch) + + polybftBackendMock.AssertExpectations(t) + blockchainMock.AssertExpectations(t) +} + +func TestFSM_Validate_EpochEndingBlock_UpdatingValidatorSetInNonEpochEndingBlock(t *testing.T) { + t.Parallel() + + const ( + accountsCount = 5 + parentBlockNumber = 25 + signaturesCount = 3 + ) + + validators := validator.NewTestValidators(t, accountsCount) + parentExtra := createTestExtraObject(validators.GetPublicIdentities(), validator.AccountSet{}, 4, signaturesCount, signaturesCount) + parentExtra.Validators = nil + + parent := &types.Header{ + Number: parentBlockNumber, + ExtraData: parentExtra.MarshalRLPTo(nil), + } + parent.ComputeHash() + + polybftBackendMock := new(polybftBackendMock) + polybftBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validators.GetPublicIdentities(), nil).Once() + + // a new validator is added to delta which proposers block does not have + privateKey, err := bls.GenerateBlsKey() + require.NoError(t, err) + + newValidatorDelta := &validator.ValidatorSetDelta{ + Added: validator.AccountSet{&validator.ValidatorMetadata{ + Address: types.BytesToAddress([]byte{0, 1, 2, 3}), + BlsKey: privateKey.PublicKey(), + VotingPower: new(big.Int).SetUint64(1), + IsActive: true, + }}, + } + + extra := createTestExtraObject(validators.GetPublicIdentities(), validator.AccountSet{}, 4, signaturesCount, signaturesCount) + parentCheckpointHash, err := extra.Checkpoint.Hash(0, parentBlockNumber, parent.Hash) + require.NoError(t, err) + + extra.Validators = newValidatorDelta // this will cause test to fail + extra.Parent = createSignature(t, validators.GetPrivateIdentities(), parentCheckpointHash, bls.DomainCheckpointManager) + + stateBlock := createDummyStateBlock(parent.Number+1, types.Hash{100, 15}, extra.MarshalRLPTo(nil)) + + proposalHash, err := new(CheckpointData).Hash(0, stateBlock.Block.Number(), stateBlock.Block.Hash()) + require.NoError(t, err) + + stateBlock.Block.Header.Hash = proposalHash + stateBlock.Block.Header.ParentHash = parent.Hash + stateBlock.Block.Header.Timestamp = uint64(time.Now().UTC().Unix()) + + proposal := stateBlock.Block.MarshalRLP() + + blockchainMock := new(blockchainMock) + blockchainMock.On("ProcessBlock", mock.Anything, mock.Anything). + Return(stateBlock, error(nil)). + Maybe() + + fsm := &fsm{ + parent: parent, + backend: blockchainMock, + validators: validators.ToValidatorSet(), + logger: hclog.NewNullLogger(), + polybftBackend: polybftBackendMock, + config: &PolyBFTConfig{BlockTimeDrift: 1}, + } + + err = fsm.Validate(proposal) + require.ErrorIs(t, err, errValidatorsUpdateInNonEpochEnding) + + polybftBackendMock.AssertExpectations(t) + blockchainMock.AssertExpectations(t) +} + func TestFSM_Validate_IncorrectHeaderParentHash(t *testing.T) { t.Parallel() @@ -702,15 +946,22 @@ func TestFSM_Validate_IncorrectHeaderParentHash(t *testing.T) { signaturesCount = 3 ) - validators := newTestValidators(t, accountsCount) + validators := validator.NewTestValidators(t, accountsCount) parent := &types.Header{ Number: parentBlockNumber, - ExtraData: createTestExtra(validators.getPublicIdentities(), AccountSet{}, 4, signaturesCount, signaturesCount), + ExtraData: createTestExtra(validators.GetPublicIdentities(), validator.AccountSet{}, 4, signaturesCount, signaturesCount), } parent.ComputeHash() - fsm := &fsm{parent: parent, backend: &blockchainMock{}, - validators: validators.toValidatorSet(), logger: hclog.NewNullLogger()} + fsm := &fsm{ + parent: parent, + backend: &blockchainMock{}, + validators: validators.ToValidatorSet(), + logger: hclog.NewNullLogger(), + config: &PolyBFTConfig{ + BlockTimeDrift: 1, + }, + } stateBlock := createDummyStateBlock(parent.Number+1, types.Hash{100, 15}, parent.ExtraData) @@ -733,10 +984,10 @@ func TestFSM_Validate_InvalidNumber(t *testing.T) { signaturesCount = 3 ) - validators := newTestValidators(t, accountsCount) + validators := validator.NewTestValidators(t, accountsCount) parent := &types.Header{ Number: parentBlockNumber, - ExtraData: createTestExtra(validators.getPublicIdentities(), AccountSet{}, 4, signaturesCount, signaturesCount), + ExtraData: createTestExtra(validators.GetPublicIdentities(), validator.AccountSet{}, 4, signaturesCount, signaturesCount), } parent.ComputeHash() @@ -744,8 +995,14 @@ func TestFSM_Validate_InvalidNumber(t *testing.T) { for _, blockNum := range []uint64{parentBlockNumber - 1, parentBlockNumber, parentBlockNumber + 2} { stateBlock := createDummyStateBlock(blockNum, parent.Hash, parent.ExtraData) mBlockBuilder := newBlockBuilderMock(stateBlock) - fsm := &fsm{parent: parent, blockBuilder: mBlockBuilder, backend: &blockchainMock{}, - validators: validators.toValidatorSet(), logger: hclog.NewNullLogger()} + fsm := &fsm{ + parent: parent, + blockBuilder: mBlockBuilder, + backend: &blockchainMock{}, + validators: validators.ToValidatorSet(), + logger: hclog.NewNullLogger(), + config: &PolyBFTConfig{BlockTimeDrift: 1}, + } proposalHash, err := new(CheckpointData).Hash(fsm.backend.GetChainID(), stateBlock.Block.Number(), stateBlock.Block.Hash()) require.NoError(t, err) @@ -763,10 +1020,10 @@ func TestFSM_Validate_TimestampOlder(t *testing.T) { const parentBlockNumber = 10 - validators := newTestValidators(t, 5) + validators := validator.NewTestValidators(t, 5) parent := &types.Header{ Number: parentBlockNumber, - ExtraData: createTestExtra(validators.getPublicIdentities(), AccountSet{}, 4, 3, 3), + ExtraData: createTestExtra(validators.GetPublicIdentities(), validator.AccountSet{}, 4, 3, 3), Timestamp: uint64(time.Now().UTC().Unix()), } parent.ComputeHash() @@ -780,8 +1037,14 @@ func TestFSM_Validate_TimestampOlder(t *testing.T) { ExtraData: parent.ExtraData, } stateBlock := &types.FullBlock{Block: consensus.BuildBlock(consensus.BuildBlockParams{Header: header})} - fsm := &fsm{parent: parent, backend: &blockchainMock{}, - validators: validators.toValidatorSet(), logger: hclog.NewNullLogger()} + fsm := &fsm{ + parent: parent, + backend: &blockchainMock{}, + validators: validators.ToValidatorSet(), + logger: hclog.NewNullLogger(), + config: &PolyBFTConfig{ + BlockTimeDrift: 1, + }} checkpointHash, err := new(CheckpointData).Hash(fsm.backend.GetChainID(), header.Number, header.Hash) require.NoError(t, err) @@ -799,10 +1062,10 @@ func TestFSM_Validate_IncorrectMixHash(t *testing.T) { const parentBlockNumber = 10 - validators := newTestValidators(t, 5) + validators := validator.NewTestValidators(t, 5) parent := &types.Header{ Number: parentBlockNumber, - ExtraData: createTestExtra(validators.getPublicIdentities(), AccountSet{}, 4, 3, 3), + ExtraData: createTestExtra(validators.GetPublicIdentities(), validator.AccountSet{}, 4, 3, 3), Timestamp: uint64(100), } parent.ComputeHash() @@ -820,8 +1083,11 @@ func TestFSM_Validate_IncorrectMixHash(t *testing.T) { fsm := &fsm{ parent: parent, backend: &blockchainMock{}, - validators: validators.toValidatorSet(), + validators: validators.ToValidatorSet(), logger: hclog.NewNullLogger(), + config: &PolyBFTConfig{ + BlockTimeDrift: 1, + }, } rlpBlock := buildBlock.Block.MarshalRLP() @@ -842,13 +1108,13 @@ func TestFSM_Insert_Good(t *testing.T) { ) setupFn := func() (*fsm, []*messages.CommittedSeal, *types.FullBlock, *blockchainMock) { - validators := newTestValidators(t, accountCount) - allAccounts := validators.getPrivateIdentities() - validatorsMetadata := validators.getPublicIdentities() + validators := validator.NewTestValidators(t, accountCount) + allAccounts := validators.GetPrivateIdentities() + validatorsMetadata := validators.GetPublicIdentities() - extraParent := createTestExtra(validatorsMetadata, AccountSet{}, len(allAccounts)-1, signaturesCount, signaturesCount) + extraParent := createTestExtra(validatorsMetadata, validator.AccountSet{}, len(allAccounts)-1, signaturesCount, signaturesCount) parent := &types.Header{Number: parentBlockNumber, ExtraData: extraParent} - extraBlock := createTestExtra(validatorsMetadata, AccountSet{}, len(allAccounts)-1, signaturesCount, signaturesCount) + extraBlock := createTestExtra(validatorsMetadata, validator.AccountSet{}, len(allAccounts)-1, signaturesCount, signaturesCount) block := consensus.BuildBlock( consensus.BuildBlockParams{ Header: &types.Header{Number: parentBlockNumber + 1, ParentHash: parent.Hash, ExtraData: extraBlock}, @@ -859,7 +1125,7 @@ func TestFSM_Insert_Good(t *testing.T) { builderMock := newBlockBuilderMock(builtBlock) chainMock := &blockchainMock{} chainMock.On("CommitBlock", mock.Anything).Return(error(nil)).Once() - chainMock.On("ProcessBlock", mock.Anything, mock.Anything, mock.Anything). + chainMock.On("ProcessBlock", mock.Anything, mock.Anything). Return(builtBlock, error(nil)). Maybe() @@ -868,7 +1134,7 @@ func TestFSM_Insert_Good(t *testing.T) { blockBuilder: builderMock, target: builtBlock, backend: chainMock, - validators: NewValidatorSet(validatorsMetadata[0:len(validatorsMetadata)-1], hclog.NewNullLogger()), + validators: validator.NewValidatorSet(validatorsMetadata[0:len(validatorsMetadata)-1], hclog.NewNullLogger()), logger: hclog.NewNullLogger(), } @@ -934,13 +1200,13 @@ func TestFSM_Insert_InvalidNode(t *testing.T) { signaturesCount = 3 ) - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}) - validatorsMetadata := validators.getPublicIdentities() + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}) + validatorsMetadata := validators.GetPublicIdentities() parent := &types.Header{Number: parentBlockNumber} parent.ComputeHash() - extraBlock := createTestExtra(validatorsMetadata, AccountSet{}, len(validators.validators)-1, signaturesCount, signaturesCount) + extraBlock := createTestExtra(validatorsMetadata, validator.AccountSet{}, len(validators.Validators)-1, signaturesCount, signaturesCount) finalBlock := consensus.BuildBlock( consensus.BuildBlockParams{ Header: &types.Header{Number: parentBlockNumber + 1, ParentHash: parent.Hash, ExtraData: extraBlock}, @@ -949,25 +1215,25 @@ func TestFSM_Insert_InvalidNode(t *testing.T) { buildBlock := &types.FullBlock{Block: finalBlock, Receipts: []*types.Receipt{}} mBlockBuilder := newBlockBuilderMock(buildBlock) - validatorSet := NewValidatorSet(validatorsMetadata[0:len(validatorsMetadata)-1], hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validatorsMetadata[0:len(validatorsMetadata)-1], hclog.NewNullLogger()) fsm := &fsm{parent: parent, blockBuilder: mBlockBuilder, backend: &blockchainMock{}, validators: validatorSet, } proposal := buildBlock.Block.MarshalRLP() - validatorA := validators.getValidator("A") - validatorB := validators.getValidator("B") + validatorA := validators.GetValidator("A") + validatorB := validators.GetValidator("B") proposalHash := buildBlock.Block.Hash().Bytes() - sigA, err := validatorA.mustSign(proposalHash, bls.DomainCheckpointManager).Marshal() + sigA, err := validatorA.MustSign(proposalHash, bls.DomainCheckpointManager).Marshal() require.NoError(t, err) - sigB, err := validatorB.mustSign(proposalHash, bls.DomainCheckpointManager).Marshal() + sigB, err := validatorB.MustSign(proposalHash, bls.DomainCheckpointManager).Marshal() require.NoError(t, err) // create test account outside of validator set - nonValidatorAccount := newTestValidator(t, "non_validator", 1) - nonValidatorSignature, err := nonValidatorAccount.mustSign(proposalHash, bls.DomainCheckpointManager).Marshal() + nonValidatorAccount := validator.NewTestValidator(t, "non_validator", 1) + nonValidatorSignature, err := nonValidatorAccount.MustSign(proposalHash, bls.DomainCheckpointManager).Marshal() require.NoError(t, err) commitedSeals := []*messages.CommittedSeal{ @@ -1004,7 +1270,8 @@ func TestFSM_DecodeCommitmentStateTxs(t *testing.T) { f := &fsm{ proposerCommitmentToRegister: signedCommitment, - commitEpochInput: createTestCommitEpochInput(t, 0, nil, 10), + commitEpochInput: createTestCommitEpochInput(t, 0, 10), + distributeRewardsInput: createTestDistributeRewardsInput(t, 0, nil, 10), logger: hclog.NewNullLogger(), } @@ -1022,7 +1289,7 @@ func TestFSM_DecodeCommitmentStateTxs(t *testing.T) { func TestFSM_DecodeCommitEpochStateTx(t *testing.T) { t.Parallel() - commitEpoch := createTestCommitEpochInput(t, 0, nil, 10) + commitEpoch := createTestCommitEpochInput(t, 0, 10) input, err := commitEpoch.EncodeAbi() require.NoError(t, err) require.NotNil(t, input) @@ -1031,14 +1298,12 @@ func TestFSM_DecodeCommitEpochStateTx(t *testing.T) { decodedInputData, err := decodeStateTransaction(tx.Input) require.NoError(t, err) - decodedCommitEpoch, ok := decodedInputData.(*contractsapi.CommitEpochChildValidatorSetFn) + decodedCommitEpoch, ok := decodedInputData.(*contractsapi.CommitEpochValidatorSetFn) require.True(t, ok) require.True(t, commitEpoch.ID.Cmp(decodedCommitEpoch.ID) == 0) require.NotNil(t, decodedCommitEpoch.Epoch) require.True(t, commitEpoch.Epoch.StartBlock.Cmp(decodedCommitEpoch.Epoch.StartBlock) == 0) require.True(t, commitEpoch.Epoch.EndBlock.Cmp(decodedCommitEpoch.Epoch.EndBlock) == 0) - require.NotNil(t, decodedCommitEpoch.Uptime) - require.True(t, commitEpoch.Uptime.TotalBlocks.Cmp(decodedCommitEpoch.Uptime.TotalBlocks) == 0) } func TestFSM_VerifyStateTransaction_ValidBothTypesOfStateTransactions(t *testing.T) { @@ -1050,7 +1315,7 @@ func TestFSM_VerifyStateTransaction_ValidBothTypesOfStateTransactions(t *testing signedCommitments [2]*CommitmentMessageSigned ) - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}) + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}) commitments[0], signedCommitments[0], stateSyncs[0] = buildCommitmentAndStateSyncs(t, 10, uint64(3), 2) commitments[1], signedCommitments[1], stateSyncs[1] = buildCommitmentAndStateSyncs(t, 10, uint64(3), 12) @@ -1059,13 +1324,13 @@ func TestFSM_VerifyStateTransaction_ValidBothTypesOfStateTransactions(t *testing // add register commitment state transaction hash, err := sc.Hash() require.NoError(t, err) - signature := createSignature(t, validators.getPrivateIdentities(aliases...), hash, bls.DomainStateReceiver) + signature := createSignature(t, validators.GetPrivateIdentities(aliases...), hash, bls.DomainStateReceiver) sc.AggSignature = *signature } f := &fsm{ isEndOfSprint: true, - validators: validators.toValidatorSet(), + validators: validators.ToValidatorSet(), } var txns []*types.Transaction @@ -1104,11 +1369,11 @@ func TestFSM_VerifyStateTransaction_InvalidTypeOfStateTransactions(t *testing.T) func TestFSM_VerifyStateTransaction_QuorumNotReached(t *testing.T) { t.Parallel() - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) _, commitmentMessageSigned, _ := buildCommitmentAndStateSyncs(t, 10, uint64(3), 2) f := &fsm{ isEndOfSprint: true, - validators: validators.toValidatorSet(), + validators: validators.ToValidatorSet(), } hash, err := commitmentMessageSigned.Hash() @@ -1116,7 +1381,7 @@ func TestFSM_VerifyStateTransaction_QuorumNotReached(t *testing.T) { var txns []*types.Transaction - signature := createSignature(t, validators.getPrivateIdentities("A", "B"), hash, bls.DomainStateReceiver) + signature := createSignature(t, validators.GetPrivateIdentities("A", "B"), hash, bls.DomainStateReceiver) commitmentMessageSigned.AggSignature = *signature inputData, err := commitmentMessageSigned.EncodeAbi() @@ -1132,11 +1397,11 @@ func TestFSM_VerifyStateTransaction_QuorumNotReached(t *testing.T) { func TestFSM_VerifyStateTransaction_InvalidSignature(t *testing.T) { t.Parallel() - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) _, commitmentMessageSigned, _ := buildCommitmentAndStateSyncs(t, 10, uint64(3), 2) f := &fsm{ isEndOfSprint: true, - validators: validators.toValidatorSet(), + validators: validators.ToValidatorSet(), } hash, err := commitmentMessageSigned.Hash() @@ -1144,9 +1409,9 @@ func TestFSM_VerifyStateTransaction_InvalidSignature(t *testing.T) { var txns []*types.Transaction - signature := createSignature(t, validators.getPrivateIdentities("A", "B", "C", "D"), hash, bls.DomainStateReceiver) - invalidValidator := newTestValidator(t, "G", 1) - invalidSignature, err := invalidValidator.mustSign([]byte("malicious message"), bls.DomainStateReceiver).Marshal() + signature := createSignature(t, validators.GetPrivateIdentities("A", "B", "C", "D"), hash, bls.DomainStateReceiver) + invalidValidator := validator.NewTestValidator(t, "G", 1) + invalidSignature, err := invalidValidator.MustSign([]byte("malicious message"), bls.DomainStateReceiver).Marshal() require.NoError(t, err) commitmentMessageSigned.AggSignature = Signature{ @@ -1160,17 +1425,16 @@ func TestFSM_VerifyStateTransaction_InvalidSignature(t *testing.T) { txns = append(txns, createStateTransactionWithData(contracts.StateReceiverContract, inputData)) - err = f.VerifyStateTransactions(txns) - require.ErrorContains(t, err, "invalid signature for tx") + require.ErrorContains(t, f.VerifyStateTransactions(txns), "invalid signature for state tx") } func TestFSM_VerifyStateTransaction_TwoCommitmentMessages(t *testing.T) { t.Parallel() - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) _, commitmentMessageSigned, _ := buildCommitmentAndStateSyncs(t, 10, uint64(3), 2) - validatorSet := NewValidatorSet(validators.getPublicIdentities(), hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validators.GetPublicIdentities(), hclog.NewNullLogger()) f := &fsm{ isEndOfSprint: true, @@ -1182,7 +1446,7 @@ func TestFSM_VerifyStateTransaction_TwoCommitmentMessages(t *testing.T) { var txns []*types.Transaction - signature := createSignature(t, validators.getPrivateIdentities("A", "B", "C", "D"), hash, bls.DomainStateReceiver) + signature := createSignature(t, validators.GetPrivateIdentities("A", "B", "C", "D"), hash, bls.DomainStateReceiver) commitmentMessageSigned.AggSignature = *signature inputData, err := commitmentMessageSigned.EncodeAbi() @@ -1208,24 +1472,24 @@ func TestFSM_Validate_FailToVerifySignatures(t *testing.T) { signaturesCount = 3 ) - validators := newTestValidators(t, accountsCount) - validatorsMetadata := validators.getPublicIdentities() + validators := validator.NewTestValidators(t, accountsCount) + validatorsMetadata := validators.GetPublicIdentities() - extra := createTestExtraObject(validatorsMetadata, AccountSet{}, 4, signaturesCount, signaturesCount) + extra := createTestExtraObject(validatorsMetadata, validator.AccountSet{}, 4, signaturesCount, signaturesCount) validatorsHash, err := validatorsMetadata.Hash() require.NoError(t, err) extra.Checkpoint = &CheckpointData{CurrentValidatorsHash: validatorsHash, NextValidatorsHash: validatorsHash} parent := &types.Header{ Number: parentBlockNumber, - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + ExtraData: extra.MarshalRLPTo(nil), } parent.ComputeHash() polybftBackendMock := new(polybftBackendMock) polybftBackendMock.On("GetValidators", mock.Anything, mock.Anything).Return(validatorsMetadata, nil).Once() - validatorSet := NewValidatorSet(validatorsMetadata, hclog.NewNullLogger()) + validatorSet := validator.NewValidatorSet(validatorsMetadata, hclog.NewNullLogger()) fsm := &fsm{ parent: parent, @@ -1233,6 +1497,9 @@ func TestFSM_Validate_FailToVerifySignatures(t *testing.T) { polybftBackend: polybftBackendMock, validators: validatorSet, logger: hclog.NewNullLogger(), + config: &PolyBFTConfig{ + BlockTimeDrift: 1, + }, } finalBlock := consensus.BuildBlock(consensus.BuildBlockParams{ @@ -1264,6 +1531,7 @@ func createDummyStateBlock(blockNumber uint64, parentHash types.Hash, extraData ParentHash: parentHash, Difficulty: 1, ExtraData: extraData, + MixHash: PolyBFTMixDigest, }, }) @@ -1272,17 +1540,14 @@ func createDummyStateBlock(blockNumber uint64, parentHash types.Hash, extraData func createTestExtra( allAccounts, - previousValidatorSet AccountSet, + previousValidatorSet validator.AccountSet, validatorsCount, committedSignaturesCount, parentSignaturesCount int, ) []byte { extraData := createTestExtraObject(allAccounts, previousValidatorSet, validatorsCount, committedSignaturesCount, parentSignaturesCount) - marshaled := extraData.MarshalRLPTo(nil) - result := make([]byte, ExtraVanity+len(marshaled)) - copy(result[ExtraVanity:], marshaled) - return result + return extraData.MarshalRLPTo(nil) } func createTestCommitment(t *testing.T, accounts []*wallet.Account) *CommitmentMessageSigned { @@ -1343,7 +1608,7 @@ func newBlockBuilderMock(stateBlock *types.FullBlock) *blockBuilderMock { } func createTestExtraObject(allAccounts, - previousValidatorSet AccountSet, + previousValidatorSet validator.AccountSet, validatorsCount, committedSignaturesCount, parentSignaturesCount int) *Extra { @@ -1368,13 +1633,13 @@ func createTestExtraObject(allAccounts, return extraData } -func generateValidatorDelta(validatorCount int, allAccounts, previousValidatorSet AccountSet) (vd *ValidatorSetDelta) { +func generateValidatorDelta(validatorCount int, allAccounts, previousValidatorSet validator.AccountSet) (vd *validator.ValidatorSetDelta) { oldMap := make(map[types.Address]int, previousValidatorSet.Len()) for i, x := range previousValidatorSet { oldMap[x.Address] = i } - vd = &ValidatorSetDelta{} + vd = &validator.ValidatorSetDelta{} vd.Removed = bitmap.Bitmap{} for _, id := range rand.Perm(len(allAccounts))[:validatorCount] { diff --git a/consensus/polybft/handlers.go b/consensus/polybft/handlers.go index f566b276b7..686e386a03 100644 --- a/consensus/polybft/handlers.go +++ b/consensus/polybft/handlers.go @@ -1,6 +1,9 @@ package polybft -import "github.com/0xPolygon/polygon-edge/types" +import ( + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/types" +) type PostBlockRequest struct { // FullBlock is a reference of the executed block @@ -23,5 +26,5 @@ type PostEpochRequest struct { SystemState SystemState // ValidatorSet is the validator set for the new epoch - ValidatorSet *validatorSet + ValidatorSet validator.ValidatorSet } diff --git a/consensus/polybft/hash_test.go b/consensus/polybft/hash_test.go index 9dbfda7cac..314a9dcc51 100644 --- a/consensus/polybft/hash_test.go +++ b/consensus/polybft/hash_test.go @@ -5,6 +5,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/assert" @@ -12,10 +13,9 @@ import ( func Test_setupHeaderHashFunc(t *testing.T) { extra := &Extra{ - Validators: &ValidatorSetDelta{Removed: bitmap.Bitmap{1}}, + Validators: &validator.ValidatorSetDelta{Removed: bitmap.Bitmap{1}}, Parent: createSignature(t, []*wallet.Account{generateTestAccount(t)}, types.ZeroHash, bls.DomainCheckpointManager), Checkpoint: &CheckpointData{}, - Seal: []byte{}, Committed: &Signature{}, } @@ -25,12 +25,11 @@ func Test_setupHeaderHashFunc(t *testing.T) { Timestamp: 18, } - header.ExtraData = append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...) + header.ExtraData = extra.MarshalRLPTo(nil) notFullExtraHash := types.HeaderHash(header) - extra.Seal = []byte{1, 2, 3, 255} extra.Committed = createSignature(t, []*wallet.Account{generateTestAccount(t)}, types.ZeroHash, bls.DomainCheckpointManager) - header.ExtraData = append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...) + header.ExtraData = extra.MarshalRLPTo(nil) fullExtraHash := types.HeaderHash(header) assert.Equal(t, notFullExtraHash, fullExtraHash) diff --git a/consensus/polybft/helpers_test.go b/consensus/polybft/helpers_test.go index eec39068b8..7d8ed09231 100644 --- a/consensus/polybft/helpers_test.go +++ b/consensus/polybft/helpers_test.go @@ -12,6 +12,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" @@ -58,39 +59,47 @@ func createSignature(t *testing.T, accounts []*wallet.Account, hash types.Hash, } func createTestCommitEpochInput(t *testing.T, epochID uint64, - validatorSet AccountSet, epochSize uint64) *contractsapi.CommitEpochChildValidatorSetFn { + epochSize uint64) *contractsapi.CommitEpochValidatorSetFn { t.Helper() - if validatorSet == nil { - validatorSet = newTestValidators(t, 5).getPublicIdentities() - } - var startBlock uint64 = 0 if epochID > 1 { startBlock = (epochID - 1) * epochSize } - uptime := &contractsapi.Uptime{ - EpochID: new(big.Int).SetUint64(epochID), - UptimeData: []*contractsapi.UptimeData{}, - TotalBlocks: new(big.Int).SetUint64(epochSize), - } - - commitEpoch := &contractsapi.CommitEpochChildValidatorSetFn{ - ID: uptime.EpochID, + commitEpoch := &contractsapi.CommitEpochValidatorSetFn{ + ID: new(big.Int).SetUint64(epochID), Epoch: &contractsapi.Epoch{ StartBlock: new(big.Int).SetUint64(startBlock + 1), EndBlock: new(big.Int).SetUint64(epochSize * epochID), EpochRoot: types.Hash{}, }, - Uptime: uptime, } - for i := range validatorSet { - uptime.AddValidatorUptime(validatorSet[i].Address, int64(epochSize)) + return commitEpoch +} + +func createTestDistributeRewardsInput(t *testing.T, epochID uint64, + validatorSet validator.AccountSet, epochSize uint64) *contractsapi.DistributeRewardForRewardPoolFn { + t.Helper() + + if validatorSet == nil { + validatorSet = validator.NewTestValidators(t, 5).GetPublicIdentities() } - return commitEpoch + uptime := make([]*contractsapi.Uptime, len(validatorSet)) + + for i, v := range validatorSet { + uptime[i] = &contractsapi.Uptime{ + Validator: v.Address, + SignedBlocks: new(big.Int).SetUint64(epochSize), + } + } + + return &contractsapi.DistributeRewardForRewardPoolFn{ + EpochID: new(big.Int).SetUint64(epochID), + Uptime: uptime, + } } func generateStateSyncEvents(t *testing.T, eventsCount int, startIdx uint64) []*contractsapi.StateSyncedEvent { @@ -134,35 +143,54 @@ func getEpochNumber(t *testing.T, blockNumber, epochSize uint64) uint64 { } // newTestState creates new instance of state used by tests. -func newTestState(t *testing.T) *State { - t.Helper() +func newTestState(tb testing.TB) *State { + tb.Helper() dir := fmt.Sprintf("/tmp/consensus-temp_%v", time.Now().UTC().Format(time.RFC3339Nano)) err := os.Mkdir(dir, 0775) if err != nil { - t.Fatal(err) + tb.Fatal(err) } state, err := newState(path.Join(dir, "my.db"), hclog.NewNullLogger(), make(chan struct{})) if err != nil { - t.Fatal(err) + tb.Fatal(err) } - t.Cleanup(func() { + tb.Cleanup(func() { if err := os.RemoveAll(dir); err != nil { - t.Fatal(err) + tb.Fatal(err) } }) return state } -func generateTestAccount(t *testing.T) *wallet.Account { - t.Helper() +func generateTestAccount(tb testing.TB) *wallet.Account { + tb.Helper() acc, err := wallet.GenerateAccount() - require.NoError(t, err) + require.NoError(tb, err) return acc } + +// createTestBridgeConfig creates test bridge configuration with hard-coded addresses +func createTestBridgeConfig() *BridgeConfig { + return &BridgeConfig{ + StateSenderAddr: types.StringToAddress("1"), + CheckpointManagerAddr: types.StringToAddress("2"), + ExitHelperAddr: types.StringToAddress("3"), + RootERC20PredicateAddr: types.StringToAddress("4"), + ChildMintableERC20PredicateAddr: types.StringToAddress("5"), + RootNativeERC20Addr: types.StringToAddress("6"), + RootERC721PredicateAddr: types.StringToAddress("8"), + ChildMintableERC721PredicateAddr: types.StringToAddress("9"), + RootERC1155PredicateAddr: types.StringToAddress("11"), + ChildMintableERC1155PredicateAddr: types.StringToAddress("12"), + CustomSupernetManagerAddr: types.StringToAddress("13"), + StakeManagerAddr: types.StringToAddress("14"), + JSONRPCEndpoint: "http://localhost:8545", + } +} diff --git a/consensus/polybft/mocks_test.go b/consensus/polybft/mocks_test.go index 9eff33161d..750067ba92 100644 --- a/consensus/polybft/mocks_test.go +++ b/consensus/polybft/mocks_test.go @@ -1,17 +1,10 @@ package polybft import ( - "fmt" - "math/big" - "sort" - "strconv" - "testing" "time" "github.com/0xPolygon/polygon-edge/blockchain" - bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" - "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" - "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/helper/progress" "github.com/0xPolygon/polygon-edge/state" "github.com/0xPolygon/polygon-edge/syncer" @@ -47,8 +40,8 @@ func (m *blockchainMock) NewBlockBuilder(parent *types.Header, coinbase types.Ad return args.Get(0).(blockBuilder), args.Error(1) //nolint:forcetypeassert } -func (m *blockchainMock) ProcessBlock(parent *types.Header, block *types.Block, callback func(*state.Transition) error) (*types.FullBlock, error) { - args := m.Called(parent, block, callback) +func (m *blockchainMock) ProcessBlock(parent *types.Header, block *types.Block) (*types.FullBlock, error) { + args := m.Called(parent, block) return args.Get(0).(*types.FullBlock), args.Error(1) //nolint:forcetypeassert } @@ -126,6 +119,12 @@ func (m *blockchainMock) GetChainID() uint64 { return 0 } +func (m *blockchainMock) GetReceiptsByHash(hash types.Hash) ([]*types.Receipt, error) { + args := m.Called(hash) + + return args.Get(0).([]*types.Receipt), args.Error(1) //nolint:forcetypeassert +} + var _ polybftBackend = (*polybftBackendMock)(nil) type polybftBackendMock struct { @@ -133,14 +132,14 @@ type polybftBackendMock struct { } // GetValidators retrieves validator set for the given block -func (p *polybftBackendMock) GetValidators(blockNumber uint64, parents []*types.Header) (AccountSet, error) { +func (p *polybftBackendMock) GetValidators(blockNumber uint64, parents []*types.Header) (validator.AccountSet, error) { args := p.Called(blockNumber, parents) if len(args) == 1 { - accountSet, _ := args.Get(0).(AccountSet) + accountSet, _ := args.Get(0).(validator.AccountSet) return accountSet, nil } else if len(args) == 2 { - accountSet, _ := args.Get(0).(AccountSet) + accountSet, _ := args.Get(0).(validator.AccountSet) return accountSet, args.Error(1) } @@ -204,21 +203,6 @@ type systemStateMock struct { mock.Mock } -func (m *systemStateMock) GetValidatorSet() (AccountSet, error) { - args := m.Called() - if len(args) == 1 { - accountSet, _ := args.Get(0).(AccountSet) - - return accountSet, nil - } else if len(args) == 2 { - accountSet, _ := args.Get(0).(AccountSet) - - return accountSet, args.Error(1) - } - - panic("systemStateMock.GetValidatorSet doesn't support such combination of arguments") //nolint:gocritic -} - func (m *systemStateMock) GetNextCommittedIndex() (uint64, error) { args := m.Called() @@ -278,175 +262,6 @@ func (t *transportMock) Multicast(msg interface{}) { _ = t.Called(msg) } -type testValidators struct { - validators map[string]*testValidator -} - -func newTestValidators(t *testing.T, validatorsCount int) *testValidators { - t.Helper() - - aliases := make([]string, validatorsCount) - for i := 0; i < validatorsCount; i++ { - aliases[i] = strconv.Itoa(i) - } - - return newTestValidatorsWithAliases(t, aliases) -} - -func newTestValidatorsWithAliases(t *testing.T, aliases []string, votingPowers ...[]uint64) *testValidators { - t.Helper() - - validators := map[string]*testValidator{} - - for i, alias := range aliases { - votingPower := uint64(1) - if len(votingPowers) == 1 { - votingPower = votingPowers[0][i] - } - - validators[alias] = newTestValidator(t, alias, votingPower) - } - - return &testValidators{validators: validators} -} - -func (v *testValidators) create(t *testing.T, alias string, votingPower uint64) { - t.Helper() - - if _, ok := v.validators[alias]; !ok { - v.validators[alias] = newTestValidator(t, alias, votingPower) - } -} - -func (v *testValidators) iterAcct(aliases []string, handle func(t *testValidator)) { - if len(aliases) == 0 { - // loop over the whole set - for k := range v.validators { - aliases = append(aliases, k) - } - // sort the names since they get queried randomly - sort.Strings(aliases) - } - - for _, alias := range aliases { - handle(v.getValidator(alias)) - } -} - -func (v *testValidators) getParamValidators(aliases ...string) (res []*Validator) { - v.iterAcct(aliases, func(t *testValidator) { - res = append(res, t.paramsValidator()) - }) - - return -} - -func (v *testValidators) getValidators(aliases ...string) (res []*testValidator) { - v.iterAcct(aliases, func(t *testValidator) { - res = append(res, t) - }) - - return -} - -func (v *testValidators) getPublicIdentities(aliases ...string) (res AccountSet) { - v.iterAcct(aliases, func(t *testValidator) { - res = append(res, t.ValidatorMetadata()) - }) - - return -} - -func (v *testValidators) getPrivateIdentities(aliases ...string) (res []*wallet.Account) { - v.iterAcct(aliases, func(t *testValidator) { - res = append(res, t.account) - }) - - return -} - -func (v *testValidators) getValidator(alias string) *testValidator { - vv, ok := v.validators[alias] - if !ok { - panic(fmt.Sprintf("Validator %s does not exist", alias)) //nolint:gocritic - } - - return vv -} - -func (v *testValidators) toValidatorSet() *validatorSet { - return NewValidatorSet(v.getPublicIdentities(), hclog.NewNullLogger()) -} - -func (v *testValidators) updateVotingPowers(votingPowersMap map[string]uint64) AccountSet { - if len(votingPowersMap) == 0 { - return AccountSet{} - } - - aliases := []string{} - for alias := range votingPowersMap { - aliases = append(aliases, alias) - } - - v.iterAcct(aliases, func(t *testValidator) { - t.votingPower = votingPowersMap[t.alias] - }) - - return v.getPublicIdentities(aliases...) -} - -type testValidator struct { - alias string - account *wallet.Account - votingPower uint64 -} - -func newTestValidator(t *testing.T, alias string, votingPower uint64) *testValidator { - t.Helper() - - return &testValidator{ - alias: alias, - votingPower: votingPower, - account: generateTestAccount(t), - } -} - -func (v *testValidator) Address() types.Address { - return types.Address(v.account.Ecdsa.Address()) -} - -func (v *testValidator) Key() *wallet.Key { - return wallet.NewKey(v.account) -} - -func (v *testValidator) paramsValidator() *Validator { - bls := v.account.Bls.PublicKey().Marshal() - - return &Validator{ - Address: v.Address(), - BlsKey: hex.EncodeToString(bls), - Balance: big.NewInt(1000), - Stake: big.NewInt(1000), - } -} - -func (v *testValidator) ValidatorMetadata() *ValidatorMetadata { - return &ValidatorMetadata{ - Address: types.Address(v.account.Ecdsa.Address()), - BlsKey: v.account.Bls.PublicKey(), - VotingPower: new(big.Int).SetUint64(v.votingPower), - } -} - -func (v *testValidator) mustSign(hash, domain []byte) *bls.Signature { - signature, err := v.account.Bls.Sign(hash, domain) - if err != nil { - panic(fmt.Sprintf("BUG: failed to sign: %v", err)) //nolint:gocritic - } - - return signature -} - type testHeadersMap struct { headersByNumber map[uint64]*types.Header } @@ -488,8 +303,8 @@ type txPoolMock struct { mock.Mock } -func (tp *txPoolMock) Prepare() { - tp.Called() +func (tp *txPoolMock) Prepare(baseFee uint64) { + tp.Called(baseFee) } func (tp *txPoolMock) Length() uint64 { diff --git a/consensus/polybft/polybft.go b/consensus/polybft/polybft.go index 25c1e1d38c..b4fabbf8bd 100644 --- a/consensus/polybft/polybft.go +++ b/consensus/polybft/polybft.go @@ -2,8 +2,11 @@ package polybft import ( + "context" "encoding/json" + "errors" "fmt" + "math/big" "path/filepath" "time" @@ -11,6 +14,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/helper/common" @@ -28,10 +32,14 @@ const ( bridgeProto = "/bridge/0.2" ) +var ( + errMissingBridgeConfig = errors.New("invalid genesis configuration, missing bridge configuration") +) + // polybftBackend is an interface defining polybft methods needed by fsm and sync tracker type polybftBackend interface { // GetValidators retrieves validator set for the given block - GetValidators(blockNumber uint64, parents []*types.Header) (AccountSet, error) + GetValidators(blockNumber uint64, parents []*types.Header) (validator.AccountSet, error) } // Factory is the factory function to create a discovery consensus @@ -118,40 +126,209 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st return err } - // initialize ChildValidatorSet SC - input, err := getInitChildValidatorSetInput(polyBFTConfig) - if err != nil { + // calculate initial total supply of native erc20 token + // we skip zero address, since its a special case address + // that is used for minting and burning native token + initialTotalSupply := big.NewInt(0) + + for addr, alloc := range config.Genesis.Alloc { + if addr == types.ZeroAddress { + continue + } + + initialTotalSupply.Add(initialTotalSupply, alloc.Balance) + } + + bridgeCfg := polyBFTConfig.Bridge + if bridgeCfg == nil { + return errMissingBridgeConfig + } + + // initialize ValidatorSet SC + if err = initValidatorSet(polyBFTConfig, transition); err != nil { return err } - if err = initContract(contracts.ValidatorSetContract, input, "ChildValidatorSet", transition); err != nil { + // approve reward pool + if err = approveRewardPoolAsSpender(polyBFTConfig, transition); err != nil { return err } - // initialize ChildERC20Predicate SC - input, err = getInitChildERC20PredicateInput(polyBFTConfig.Bridge) - if err != nil { + // mint reward tokens to reward wallet + if err = mintRewardTokensToWallet(polyBFTConfig, transition); err != nil { return err } - if err = initContract(contracts.ChildERC20PredicateContract, input, "ChildERC20Predicate", transition); err != nil { + // initialize RewardPool SC + if err = initRewardPool(polyBFTConfig, transition); err != nil { return err } - rootNativeERC20Token := types.ZeroAddress - if polyBFTConfig.Bridge != nil { - rootNativeERC20Token = polyBFTConfig.Bridge.RootNativeERC20Addr + // check if there are Bridge Allow List Admins and Bridge Block List Admins + // and if there are, get the first address as the Admin + var bridgeAllowListAdmin types.Address + if config.Params.BridgeAllowList != nil && len(config.Params.BridgeAllowList.AdminAddresses) > 0 { + bridgeAllowListAdmin = config.Params.BridgeAllowList.AdminAddresses[0] + } + + bridgeBlockListAdmin := types.ZeroAddress + if config.Params.BridgeBlockList != nil && len(config.Params.BridgeBlockList.AdminAddresses) > 0 { + bridgeBlockListAdmin = config.Params.BridgeBlockList.AdminAddresses[0] + } + + // initialize Predicate SCs + if bridgeAllowListAdmin != types.ZeroAddress || bridgeBlockListAdmin != types.ZeroAddress { + // The owner of the contract will be the allow list admin or the block list admin, if any of them is set. + owner := contracts.SystemCaller + if bridgeAllowListAdmin != types.ZeroAddress { + owner = bridgeAllowListAdmin + } else if bridgeBlockListAdmin != types.ZeroAddress { + owner = bridgeBlockListAdmin + } + + // initialize ChildERC20PredicateAccessList SC + input, err := getInitERC20PredicateACLInput(polyBFTConfig.Bridge, owner, false) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.ChildERC20PredicateContract, input, + "ChildERC20PredicateAccessList", transition); err != nil { + return err + } + + // initialize ChildERC721PredicateAccessList SC + input, err = getInitERC721PredicateACLInput(polyBFTConfig.Bridge, owner, false) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.ChildERC721PredicateContract, input, + "ChildERC721PredicateAccessList", transition); err != nil { + return err + } + + // initialize ChildERC1155PredicateAccessList SC + input, err = getInitERC1155PredicateACLInput(polyBFTConfig.Bridge, owner, false) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.ChildERC1155PredicateContract, input, + "ChildERC1155PredicateAccessList", transition); err != nil { + return err + } + + // initialize RootMintableERC20PredicateAccessList SC + input, err = getInitERC20PredicateACLInput(polyBFTConfig.Bridge, owner, true) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.RootMintableERC20PredicateContract, input, + "RootMintableERC20PredicateAccessList", transition); err != nil { + return err + } + + // initialize RootMintableERC721PredicateAccessList SC + input, err = getInitERC721PredicateACLInput(polyBFTConfig.Bridge, owner, true) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.RootMintableERC721PredicateContract, input, + "RootMintableERC721PredicateAccessList", transition); err != nil { + return err + } + + // initialize RootMintableERC1155PredicateAccessList SC + input, err = getInitERC1155PredicateACLInput(polyBFTConfig.Bridge, owner, true) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.RootMintableERC1155PredicateContract, input, + "RootMintableERC1155PredicateAccessList", transition); err != nil { + return err + } + } else { + // initialize ChildERC20Predicate SC + input, err := getInitERC20PredicateInput(bridgeCfg, false) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.ChildERC20PredicateContract, input, + "ChildERC20Predicate", transition); err != nil { + return err + } + + // initialize ChildERC721Predicate SC + input, err = getInitERC721PredicateInput(bridgeCfg, false) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.ChildERC721PredicateContract, input, + "ChildERC721Predicate", transition); err != nil { + return err + } + + // initialize ChildERC1155Predicate SC + input, err = getInitERC1155PredicateInput(bridgeCfg, false) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.ChildERC1155PredicateContract, input, + "ChildERC1155Predicate", transition); err != nil { + return err + } + + // initialize RootMintableERC20Predicate SC + input, err = getInitERC20PredicateInput(bridgeCfg, true) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.RootMintableERC20PredicateContract, input, + "RootMintableERC20Predicate", transition); err != nil { + return err + } + + // initialize RootMintableERC721Predicate SC + input, err = getInitERC721PredicateInput(bridgeCfg, true) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.RootMintableERC721PredicateContract, input, + "RootMintableERC721Predicate", transition); err != nil { + return err + } + + // initialize RootMintableERC1155Predicate SC + input, err = getInitERC1155PredicateInput(bridgeCfg, true) + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, contracts.RootMintableERC1155PredicateContract, input, + "RootMintableERC1155Predicate", transition); err != nil { + return err + } } - if polyBFTConfig.MintableERC20Token { + if polyBFTConfig.NativeTokenConfig.IsMintable { // initialize NativeERC20Mintable SC params := &contractsapi.InitializeNativeERC20MintableFn{ - Predicate_: contracts.ChildERC20PredicateContract, - Owner_: polyBFTConfig.Governance, - RootToken_: rootNativeERC20Token, - Name_: nativeTokenName, - Symbol_: nativeTokenSymbol, - Decimals_: nativeTokenDecimals, + Predicate_: contracts.ChildERC20PredicateContract, + Owner_: polyBFTConfig.NativeTokenConfig.Owner, + RootToken_: types.ZeroAddress, // in case native mintable token is used, it is always root token + Name_: polyBFTConfig.NativeTokenConfig.Name, + Symbol_: polyBFTConfig.NativeTokenConfig.Symbol, + Decimals_: polyBFTConfig.NativeTokenConfig.Decimals, + TokenSupply_: initialTotalSupply, } input, err := params.EncodeAbi() @@ -159,17 +336,19 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st return err } - if err = initContract(contracts.NativeERC20TokenContract, input, "NativeERC20Mintable", transition); err != nil { + if err = callContract(contracts.SystemCaller, + contracts.NativeERC20TokenContract, input, "NativeERC20Mintable", transition); err != nil { return err } } else { // initialize NativeERC20 SC params := &contractsapi.InitializeNativeERC20Fn{ - Name_: nativeTokenName, - Symbol_: nativeTokenSymbol, - Decimals_: nativeTokenDecimals, - RootToken_: rootNativeERC20Token, - Predicate_: contracts.ChildERC20PredicateContract, + Name_: polyBFTConfig.NativeTokenConfig.Name, + Symbol_: polyBFTConfig.NativeTokenConfig.Symbol, + Decimals_: polyBFTConfig.NativeTokenConfig.Decimals, + RootToken_: polyBFTConfig.Bridge.RootNativeERC20Addr, + Predicate_: contracts.ChildERC20PredicateContract, + TokenSupply_: initialTotalSupply, } input, err := params.EncodeAbi() @@ -177,15 +356,50 @@ func GenesisPostHookFactory(config *chain.Chain, engineName string) func(txn *st return err } - if err = initContract(contracts.NativeERC20TokenContract, input, "NativeERC20", transition); err != nil { + if err = callContract(contracts.SystemCaller, + contracts.NativeERC20TokenContract, input, "NativeERC20", transition); err != nil { return err } + + // initialize EIP1559Burn SC + if config.Params.BurnContract != nil && + len(config.Params.BurnContract) == 1 && + !polyBFTConfig.NativeTokenConfig.IsMintable { + var contractAddress types.Address + for _, address := range config.Params.BurnContract { + contractAddress = address + } + + // contract address exists in allocations + if _, ok := config.Genesis.Alloc[contractAddress]; ok { + burnParams := &contractsapi.InitializeEIP1559BurnFn{ + NewChildERC20Predicate: contracts.ChildERC20PredicateContract, + NewBurnDestination: config.Params.BurnContractDestinationAddress, + } + + input, err = burnParams.EncodeAbi() + if err != nil { + return err + } + + if err = callContract(contracts.SystemCaller, + contractAddress, + input, "EIP1559Burn", transition); err != nil { + return err + } + } + } } return nil } } +func ForkManagerFactory(forks *chain.Forks) error { + // place fork manager handler registration here + return nil +} + // Initialize initializes the consensus (e.g. setup data) func (p *Polybft) Initialize() error { p.logger.Info("initializing polybft...") @@ -250,6 +464,21 @@ func (p *Polybft) Initialize() error { return nil } +func ForkManagerInitialParamsFactory(config *chain.Chain) (*chain.ForkParams, error) { + pbftConfig, err := GetPolyBFTConfig(config) + if err != nil { + return nil, err + } + + return &chain.ForkParams{ + MaxValidatorSetSize: &pbftConfig.MaxValidatorSetSize, + EpochSize: &pbftConfig.EpochSize, + SprintSize: &pbftConfig.SprintSize, + BlockTime: &pbftConfig.BlockTime, + BlockTimeDrift: &pbftConfig.BlockTimeDrift, + }, nil +} + // Start starts the consensus and servers func (p *Polybft) Start() error { p.logger.Info("starting polybft consensus", "signer", p.key.String()) @@ -259,18 +488,21 @@ func (p *Polybft) Start() error { return fmt.Errorf("failed to start syncer. Error: %w", err) } - // start syncing - go func() { + // sync concurrently, retrying indefinitely + go common.RetryForever(context.Background(), time.Second, func(context.Context) error { blockHandler := func(b *types.FullBlock) bool { p.runtime.OnBlockInserted(b) return false } - if err := p.syncer.Sync(blockHandler); err != nil { p.logger.Error("blocks synchronization failed", "error", err) + + return err } - }() + + return nil + }) // start consensus runtime if err := p.startRuntime(); err != nil { @@ -321,6 +553,8 @@ func (p *Polybft) startConsensusProtocol() { return } + p.logger.Debug("peers connected") + newBlockSub := p.blockchain.SubscribeEvents() defer newBlockSub.Close() @@ -446,12 +680,12 @@ func (p *Polybft) VerifyHeader(header *types.Header) error { ) } - return p.verifyHeaderImpl(parent, header, nil) + return p.verifyHeaderImpl(parent, header, p.consensusConfig.BlockTimeDrift, nil) } -func (p *Polybft) verifyHeaderImpl(parent, header *types.Header, parents []*types.Header) error { +func (p *Polybft) verifyHeaderImpl(parent, header *types.Header, blockTimeDrift uint64, parents []*types.Header) error { // validate header fields - if err := validateHeaderFields(parent, header); err != nil { + if err := validateHeaderFields(parent, header, blockTimeDrift); err != nil { return fmt.Errorf("failed to validate header for block %d. error = %w", header.Number, err) } @@ -466,7 +700,7 @@ func (p *Polybft) verifyHeaderImpl(parent, header *types.Header, parents []*type header, parent, parents, p.blockchain.GetChainID(), p, bls.DomainCheckpointManager, p.logger) } -func (p *Polybft) GetValidators(blockNumber uint64, parents []*types.Header) (AccountSet, error) { +func (p *Polybft) GetValidators(blockNumber uint64, parents []*types.Header) (validator.AccountSet, error) { return p.validatorsCache.GetSnapshot(blockNumber, parents) } @@ -482,12 +716,52 @@ func (p *Polybft) GetBlockCreator(h *types.Header) (types.Address, error) { } // PreCommitState a hook to be called before finalizing state transition on inserting block -func (p *Polybft) PreCommitState(_ *types.Header, _ *state.Transition) error { - // Not required +func (p *Polybft) PreCommitState(block *types.Block, _ *state.Transition) error { + commitmentTxExists := false + + validators, err := p.GetValidators(block.Number()-1, nil) + if err != nil { + return err + } + + // validate commitment state transactions + for _, tx := range block.Transactions { + if tx.Type != types.StateTx { + continue + } + + decodedStateTx, err := decodeStateTransaction(tx.Input) + if err != nil { + return fmt.Errorf("unknown state transaction: tx=%v, error: %w", tx.Hash, err) + } + + if signedCommitment, ok := decodedStateTx.(*CommitmentMessageSigned); ok { + if commitmentTxExists { + return fmt.Errorf("only one commitment state tx is allowed per block: %v", tx.Hash) + } + + commitmentTxExists = true + + if err := verifyBridgeCommitmentTx( + tx.Hash, + signedCommitment, + validator.NewValidatorSet(validators, p.logger)); err != nil { + return err + } + } + } + return nil } -// GetBridgeProvider returns an instance of BridgeDataProvider +// GetBridgeProvider is an implementation of Consensus interface +// Returns an instance of BridgeDataProvider func (p *Polybft) GetBridgeProvider() consensus.BridgeDataProvider { return p.runtime } + +// GetBridgeProvider is an implementation of Consensus interface +// Filters extra data to not contain Committed field +func (p *Polybft) FilterExtra(extra []byte) ([]byte, error) { + return GetIbftExtraClean(extra) +} diff --git a/consensus/polybft/polybft_config.go b/consensus/polybft/polybft_config.go index 35fa509c99..feb39a1d56 100644 --- a/consensus/polybft/polybft_config.go +++ b/consensus/polybft/polybft_config.go @@ -1,25 +1,21 @@ package polybft import ( - "encoding/hex" "encoding/json" - "fmt" "math/big" - "os" - "path/filepath" - "time" "github.com/0xPolygon/polygon-edge/chain" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/types" ) +const ConsensusName = "polybft" + // PolyBFTConfig is the configuration file for the Polybft consensus protocol. type PolyBFTConfig struct { // InitialValidatorSet are the genesis validators - InitialValidatorSet []*Validator `json:"initialValidatorSet"` + InitialValidatorSet []*validator.GenesisValidator `json:"initialValidatorSet"` // Bridge is the rootchain bridge configuration Bridge *BridgeConfig `json:"bridge"` @@ -34,40 +30,84 @@ type PolyBFTConfig struct { SprintSize uint64 `json:"sprintSize"` // BlockTime is target frequency of blocks production - BlockTime time.Duration `json:"blockTime"` + BlockTime common.Duration `json:"blockTime"` // Governance is the initial governance address Governance types.Address `json:"governance"` - // MintableERC20Token denotes whether mintable ERC20 token is used - MintableERC20Token bool `json:"mintableERC20"` + // NativeTokenConfig defines name, symbol and decimal count of the native token + NativeTokenConfig *TokenConfig `json:"nativeTokenConfig"` InitialTrieRoot types.Hash `json:"initialTrieRoot"` + + // SupernetID indicates ID of given supernet generated by stake manager contract + SupernetID int64 `json:"supernetID"` + + // MinValidatorSetSize indicates the minimum size of validator set + MinValidatorSetSize uint64 `json:"minValidatorSetSize"` + + // MaxValidatorSetSize indicates the maximum size of validator set + MaxValidatorSetSize uint64 `json:"maxValidatorSetSize"` + + // RewardConfig defines rewards configuration + RewardConfig *RewardsConfig `json:"rewardConfig"` + + // BlockTimeDrift defines the time slot in which a new block can be created + BlockTimeDrift uint64 `json:"blockTimeDrift"` +} + +// LoadPolyBFTConfig loads chain config from provided path and unmarshals PolyBFTConfig +func LoadPolyBFTConfig(chainConfigFile string) (PolyBFTConfig, error) { + chainCfg, err := chain.ImportFromFile(chainConfigFile) + if err != nil { + return PolyBFTConfig{}, err + } + + polybftConfig, err := GetPolyBFTConfig(chainCfg) + if err != nil { + return PolyBFTConfig{}, err + } + + return polybftConfig, err } // GetPolyBFTConfig deserializes provided chain config and returns PolyBFTConfig func GetPolyBFTConfig(chainConfig *chain.Chain) (PolyBFTConfig, error) { - consensusConfigJSON, err := json.Marshal(chainConfig.Params.Engine["polybft"]) + consensusConfigJSON, err := json.Marshal(chainConfig.Params.Engine[ConsensusName]) if err != nil { return PolyBFTConfig{}, err } var polyBFTConfig PolyBFTConfig - err = json.Unmarshal(consensusConfigJSON, &polyBFTConfig) - - if err != nil { + if err = json.Unmarshal(consensusConfigJSON, &polyBFTConfig); err != nil { return PolyBFTConfig{}, err } return polyBFTConfig, nil } -// BridgeConfig is the rootchain bridge configuration +// BridgeConfig is the rootchain configuration, needed for bridging type BridgeConfig struct { - BridgeAddr types.Address `json:"stateSenderAddr"` - CheckpointAddr types.Address `json:"checkpointAddr"` - RootERC20PredicateAddr types.Address `json:"rootERC20PredicateAddr"` - RootNativeERC20Addr types.Address `json:"rootNativeERC20Addr"` + StateSenderAddr types.Address `json:"stateSenderAddress"` + CheckpointManagerAddr types.Address `json:"checkpointManagerAddress"` + ExitHelperAddr types.Address `json:"exitHelperAddress"` + RootERC20PredicateAddr types.Address `json:"erc20PredicateAddress"` + ChildMintableERC20PredicateAddr types.Address `json:"erc20ChildMintablePredicateAddress"` + RootNativeERC20Addr types.Address `json:"nativeERC20Address"` + RootERC721PredicateAddr types.Address `json:"erc721PredicateAddress"` + ChildMintableERC721PredicateAddr types.Address `json:"erc721ChildMintablePredicateAddress"` + RootERC1155PredicateAddr types.Address `json:"erc1155PredicateAddress"` + ChildMintableERC1155PredicateAddr types.Address `json:"erc1155ChildMintablePredicateAddress"` + ChildERC20Addr types.Address `json:"childERC20Address"` + ChildERC721Addr types.Address `json:"childERC721Address"` + ChildERC1155Addr types.Address `json:"childERC1155Address"` + CustomSupernetManagerAddr types.Address `json:"customSupernetManagerAddr"` + StakeManagerAddr types.Address `json:"stakeManagerAddr"` + // only populated if stake-manager-deploy command is executed, and used for e2e tests + StakeTokenAddr types.Address `json:"stakeTokenAddr,omitempty"` + BLSAddress types.Address `json:"blsAddr"` + BN256G2Address types.Address `json:"bn256G2Addr"` + JSONRPCEndpoint string `json:"jsonRPCEndpoint"` EventTrackerStartBlocks map[types.Address]uint64 `json:"eventTrackerStartBlocks"` } @@ -76,186 +116,115 @@ func (p *PolyBFTConfig) IsBridgeEnabled() bool { return p.Bridge != nil } -// Validator represents public information about validator accounts which are the part of genesis -type Validator struct { - Address types.Address - BlsPrivateKey *bls.PrivateKey - BlsKey string - BlsSignature string - Balance *big.Int - Stake *big.Int - MultiAddr string -} - -type validatorRaw struct { - Address types.Address `json:"address"` - BlsKey string `json:"blsKey"` - BlsSignature string `json:"blsSignature"` - Balance *string `json:"balance"` - Stake *string `json:"stake"` - MultiAddr string `json:"multiAddr"` -} - -func (v *Validator) MarshalJSON() ([]byte, error) { - raw := &validatorRaw{Address: v.Address, BlsKey: v.BlsKey, MultiAddr: v.MultiAddr, BlsSignature: v.BlsSignature} - raw.Balance = types.EncodeBigInt(v.Balance) - raw.Stake = types.EncodeBigInt(v.Stake) - - return json.Marshal(raw) +// RootchainConfig contains rootchain metadata (such as JSON RPC endpoint and contract addresses) +type RootchainConfig struct { + JSONRPCAddr string + + StateSenderAddress types.Address + CheckpointManagerAddress types.Address + BLSAddress types.Address + BN256G2Address types.Address + ExitHelperAddress types.Address + RootERC20PredicateAddress types.Address + ChildMintableERC20PredicateAddress types.Address + RootNativeERC20Address types.Address + ChildERC20Address types.Address + RootERC721PredicateAddress types.Address + ChildMintableERC721PredicateAddress types.Address + ChildERC721Address types.Address + RootERC1155PredicateAddress types.Address + ChildMintableERC1155PredicateAddress types.Address + ChildERC1155Address types.Address + CustomSupernetManagerAddress types.Address + StakeManagerAddress types.Address + StakeTokenAddress types.Address } -func (v *Validator) UnmarshalJSON(data []byte) error { - var ( - raw validatorRaw - err error - ) - - if err = json.Unmarshal(data, &raw); err != nil { - return err - } - - v.Address = raw.Address - v.BlsKey = raw.BlsKey - v.BlsSignature = raw.BlsSignature - v.MultiAddr = raw.MultiAddr - - v.Balance, err = types.ParseUint256orHex(raw.Balance) - if err != nil { - return err - } - - v.Stake, err = types.ParseUint256orHex(raw.Stake) - if err != nil { - return err - } - - return nil -} +// ToBridgeConfig creates BridgeConfig instance +func (r *RootchainConfig) ToBridgeConfig() *BridgeConfig { + return &BridgeConfig{ + JSONRPCEndpoint: r.JSONRPCAddr, -// UnmarshalBLSPublicKey unmarshals the hex encoded BLS public key -func (v *Validator) UnmarshalBLSPublicKey() (*bls.PublicKey, error) { - decoded, err := hex.DecodeString(v.BlsKey) - if err != nil { - return nil, err + StateSenderAddr: r.StateSenderAddress, + CheckpointManagerAddr: r.CheckpointManagerAddress, + ExitHelperAddr: r.ExitHelperAddress, + RootERC20PredicateAddr: r.RootERC20PredicateAddress, + ChildMintableERC20PredicateAddr: r.ChildMintableERC20PredicateAddress, + RootNativeERC20Addr: r.RootNativeERC20Address, + RootERC721PredicateAddr: r.RootERC721PredicateAddress, + ChildMintableERC721PredicateAddr: r.ChildMintableERC721PredicateAddress, + RootERC1155PredicateAddr: r.RootERC1155PredicateAddress, + ChildMintableERC1155PredicateAddr: r.ChildMintableERC1155PredicateAddress, + ChildERC20Addr: r.ChildERC20Address, + ChildERC721Addr: r.ChildERC721Address, + ChildERC1155Addr: r.ChildERC1155Address, + CustomSupernetManagerAddr: r.CustomSupernetManagerAddress, + StakeManagerAddr: r.StakeManagerAddress, + BLSAddress: r.BLSAddress, + BN256G2Address: r.BN256G2Address, } - - return bls.UnmarshalPublicKey(decoded) } -// UnmarshalBLSSignature unmarshals the hex encoded BLS signature -func (v *Validator) UnmarshalBLSSignature() (*bls.Signature, error) { - decoded, err := hex.DecodeString(v.BlsSignature) - if err != nil { - return nil, err - } - - return bls.UnmarshalSignature(decoded) +// TokenConfig is the configuration of native token used by edge network +type TokenConfig struct { + Name string `json:"name"` + Symbol string `json:"symbol"` + Decimals uint8 `json:"decimals"` + IsMintable bool `json:"isMintable"` + Owner types.Address `json:"owner"` } -// ToValidatorInitAPIBinding converts Validator to instance of contractsapi.ValidatorInit -func (v Validator) ToValidatorInitAPIBinding() (*contractsapi.ValidatorInit, error) { - blsSignature, err := v.UnmarshalBLSSignature() - if err != nil { - return nil, err - } - - signBigInts, err := blsSignature.ToBigInt() - if err != nil { - return nil, err - } +type RewardsConfig struct { + // TokenAddress is the address of reward token on child chain + TokenAddress types.Address - pubKey, err := v.UnmarshalBLSPublicKey() - if err != nil { - return nil, err - } + // WalletAddress is the address of reward wallet on child chain + WalletAddress types.Address - return &contractsapi.ValidatorInit{ - Addr: v.Address, - Pubkey: pubKey.ToBigInt(), - Signature: signBigInts, - Stake: new(big.Int).Set(v.Stake), - }, nil + // WalletAmount is the amount of tokens in reward wallet + WalletAmount *big.Int } -// ToValidatorMetadata creates ValidatorMetadata instance -func (v *Validator) ToValidatorMetadata() (*ValidatorMetadata, error) { - blsKey, err := v.UnmarshalBLSPublicKey() - if err != nil { - return nil, err +func (r *RewardsConfig) MarshalJSON() ([]byte, error) { + raw := &rewardsConfigRaw{ + TokenAddress: r.TokenAddress, + WalletAddress: r.WalletAddress, + WalletAmount: types.EncodeBigInt(r.WalletAmount), } - metadata := &ValidatorMetadata{ - Address: v.Address, - BlsKey: blsKey, - VotingPower: new(big.Int).Set(v.Stake), - IsActive: true, - } - - return metadata, nil -} - -// String implements fmt.Stringer interface -func (v *Validator) String() string { - return fmt.Sprintf("Address=%s; Balance=%d; P2P Multi addr=%s; BLS Key=%s;", - v.Address, v.Balance, v.MultiAddr, v.BlsKey) + return json.Marshal(raw) } -// RootchainConfig contains information about rootchain contract addresses -// as well as rootchain admin account address -type RootchainConfig struct { - StateSenderAddress types.Address `json:"stateSenderAddress"` - CheckpointManagerAddress types.Address `json:"checkpointManagerAddress"` - BLSAddress types.Address `json:"blsAddress"` - BN256G2Address types.Address `json:"bn256G2Address"` - ExitHelperAddress types.Address `json:"exitHelperAddress"` - RootERC20PredicateAddress types.Address `json:"rootERC20PredicateAddress"` - RootNativeERC20Address types.Address `json:"rootNativeERC20Address"` - ERC20TemplateAddress types.Address `json:"erc20TemplateAddress"` -} +func (r *RewardsConfig) UnmarshalJSON(data []byte) error { + var ( + raw rewardsConfigRaw + err error + ) -// ToBridgeConfig creates BridgeConfig instance -func (r *RootchainConfig) ToBridgeConfig() *BridgeConfig { - return &BridgeConfig{ - BridgeAddr: r.StateSenderAddress, - CheckpointAddr: r.CheckpointManagerAddress, - RootERC20PredicateAddr: r.RootERC20PredicateAddress, - RootNativeERC20Addr: r.RootNativeERC20Address, + if err = json.Unmarshal(data, &raw); err != nil { + return err } -} -// Manifest holds metadata, such as genesis validators and rootchain configuration -type Manifest struct { - GenesisValidators []*Validator `json:"validators"` - RootchainConfig *RootchainConfig `json:"rootchain"` - ChainID int64 `json:"chainID"` -} + r.TokenAddress = raw.TokenAddress + r.WalletAddress = raw.WalletAddress -// LoadManifest deserializes Manifest instance -func LoadManifest(metadataFile string) (*Manifest, error) { - data, err := os.ReadFile(metadataFile) + r.WalletAmount, err = types.ParseUint256orHex(raw.WalletAmount) if err != nil { - return nil, err - } - - var manifest Manifest - - if err := json.Unmarshal(data, &manifest); err != nil { - return nil, err + return err } - return &manifest, nil + return nil } -// Save marshals RootchainManifest instance to json and persists it to given location -func (m *Manifest) Save(manifestPath string) error { - data, err := json.MarshalIndent(m, "", " ") - if err != nil { - return fmt.Errorf("failed to marshal rootchain manifest to JSON: %w", err) - } - - if err := common.SaveFileSafe(filepath.Clean(manifestPath), data, 0660); err != nil { - return fmt.Errorf("failed to save rootchain manifest file: %w", err) - } +type rewardsConfigRaw struct { + TokenAddress types.Address `json:"rewardTokenAddress"` + WalletAddress types.Address `json:"rewardWalletAddress"` + WalletAmount *string `json:"rewardWalletAmount"` +} - return nil +// BurnContractInfo contains metadata for burn contract, which is part of EIP-1559 specification +type BurnContractInfo struct { + BlockNumber uint64 + Address types.Address + DestinationAddress types.Address } diff --git a/consensus/polybft/polybft_test.go b/consensus/polybft/polybft_test.go index f57cbdffc1..5ee111d3cb 100644 --- a/consensus/polybft/polybft_test.go +++ b/consensus/polybft/polybft_test.go @@ -5,9 +5,10 @@ import ( "testing" "time" + "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/consensus" - "github.com/0xPolygon/polygon-edge/consensus/ibft/signer" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/helper/progress" "github.com/0xPolygon/polygon-edge/txpool" @@ -16,6 +17,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" ) // the test initializes polybft and chain mock (map of headers) after which a new header is verified @@ -32,7 +34,7 @@ func TestPolybft_VerifyHeader(t *testing.T) { ) updateHeaderExtra := func(header *types.Header, - validators *ValidatorSetDelta, + validators *validator.ValidatorSetDelta, parentSignature *Signature, checkpointData *CheckpointData, committedAccounts []*wallet.Account) *Signature { @@ -41,14 +43,13 @@ func TestPolybft_VerifyHeader(t *testing.T) { Parent: parentSignature, Checkpoint: checkpointData, Committed: &Signature{}, - Seal: []byte{}, } if extra.Checkpoint == nil { extra.Checkpoint = &CheckpointData{} } - header.ExtraData = append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...) + header.ExtraData = extra.MarshalRLPTo(nil) header.ComputeHash() if len(committedAccounts) > 0 { @@ -56,24 +57,25 @@ func TestPolybft_VerifyHeader(t *testing.T) { require.NoError(t, err) extra.Committed = createSignature(t, committedAccounts, checkpointHash, bls.DomainCheckpointManager) - header.ExtraData = append(make([]byte, signer.IstanbulExtraVanity), extra.MarshalRLPTo(nil)...) + header.ExtraData = extra.MarshalRLPTo(nil) } return extra.Committed } // create all validators - validators := newTestValidators(t, allValidatorsSize) + validators := validator.NewTestValidators(t, allValidatorsSize) // create configuration polyBftConfig := PolyBFTConfig{ - InitialValidatorSet: validators.getParamValidators(), + InitialValidatorSet: validators.GetParamValidators(), EpochSize: fixedEpochSize, SprintSize: 5, + BlockTimeDrift: 10, } - validatorSet := validators.getPublicIdentities() - accounts := validators.getPrivateIdentities() + validatorSet := validators.GetPublicIdentities() + accounts := validators.GetPrivateIdentities() // calculate validators before and after the end of the first epoch validatorSetParent, validatorSetCurrent := validatorSet[:len(validatorSet)-1], validatorSet[1:] @@ -83,7 +85,7 @@ func TestPolybft_VerifyHeader(t *testing.T) { headersMap := &testHeadersMap{} // create genesis header - genesisDelta, err := createValidatorSetDelta(nil, validatorSetParent) + genesisDelta, err := validator.CreateValidatorSetDelta(nil, validatorSetParent) require.NoError(t, err) genesisHeader := &types.Header{Number: 0} @@ -94,7 +96,7 @@ func TestPolybft_VerifyHeader(t *testing.T) { // create headers from 1 to 9 for i := uint64(1); i < polyBftConfig.EpochSize; i++ { - delta, err := createValidatorSetDelta(validatorSetParent, validatorSetParent) + delta, err := validator.CreateValidatorSetDelta(validatorSetParent, validatorSetParent) require.NoError(t, err) header := &types.Header{Number: i} @@ -123,12 +125,12 @@ func TestPolybft_VerifyHeader(t *testing.T) { } // create parent header (block 10) - parentDelta, err := createValidatorSetDelta(validatorSetParent, validatorSetCurrent) + parentDelta, err := validator.CreateValidatorSetDelta(validatorSetParent, validatorSetCurrent) require.NoError(t, err) parentHeader := &types.Header{ Number: polyBftConfig.EpochSize, - Timestamp: uint64(time.Now().UTC().UnixMilli()), + Timestamp: uint64(time.Now().UTC().Unix()), } parentCommitment := updateHeaderExtra(parentHeader, parentDelta, nil, &CheckpointData{EpochNumber: 1}, accountSetParent) @@ -136,7 +138,7 @@ func TestPolybft_VerifyHeader(t *testing.T) { headersMap.addHeader(parentHeader) // create current header (block 11) with all appropriate fields required for validation - currentDelta, err := createValidatorSetDelta(validatorSetCurrent, validatorSetCurrent) + currentDelta, err := validator.CreateValidatorSetDelta(validatorSetCurrent, validatorSetCurrent) require.NoError(t, err) currentHeader := &types.Header{ @@ -271,3 +273,75 @@ func Test_Factory(t *testing.T) { assert.Equal(t, epochSize, polybft.consensusConfig.EpochSize) assert.Equal(t, params, polybft.config) } + +func Test_GenesisPostHookFactory(t *testing.T) { + t.Parallel() + + const ( + epochSize = 15 + maxValidators = 150 + ) + + validators := validator.NewTestValidators(t, 6) + bridgeCfg := createTestBridgeConfig() + cases := []struct { + name string + config *PolyBFTConfig + bridgeAllowList *chain.AddressListConfig + expectedErr error + }{ + { + name: "non-mintable native token; access lists disabled", + config: &PolyBFTConfig{ + InitialValidatorSet: validators.GetParamValidators(), + Bridge: bridgeCfg, + EpochSize: epochSize, + RewardConfig: &RewardsConfig{WalletAmount: ethgo.Ether(1000)}, + NativeTokenConfig: &TokenConfig{Name: "Test", Symbol: "TEST", Decimals: 18}, + MaxValidatorSetSize: maxValidators, + }, + }, + { + name: "mintable native token; access lists enabled", + config: &PolyBFTConfig{ + InitialValidatorSet: validators.GetParamValidators(), + Bridge: bridgeCfg, + EpochSize: epochSize, + RewardConfig: &RewardsConfig{WalletAmount: ethgo.Ether(1000)}, + NativeTokenConfig: &TokenConfig{Name: "Test Mintable", Symbol: "TEST_MNT", Decimals: 18, IsMintable: true}, + MaxValidatorSetSize: maxValidators, + }, + bridgeAllowList: &chain.AddressListConfig{ + AdminAddresses: []types.Address{validators.Validators["0"].Address()}, + EnabledAddresses: []types.Address{validators.Validators["1"].Address()}, + }, + }, + { + name: "missing bridge configuration", + config: &PolyBFTConfig{}, + expectedErr: errMissingBridgeConfig, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + params := &chain.Params{ + Engine: map[string]interface{}{ConsensusName: tc.config}, + BridgeAllowList: tc.bridgeAllowList, + } + chainConfig := &chain.Chain{Params: params, Genesis: &chain.Genesis{Alloc: make(map[types.Address]*chain.GenesisAccount)}} + initHandler := GenesisPostHookFactory(chainConfig, ConsensusName) + require.NotNil(t, initHandler) + + transition := newTestTransition(t, nil) + if tc.expectedErr == nil { + require.NoError(t, initHandler(transition)) + } else { + require.ErrorIs(t, initHandler(transition), tc.expectedErr) + } + }) + } +} diff --git a/consensus/polybft/proposer_calculator.go b/consensus/polybft/proposer_calculator.go index acbc301991..9c280bb9ae 100644 --- a/consensus/polybft/proposer_calculator.go +++ b/consensus/polybft/proposer_calculator.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" @@ -19,7 +20,7 @@ var ( // PrioritizedValidator holds ValidatorMetadata together with priority type PrioritizedValidator struct { - Metadata *ValidatorMetadata + Metadata *validator.ValidatorMetadata ProposerPriority *big.Int } @@ -52,7 +53,7 @@ func NewProposerSnapshotFromState(config *runtimeConfig) (*ProposerSnapshot, err } // NewProposerSnapshot creates ProposerSnapshot with height and validators with all priorities set to zero -func NewProposerSnapshot(height uint64, validators []*ValidatorMetadata) *ProposerSnapshot { +func NewProposerSnapshot(height uint64, validators []*validator.ValidatorMetadata) *ProposerSnapshot { validatorsSnap := make([]*PrioritizedValidator, len(validators)) for i, x := range validators { @@ -235,7 +236,7 @@ func (pc *ProposerCalculator) updatePerBlock(blockNumber uint64) error { return fmt.Errorf("cannot get block header and extra while updating proposers snapshot %d: %w", blockNumber, err) } - var newValidatorSet AccountSet = nil + var newValidatorSet validator.AccountSet = nil if extra.Validators != nil && !extra.Validators.IsEmpty() { newValidatorSet, err = pc.config.polybftBackend.GetValidators(blockNumber, nil) @@ -294,7 +295,7 @@ func incrementProposerPriorityNTimes(snapshot *ProposerSnapshot, times uint64) ( return proposer, nil } -func updateValidators(snapshot *ProposerSnapshot, newValidatorSet AccountSet) error { +func updateValidators(snapshot *ProposerSnapshot, newValidatorSet validator.AccountSet) error { if newValidatorSet.Len() == 0 { return nil } diff --git a/consensus/polybft/proposer_calculator_test.go b/consensus/polybft/proposer_calculator_test.go index 7e51a606c9..a746468e21 100644 --- a/consensus/polybft/proposer_calculator_test.go +++ b/consensus/polybft/proposer_calculator_test.go @@ -6,6 +6,7 @@ import ( "testing" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/assert" @@ -15,10 +16,10 @@ import ( func TestProposerCalculator_SetIndex(t *testing.T) { t.Parallel() - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}, []uint64{10, 100, 1, 50, 30}) - metadata := validators.getPublicIdentities() + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}, []uint64{10, 100, 1, 50, 30}) + metadata := validators.GetPublicIdentities() - vs := validators.toValidatorSet() + vs := validators.ToValidatorSet() snapshot := NewProposerSnapshot(1, metadata) @@ -39,8 +40,8 @@ func TestProposerCalculator_SetIndex(t *testing.T) { func TestProposerCalculator_RegularFlow(t *testing.T) { t.Parallel() - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}, []uint64{1, 2, 3, 4, 5}) - metadata := validators.getPublicIdentities() + validators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E"}, []uint64{1, 2, 3, 4, 5}) + metadata := validators.GetPublicIdentities() snapshot := NewProposerSnapshot(0, metadata) @@ -80,7 +81,7 @@ func TestProposerCalculator_SamePriority(t *testing.T) { require.NoError(t, err) // at some point priorities will be the same and bytes address will be compared - vs := NewValidatorSet([]*ValidatorMetadata{ + vs := validator.NewValidatorSet([]*validator.ValidatorMetadata{ { BlsKey: keys[0].PublicKey(), Address: types.Address{0x1}, @@ -126,7 +127,7 @@ func TestProposerCalculator_InversePriorityOrderWithExpectedListOfSelection(t *t require.NoError(t, err) // priorities are from high to low vp in validator set - vset := NewValidatorSet([]*ValidatorMetadata{ + vset := validator.NewValidatorSet([]*validator.ValidatorMetadata{ { BlsKey: keys[0].PublicKey(), Address: types.Address{0x1}, @@ -175,7 +176,7 @@ func TestProposerCalculator_IncrementProposerPrioritySameVotingPower(t *testing. keys, err := bls.CreateRandomBlsKeys(3) require.NoError(t, err) - vs := NewValidatorSet([]*ValidatorMetadata{ + vs := validator.NewValidatorSet([]*validator.ValidatorMetadata{ { BlsKey: keys[0].PublicKey(), Address: types.Address{0x1}, @@ -231,7 +232,7 @@ func TestProposerCalculator_AveragingInIncrementProposerPriorityWithVotingPower( vp2 := int64(1) total := vp0 + vp1 + vp2 avg := (vp0 + vp1 + vp2 - total) / 3 - valz := []*ValidatorMetadata{ + valz := []*validator.ValidatorMetadata{ { BlsKey: keys[0].PublicKey(), Address: types.Address{0x1}, @@ -375,11 +376,11 @@ func TestProposerCalculator_UpdatesForNewValidatorSet(t *testing.T) { keys, err := bls.CreateRandomBlsKeys(2) require.NoError(t, err) - v1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(100)} - v2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(100)} + v1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(100)} + v2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(100)} - accountSet := []*ValidatorMetadata{v1, v2} - vs := NewValidatorSet(accountSet, hclog.NewNullLogger()) + accountSet := []*validator.ValidatorMetadata{v1, v2} + vs := validator.NewValidatorSet(accountSet, hclog.NewNullLogger()) snapshot := NewProposerSnapshot(0, vs.Accounts()) @@ -402,7 +403,8 @@ func TestProposerCalculator_UpdatesForNewValidatorSet(t *testing.T) { // verify that priorities are scaled diff := computeMaxMinPriorityDiff(snapshot.Validators) - diffMax := new(big.Int).Mul(priorityWindowSizeFactor, vs.totalVotingPower) + totalVotingPower := vs.TotalVotingPower() + diffMax := new(big.Int).Mul(priorityWindowSizeFactor, &totalVotingPower) assert.True(t, diff.Cmp(diffMax) <= 0, "expected priority distance < %d. Got %d", diffMax, diff) } @@ -414,7 +416,7 @@ func TestProposerCalculator_GetLatestProposer(t *testing.T) { count = 10 ) - validatorSet := newTestValidators(t, count).getPublicIdentities() + validatorSet := validator.NewTestValidators(t, count).GetPublicIdentities() snapshot := NewProposerSnapshot(0, validatorSet) snapshot.Validators[bestIdx].ProposerPriority = big.NewInt(1000000) @@ -447,13 +449,13 @@ func TestProposerCalculator_UpdateValidatorsSameVpUpdatedAndNewAdded(t *testing. keys, err := bls.CreateRandomBlsKeys(8) require.NoError(t, err) - v1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(100)} - v2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(100)} - v3 := &ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(100)} - v4 := &ValidatorMetadata{Address: types.Address{0x4}, BlsKey: keys[3].PublicKey(), VotingPower: big.NewInt(100)} - v5 := &ValidatorMetadata{Address: types.Address{0x5}, BlsKey: keys[4].PublicKey(), VotingPower: big.NewInt(100)} + v1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(100)} + v2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(100)} + v3 := &validator.ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(100)} + v4 := &validator.ValidatorMetadata{Address: types.Address{0x4}, BlsKey: keys[3].PublicKey(), VotingPower: big.NewInt(100)} + v5 := &validator.ValidatorMetadata{Address: types.Address{0x5}, BlsKey: keys[4].PublicKey(), VotingPower: big.NewInt(100)} - vs := NewValidatorSet([]*ValidatorMetadata{v1, v2, v3, v4, v5}, hclog.NewNullLogger()) + vs := validator.NewValidatorSet([]*validator.ValidatorMetadata{v1, v2, v3, v4, v5}, hclog.NewNullLogger()) snapshot := NewProposerSnapshot(0, vs.Accounts()) @@ -466,12 +468,12 @@ func TestProposerCalculator_UpdateValidatorsSameVpUpdatedAndNewAdded(t *testing. } // updated old validators - u1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(10)} - u2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(10)} + u1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(10)} + u2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(10)} // added new validator - a1 := &ValidatorMetadata{Address: types.Address{0x9}, BlsKey: keys[7].PublicKey(), VotingPower: big.NewInt(100)} + a1 := &validator.ValidatorMetadata{Address: types.Address{0x9}, BlsKey: keys[7].PublicKey(), VotingPower: big.NewInt(100)} - newAccountSet := []*ValidatorMetadata{u1, u2, a1} + newAccountSet := []*validator.ValidatorMetadata{u1, u2, a1} require.NoError(t, updateValidators(snapshot, newAccountSet)) assert.Equal(t, 3, len(snapshot.Validators)) @@ -512,11 +514,11 @@ func TestProposerCalculator_UpdateValidators(t *testing.T) { keys, err := bls.CreateRandomBlsKeys(4) require.NoError(t, err) - v1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(10)} - v2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(20)} - v3 := &ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(30)} + v1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(10)} + v2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(20)} + v3 := &validator.ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(30)} - vs := NewValidatorSet([]*ValidatorMetadata{v1, v2, v3}, hclog.NewNullLogger()) + vs := validator.NewValidatorSet([]*validator.ValidatorMetadata{v1, v2, v3}, hclog.NewNullLogger()) snapshot := NewProposerSnapshot(0, vs.Accounts()) require.Equal(t, big.NewInt(60), snapshot.GetTotalVotingPower()) @@ -534,13 +536,13 @@ func TestProposerCalculator_UpdateValidators(t *testing.T) { require.NoError(t, err) // updated - u1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(100)} - u2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(200)} - u3 := &ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(300)} + u1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(100)} + u2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(200)} + u3 := &validator.ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(300)} // added - a1 := &ValidatorMetadata{Address: types.Address{0x4}, BlsKey: keys[3].PublicKey(), VotingPower: big.NewInt(400)} + a1 := &validator.ValidatorMetadata{Address: types.Address{0x4}, BlsKey: keys[3].PublicKey(), VotingPower: big.NewInt(400)} - require.NoError(t, updateValidators(snapshot, []*ValidatorMetadata{u1, u2, u3, a1})) + require.NoError(t, updateValidators(snapshot, []*validator.ValidatorMetadata{u1, u2, u3, a1})) require.Equal(t, 4, len(snapshot.Validators)) // priorities are from previous iteration @@ -560,11 +562,11 @@ func TestProposerCalculator_ScaleAfterDelete(t *testing.T) { keys, err := bls.CreateRandomBlsKeys(3) require.NoError(t, err) - v1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(10)} - v2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(10)} - v3 := &ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(80000)} + v1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(10)} + v2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(10)} + v3 := &validator.ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(80000)} - vs := NewValidatorSet([]*ValidatorMetadata{v1, v2, v3}, hclog.NewNullLogger()) + vs := validator.NewValidatorSet([]*validator.ValidatorMetadata{v1, v2, v3}, hclog.NewNullLogger()) snapshot := NewProposerSnapshot(0, vs.Accounts()) assert.Equal(t, big.NewInt(80020), snapshot.GetTotalVotingPower()) @@ -584,13 +586,13 @@ func TestProposerCalculator_ScaleAfterDelete(t *testing.T) { assert.Equal(t, types.Address{0x3}, proposer.Metadata.Address) // reduce validator voting power from 8k to 1 - u1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(10)} - u2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(10)} + u1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(10)} + u2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(10)} require.Equal(t, big.NewInt(-40010), snapshot.Validators[0].ProposerPriority) require.Equal(t, big.NewInt(40010), snapshot.Validators[1].ProposerPriority) - require.NoError(t, updateValidators(snapshot, []*ValidatorMetadata{u1, u2})) + require.NoError(t, updateValidators(snapshot, []*validator.ValidatorMetadata{u1, u2})) // maxdiff = 2*tvp = 40 // diff(min,max) (-40010, 40010) = 80020 @@ -607,11 +609,11 @@ func TestProposerCalculator_ShiftAfterUpdate(t *testing.T) { keys, err := bls.CreateRandomBlsKeys(3) require.NoError(t, err) - v1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(50)} - v2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(80)} - v3 := &ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(100000)} + v1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(50)} + v2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(80)} + v3 := &validator.ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(100000)} - vs := NewValidatorSet([]*ValidatorMetadata{v1, v2, v3}, hclog.NewNullLogger()) + vs := validator.NewValidatorSet([]*validator.ValidatorMetadata{v1, v2, v3}, hclog.NewNullLogger()) snapshot := NewProposerSnapshot(0, vs.Accounts()) assert.Equal(t, big.NewInt(100130), snapshot.GetTotalVotingPower()) @@ -620,10 +622,10 @@ func TestProposerCalculator_ShiftAfterUpdate(t *testing.T) { require.NoError(t, err) // updates - u1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(5)} - u2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(8)} + u1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(5)} + u2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(8)} - require.NoError(t, updateValidators(snapshot, []*ValidatorMetadata{u1, u2})) + require.NoError(t, updateValidators(snapshot, []*validator.ValidatorMetadata{u1, u2})) // maxdiff = 2*tvp = 26 // diff(min,max) (-260, 19610) = 19870 @@ -641,11 +643,11 @@ func TestProposerCalculator_UpdateValidatorSet(t *testing.T) { keys, err := bls.CreateRandomBlsKeys(3) require.NoError(t, err) - v1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(1)} - v2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(8)} - v3 := &ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(15)} + v1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(1)} + v2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(8)} + v3 := &validator.ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(15)} - vs := NewValidatorSet([]*ValidatorMetadata{v1, v2, v3}, hclog.NewNullLogger()) + vs := validator.NewValidatorSet([]*validator.ValidatorMetadata{v1, v2, v3}, hclog.NewNullLogger()) snapshot := NewProposerSnapshot(0, vs.Accounts()) assert.Equal(t, big.NewInt(24), snapshot.GetTotalVotingPower()) @@ -654,11 +656,11 @@ func TestProposerCalculator_UpdateValidatorSet(t *testing.T) { require.NoError(t, err) // modified validator - u1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(5)} + u1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(5)} // added validator - a1 := &ValidatorMetadata{Address: types.Address{0x4}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(8)} + a1 := &validator.ValidatorMetadata{Address: types.Address{0x4}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(8)} - require.NoError(t, updateValidators(snapshot, []*ValidatorMetadata{u1, a1})) + require.NoError(t, updateValidators(snapshot, []*validator.ValidatorMetadata{u1, a1})) // expecting 2 validators with updated voting power and total voting power require.Equal(t, 2, len(snapshot.Validators)) require.Equal(t, types.Address{0x1}, snapshot.Validators[0].Metadata.Address) @@ -677,10 +679,10 @@ func TestProposerCalculator_AddValidator(t *testing.T) { keys, err := bls.CreateRandomBlsKeys(3) require.NoError(t, err) - v1 := &ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(3)} - v2 := &ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(1)} + v1 := &validator.ValidatorMetadata{Address: types.Address{0x1}, BlsKey: keys[0].PublicKey(), VotingPower: big.NewInt(3)} + v2 := &validator.ValidatorMetadata{Address: types.Address{0x2}, BlsKey: keys[1].PublicKey(), VotingPower: big.NewInt(1)} - vs := NewValidatorSet([]*ValidatorMetadata{v1, v2}, hclog.NewNullLogger()) + vs := validator.NewValidatorSet([]*validator.ValidatorMetadata{v1, v2}, hclog.NewNullLogger()) snapshot := NewProposerSnapshot(0, vs.Accounts()) assert.Equal(t, big.NewInt(4), snapshot.GetTotalVotingPower()) @@ -696,9 +698,9 @@ func TestProposerCalculator_AddValidator(t *testing.T) { require.Equal(t, big.NewInt(-2), snapshot.Validators[0].ProposerPriority) require.Equal(t, big.NewInt(2), snapshot.Validators[1].ProposerPriority) - a1 := &ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(8)} + a1 := &validator.ValidatorMetadata{Address: types.Address{0x3}, BlsKey: keys[2].PublicKey(), VotingPower: big.NewInt(8)} - require.NoError(t, updateValidators(snapshot, []*ValidatorMetadata{v1, v2, a1})) + require.NoError(t, updateValidators(snapshot, []*validator.ValidatorMetadata{v1, v2, a1})) // updated vp: 8+3+1 = 12 // added validator priority = -1.125*8 ~ -13 diff --git a/consensus/polybft/runtime_helpers_test.go b/consensus/polybft/runtime_helpers_test.go index fdf1fa1e43..078129d9cc 100644 --- a/consensus/polybft/runtime_helpers_test.go +++ b/consensus/polybft/runtime_helpers_test.go @@ -5,6 +5,7 @@ import ( "github.com/0xPolygon/polygon-edge/blockchain" "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -13,11 +14,11 @@ import ( func TestHelpers_isEpochEndingBlock_DeltaNotEmpty(t *testing.T) { t.Parallel() - validators := newTestValidators(t, 3).getPublicIdentities() + validators := validator.NewTestValidators(t, 3).GetPublicIdentities() bitmap := bitmap.Bitmap{} bitmap.Set(0) - delta := &ValidatorSetDelta{ + delta := &validator.ValidatorSetDelta{ Added: validators[1:], Removed: bitmap, } @@ -36,7 +37,7 @@ func TestHelpers_isEpochEndingBlock_NoBlock(t *testing.T) { blockchainMock := new(blockchainMock) blockchainMock.On("GetHeaderByNumber", mock.Anything).Return(&types.Header{}, false) - extra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 2}, Validators: &ValidatorSetDelta{}} + extra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 2}, Validators: &validator.ValidatorSetDelta{}} blockNumber := uint64(20) isEndOfEpoch, err := isEpochEndingBlock(blockNumber, extra, blockchainMock) @@ -49,15 +50,15 @@ func TestHelpers_isEpochEndingBlock_EpochsNotTheSame(t *testing.T) { blockchainMock := new(blockchainMock) - nextBlockExtra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 3}, Validators: &ValidatorSetDelta{}} + nextBlockExtra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 3}, Validators: &validator.ValidatorSetDelta{}} nextBlock := &types.Header{ Number: 21, - ExtraData: append(make([]byte, ExtraVanity), nextBlockExtra.MarshalRLPTo(nil)...), + ExtraData: nextBlockExtra.MarshalRLPTo(nil), } blockchainMock.On("GetHeaderByNumber", mock.Anything).Return(nextBlock, true) - extra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 2}, Validators: &ValidatorSetDelta{}} + extra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 2}, Validators: &validator.ValidatorSetDelta{}} blockNumber := uint64(20) isEndOfEpoch, err := isEpochEndingBlock(blockNumber, extra, blockchainMock) @@ -70,15 +71,15 @@ func TestHelpers_isEpochEndingBlock_EpochsAreTheSame(t *testing.T) { blockchainMock := new(blockchainMock) - nextBlockExtra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 2}, Validators: &ValidatorSetDelta{}} + nextBlockExtra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 2}, Validators: &validator.ValidatorSetDelta{}} nextBlock := &types.Header{ Number: 16, - ExtraData: append(make([]byte, ExtraVanity), nextBlockExtra.MarshalRLPTo(nil)...), + ExtraData: nextBlockExtra.MarshalRLPTo(nil), } blockchainMock.On("GetHeaderByNumber", mock.Anything).Return(nextBlock, true) - extra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 2}, Validators: &ValidatorSetDelta{}} + extra := &Extra{Checkpoint: &CheckpointData{EpochNumber: 2}, Validators: &validator.ValidatorSetDelta{}} blockNumber := uint64(15) isEndOfEpoch, err := isEpochEndingBlock(blockNumber, extra, blockchainMock) diff --git a/consensus/polybft/sc_integration_test.go b/consensus/polybft/sc_integration_test.go index 9f9aa7ec76..c850705553 100644 --- a/consensus/polybft/sc_integration_test.go +++ b/consensus/polybft/sc_integration_test.go @@ -1,45 +1,53 @@ package polybft import ( - "encoding/hex" "math" "math/big" "strconv" "testing" - "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/abi" "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" - "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/contracts" - secretsHelper "github.com/0xPolygon/polygon-edge/secrets/helper" + "github.com/0xPolygon/polygon-edge/crypto" + "github.com/0xPolygon/polygon-edge/helper/hex" "github.com/0xPolygon/polygon-edge/state" "github.com/0xPolygon/polygon-edge/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/umbracle/ethgo" - "github.com/umbracle/ethgo/abi" ) func TestIntegratoin_PerformExit(t *testing.T) { t.Parallel() - // create validator set - currentValidators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D"}, []uint64{100, 100, 100, 100}) - accSet := currentValidators.getPublicIdentities() + const gasLimit = 1000000000000 - senderAddress := types.Address{1} - bn256Addr := types.Address{2} - l1StateReceiverAddr := types.Address{3} + // create validator set and checkpoint mngr + currentValidators := validator.NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D"}, []uint64{100, 100, 100, 100}) + accSet := currentValidators.GetPublicIdentities() + cm := checkpointManager{blockchain: &blockchainMock{}} + + deployerAddress := types.Address{76, 76, 1} // account that will deploy contracts + senderAddress := types.Address{1} // account that sends exit/withdraw transactions + receiverAddr := types.Address{6} // account that receive tokens + amount1 := big.NewInt(3) // amount of the first widrawal + amount2 := big.NewInt(2) // amount of the second widrawal + bn256Addr := types.Address{2} // bls contract + stateSenderAddr := types.Address{5} // generic bridge contract on rootchain alloc := map[types.Address]*chain.GenesisAccount{ - senderAddress: {Balance: big.NewInt(100000000000)}, + senderAddress: {Balance: new(big.Int).Add(amount1, amount2)}, // give some ethers to sender + deployerAddress: {Balance: ethgo.Ether(100)}, // give 100 ethers to deployer contracts.BLSContract: {Code: contractsapi.BLS.DeployedBytecode}, bn256Addr: {Code: contractsapi.BLS256.DeployedBytecode}, - l1StateReceiverAddr: {Code: contractsapi.TestL1StateReceiver.DeployedBytecode}, + stateSenderAddr: {Code: contractsapi.StateSender.DeployedBytecode}, } transition := newTestTransition(t, alloc) @@ -47,37 +55,47 @@ func TestIntegratoin_PerformExit(t *testing.T) { input, err := abi.GetMethod(function).Encode(args) require.NoError(t, err) - result := transition.Call2(senderAddress, addr, input, big.NewInt(0), 1000000000) - require.NoError(t, result.Err) + result := transition.Call2(deployerAddress, addr, input, big.NewInt(0), gasLimit) require.True(t, result.Succeeded()) - require.False(t, result.Failed()) return result.ReturnValue } + // deploy MockERC20 as root chain ERC 20 token + rootERC20Addr := deployAndInitContract(t, transition, contractsapi.RootERC20, deployerAddress, nil) + + // deploy CheckpointManager checkpointManagerInit := func() ([]byte, error) { - initialize := contractsapi.InitializeCheckpointManagerFn{ + return (&contractsapi.InitializeCheckpointManagerFn{ NewBls: contracts.BLSContract, NewBn256G2: bn256Addr, NewValidatorSet: accSet.ToAPIBinding(), ChainID_: big.NewInt(0), - } - - return initialize.EncodeAbi() + }).EncodeAbi() } + checkpointManagerAddr := deployAndInitContract(t, transition, contractsapi.CheckpointManager, deployerAddress, checkpointManagerInit) - checkpointManagerAddr := deployAndInitContract(t, transition, contractsapi.CheckpointManager, senderAddress, checkpointManagerInit) - + // deploy ExitHelper exitHelperInit := func() ([]byte, error) { - return contractsapi.ExitHelper.Abi.GetMethod("initialize").Encode([]interface{}{ethgo.Address(checkpointManagerAddr)}) + return (&contractsapi.InitializeExitHelperFn{NewCheckpointManager: checkpointManagerAddr}).EncodeAbi() + } + exitHelperContractAddress := deployAndInitContract(t, transition, contractsapi.ExitHelper, deployerAddress, exitHelperInit) + + // deploy RootERC20Predicate + rootERC20PredicateInit := func() ([]byte, error) { + return (&contractsapi.InitializeRootERC20PredicateFn{ + NewStateSender: stateSenderAddr, + NewExitHelper: exitHelperContractAddress, + NewChildERC20Predicate: contracts.ChildERC20PredicateContract, + NewChildTokenTemplate: contracts.ChildERC20Contract, + NativeTokenRootAddress: contracts.NativeERC20TokenContract, + }).EncodeAbi() } - exitHelperContractAddress := deployAndInitContract(t, transition, contractsapi.ExitHelper, senderAddress, exitHelperInit) + rootERC20PredicateAddr := deployAndInitContract(t, transition, contractsapi.RootERC20Predicate, deployerAddress, rootERC20PredicateInit) + // validate initialization of CheckpointManager require.Equal(t, getField(checkpointManagerAddr, contractsapi.CheckpointManager.Abi, "currentCheckpointBlockNumber")[31], uint8(0)) - cm := checkpointManager{ - blockchain: &blockchainMock{}, - } accSetHash, err := accSet.Hash() require.NoError(t, err) @@ -86,26 +104,81 @@ func TestIntegratoin_PerformExit(t *testing.T) { epochNumber := uint64(1) blockRound := uint64(1) + // mint + mintInput, err := (&contractsapi.MintRootERC20Fn{ + To: senderAddress, + Amount: alloc[senderAddress].Balance, + }).EncodeAbi() + require.NoError(t, err) + + result := transition.Call2(deployerAddress, rootERC20Addr, mintInput, nil, gasLimit) + require.NoError(t, result.Err) + + // approve + approveInput, err := (&contractsapi.ApproveRootERC20Fn{ + Spender: rootERC20PredicateAddr, + Amount: alloc[senderAddress].Balance, + }).EncodeAbi() + require.NoError(t, err) + + result = transition.Call2(senderAddress, rootERC20Addr, approveInput, big.NewInt(0), gasLimit) + require.NoError(t, result.Err) + + // deposit + depositInput, err := (&contractsapi.DepositToRootERC20PredicateFn{ + RootToken: rootERC20Addr, + Receiver: receiverAddr, + Amount: new(big.Int).Add(amount1, amount2), + }).EncodeAbi() + require.NoError(t, err) + + // send sync events to childchain so that receiver can obtain tokens + result = transition.Call2(senderAddress, rootERC20PredicateAddr, depositInput, big.NewInt(0), gasLimit) + require.NoError(t, result.Err) + + // simulate withdrawal from childchain to rootchain + widthdrawSig := crypto.Keccak256([]byte("WITHDRAW")) + erc20DataType := abi.MustNewType( + "tuple(bytes32 withdrawSignature, address rootToken, address withdrawer, address receiver, uint256 amount)") + + exitData1, err := erc20DataType.Encode(map[string]interface{}{ + "withdrawSignature": widthdrawSig, + "rootToken": ethgo.Address(rootERC20Addr), + "withdrawer": ethgo.Address(senderAddress), + "receiver": ethgo.Address(receiverAddr), + "amount": amount1, + }) + require.NoError(t, err) + + exitData2, err := erc20DataType.Encode(map[string]interface{}{ + "withdrawSignature": widthdrawSig, + "rootToken": ethgo.Address(rootERC20Addr), + "withdrawer": ethgo.Address(senderAddress), + "receiver": ethgo.Address(receiverAddr), + "amount": amount2, + }) + require.NoError(t, err) + exits := []*ExitEvent{ { ID: 1, - Sender: ethgo.Address{7}, - Receiver: ethgo.Address(l1StateReceiverAddr), - Data: []byte{123}, + Sender: ethgo.Address(contracts.ChildERC20PredicateContract), + Receiver: ethgo.Address(rootERC20PredicateAddr), + Data: exitData1, }, { ID: 2, - Sender: ethgo.Address{7}, - Receiver: ethgo.Address(l1StateReceiverAddr), - Data: []byte{21}, + Sender: ethgo.Address(contracts.ChildERC20PredicateContract), + Receiver: ethgo.Address(rootERC20PredicateAddr), + Data: exitData2, }, } - exitTrie, err := createExitTree(exits) + exitTree, err := createExitTree(exits) require.NoError(t, err) - eventRoot := exitTrie.Hash() + eventRoot := exitTree.Hash() - checkpointData := CheckpointData{ + checkpointData := &CheckpointData{ BlockRound: blockRound, EpochNumber: epochNumber, CurrentValidatorsHash: accSetHash, @@ -119,13 +192,12 @@ func TestIntegratoin_PerformExit(t *testing.T) { blockHash) require.NoError(t, err) - bmp := bitmap.Bitmap{} i := uint64(0) + bmp := bitmap.Bitmap{} + signatures := bls.Signatures(nil) - var signatures bls.Signatures - - currentValidators.iterAcct(nil, func(v *testValidator) { - signatures = append(signatures, v.mustSign(checkpointHash[:], bls.DomainCheckpointManager)) + currentValidators.IterAcct(nil, func(v *validator.TestValidator) { + signatures = append(signatures, v.MustSign(checkpointHash[:], bls.DomainCheckpointManager)) bmp.Set(i) i++ }) @@ -134,78 +206,65 @@ func TestIntegratoin_PerformExit(t *testing.T) { require.NoError(t, err) extra := &Extra{ - Checkpoint: &checkpointData, - } - extra.Committed = &Signature{ - AggregatedSignature: aggSignature, - Bitmap: bmp, + Checkpoint: checkpointData, + Committed: &Signature{ + AggregatedSignature: aggSignature, + Bitmap: bmp, + }, } - submitCheckpointEncoded, err := cm.abiEncodeCheckpointBlock( - blockNumber, - blockHash, - extra, - accSet) + // submit a checkpoint + submitCheckpointEncoded, err := cm.abiEncodeCheckpointBlock(blockNumber, blockHash, extra, accSet) require.NoError(t, err) - result := transition.Call2(senderAddress, checkpointManagerAddr, submitCheckpointEncoded, big.NewInt(0), 1000000000) + result = transition.Call2(senderAddress, checkpointManagerAddr, submitCheckpointEncoded, big.NewInt(0), gasLimit) require.NoError(t, result.Err) require.Equal(t, getField(checkpointManagerAddr, contractsapi.CheckpointManager.Abi, "currentCheckpointBlockNumber")[31], uint8(1)) - //check that the exit havent performed + // check that the exit hasn't performed res := getField(exitHelperContractAddress, contractsapi.ExitHelper.Abi, "processedExits", exits[0].ID) - require.Equal(t, int(res[31]), 0) + require.Equal(t, 0, int(res[31])) var exitEventAPI contractsapi.L2StateSyncedEvent proofExitEvent, err := exitEventAPI.Encode(exits[0]) require.NoError(t, err) - proof, err := exitTrie.GenerateProof(proofExitEvent) + proof, err := exitTree.GenerateProof(proofExitEvent) require.NoError(t, err) - leafIndex, err := exitTrie.LeafIndex(proofExitEvent) + leafIndex, err := exitTree.LeafIndex(proofExitEvent) require.NoError(t, err) - ehExit, err := contractsapi.ExitHelper.Abi.GetMethod("exit").Encode([]interface{}{ - blockNumber, - leafIndex, - proofExitEvent, - proof, - }) + exitFnInput, err := (&contractsapi.ExitExitHelperFn{ + BlockNumber: new(big.Int).SetUint64(blockNumber), + LeafIndex: new(big.Int).SetUint64(leafIndex), + UnhashedLeaf: proofExitEvent, + Proof: proof, + }).EncodeAbi() require.NoError(t, err) - result = transition.Call2(senderAddress, exitHelperContractAddress, ehExit, big.NewInt(0), 1000000000) + result = transition.Call2(senderAddress, exitHelperContractAddress, exitFnInput, big.NewInt(0), gasLimit) require.NoError(t, result.Err) - // check true + // check that first exit event is processed res = getField(exitHelperContractAddress, contractsapi.ExitHelper.Abi, "processedExits", exits[0].ID) - require.Equal(t, int(res[31]), 1) + require.Equal(t, 1, int(res[31])) - lastID := getField(l1StateReceiverAddr, contractsapi.TestL1StateReceiver.Abi, "id") - require.Equal(t, uint8(1), lastID[31]) - - lastAddr := getField(l1StateReceiverAddr, contractsapi.TestL1StateReceiver.Abi, "addr") - require.Equal(t, exits[0].Sender[:], lastAddr[12:]) - - lastCounter := getField(l1StateReceiverAddr, contractsapi.TestL1StateReceiver.Abi, "counter") - require.Equal(t, lastCounter[31], uint8(1)) + res = getField(rootERC20Addr, contractsapi.RootERC20.Abi, "balanceOf", receiverAddr) + require.Equal(t, amount1, new(big.Int).SetBytes(res)) } func TestIntegration_CommitEpoch(t *testing.T) { t.Parallel() // init validator sets - // (cannot run test case with more than 100 validators at the moment, - // because active validator set is capped to 100 on smart contract side) validatorSetSize := []int{5, 10, 50, 100} - // number of delegators per validator - delegatorsPerValidator := 100 - intialBalance := uint64(5 * math.Pow(10, 18)) // 5 tokens - reward := uint64(math.Pow(10, 18)) // 1 token - delegateAmount := uint64(math.Pow(10, 18)) / 2 // 0.5 token + intialBalance := uint64(5 * math.Pow(10, 18)) // 5 tokens + reward := uint64(math.Pow(10, 18)) // 1 token + walletAddress := types.StringToAddress("1234889893") - validatorSets := make([]*testValidators, len(validatorSetSize), len(validatorSetSize)) + validatorSets := make([]*validator.TestValidators, len(validatorSetSize), len(validatorSetSize)) // create all validator sets which will be used in test for i, size := range validatorSetSize { @@ -217,113 +276,114 @@ func TestIntegration_CommitEpoch(t *testing.T) { vps[j] = intialBalance } - validatorSets[i] = newTestValidatorsWithAliases(t, aliases, vps) + validatorSets[i] = validator.NewTestValidatorsWithAliases(t, aliases, vps) } // iterate through the validator set and do the test for each of them for _, currentValidators := range validatorSets { - accSet := currentValidators.getPublicIdentities() - accSetPrivateKeys := currentValidators.getPrivateIdentities() - valid2deleg := make(map[types.Address][]*wallet.Key, accSet.Len()) // delegators assigned to validators + accSet := currentValidators.GetPublicIdentities() + // validator data for polybft config + initValidators := make([]*validator.GenesisValidator, accSet.Len()) // add contracts to genesis data alloc := map[types.Address]*chain.GenesisAccount{ contracts.ValidatorSetContract: { - Code: contractsapi.ChildValidatorSet.DeployedBytecode, + Code: contractsapi.ValidatorSet.DeployedBytecode, + }, + contracts.RewardPoolContract: { + Code: contractsapi.RewardPool.DeployedBytecode, }, - contracts.BLSContract: { - Code: contractsapi.BLS.DeployedBytecode, + contracts.NativeERC20TokenContract: { + Code: contractsapi.NativeERC20.DeployedBytecode, + }, + walletAddress: { + Balance: new(big.Int).SetUint64(intialBalance), }, } - // validator data for polybft config - initValidators := make([]*Validator, accSet.Len()) - - for i, validator := range accSet { + for i, val := range accSet { // add validator to genesis data - alloc[validator.Address] = &chain.GenesisAccount{ - Balance: validator.VotingPower, + alloc[val.Address] = &chain.GenesisAccount{ + Balance: val.VotingPower, } - signature, err := secretsHelper.MakeKOSKSignature(accSetPrivateKeys[i].Bls, validator.Address, 0, bls.DomainValidatorSet) - require.NoError(t, err) - - signatureBytes, err := signature.Marshal() - require.NoError(t, err) - // create validator data for polybft config - initValidators[i] = &Validator{ - Address: validator.Address, - Balance: validator.VotingPower, - Stake: validator.VotingPower, - BlsKey: hex.EncodeToString(validator.BlsKey.Marshal()), - BlsSignature: hex.EncodeToString(signatureBytes), + initValidators[i] = &validator.GenesisValidator{ + Address: val.Address, + Balance: val.VotingPower, + Stake: val.VotingPower, + BlsKey: hex.EncodeToString(val.BlsKey.Marshal()), } - - // create delegators - delegatorAccs := createRandomTestKeys(t, delegatorsPerValidator) - - // add delegators to genesis data - for j := 0; j < delegatorsPerValidator; j++ { - delegator := delegatorAccs[j] - alloc[types.Address(delegator.Address())] = &chain.GenesisAccount{ - Balance: new(big.Int).SetUint64(intialBalance), - } - } - - valid2deleg[validator.Address] = delegatorAccs } - transition := newTestTransition(t, alloc) - polyBFTConfig := PolyBFTConfig{ InitialValidatorSet: initValidators, - BlockTime: 2 * time.Second, EpochSize: 24 * 60 * 60 / 2, SprintSize: 5, EpochReward: reward, // use 1st account as governance address - Governance: currentValidators.toValidatorSet().validators.GetAddresses()[0], + Governance: currentValidators.ToValidatorSet().Accounts().GetAddresses()[0], + RewardConfig: &RewardsConfig{ + TokenAddress: contracts.NativeERC20TokenContract, + WalletAddress: walletAddress, + WalletAmount: new(big.Int).SetUint64(intialBalance), + }, + Bridge: &BridgeConfig{ + CustomSupernetManagerAddr: types.StringToAddress("0x12312451"), + }, } - // get data for ChildValidatorSet initialization - initInput, err := getInitChildValidatorSetInput(polyBFTConfig) - require.NoError(t, err) + transition := newTestTransition(t, alloc) - // init ChildValidatorSet - err = initContract(contracts.ValidatorSetContract, initInput, "ChildValidatorSet", transition) + // init ValidatorSet + err := initValidatorSet(polyBFTConfig, transition) require.NoError(t, err) - // delegate amounts to validators - for valAddress, delegators := range valid2deleg { - for _, delegator := range delegators { - encoded, err := contractsapi.ChildValidatorSet.Abi.Methods["delegate"].Encode( - []interface{}{valAddress, false}) - require.NoError(t, err) + // init RewardPool + err = initRewardPool(polyBFTConfig, transition) + require.NoError(t, err) - result := transition.Call2(types.Address(delegator.Address()), contracts.ValidatorSetContract, encoded, new(big.Int).SetUint64(delegateAmount), 1000000000000) - require.False(t, result.Failed()) - } - } + // approve reward pool as reward token spender + err = approveRewardPoolAsSpender(polyBFTConfig, transition) + require.NoError(t, err) // create input for commit epoch - commitEpoch := createTestCommitEpochInput(t, 1, accSet, polyBFTConfig.EpochSize) + commitEpoch := createTestCommitEpochInput(t, 1, polyBFTConfig.EpochSize) input, err := commitEpoch.EncodeAbi() require.NoError(t, err) // call commit epoch result := transition.Call2(contracts.SystemCaller, contracts.ValidatorSetContract, input, big.NewInt(0), 10000000000) require.NoError(t, result.Err) - t.Logf("Number of validators %d when we add %d of delegators, Gas used %+v\n", accSet.Len(), accSet.Len()*delegatorsPerValidator, result.GasUsed) + t.Logf("Number of validators %d on commit epoch, Gas used %+v\n", accSet.Len(), result.GasUsed) + + // create input for distribute rewards + distributeRewards := createTestDistributeRewardsInput(t, 1, accSet, polyBFTConfig.EpochSize) + input, err = distributeRewards.EncodeAbi() + require.NoError(t, err) + + // call reward distributor + result = transition.Call2(contracts.SystemCaller, contracts.RewardPoolContract, input, big.NewInt(0), 10000000000) + require.NoError(t, result.Err) + t.Logf("Number of validators %d on reward distribution, Gas used %+v\n", accSet.Len(), result.GasUsed) - commitEpoch = createTestCommitEpochInput(t, 2, accSet, polyBFTConfig.EpochSize) + commitEpoch = createTestCommitEpochInput(t, 2, polyBFTConfig.EpochSize) input, err = commitEpoch.EncodeAbi() require.NoError(t, err) // call commit epoch result = transition.Call2(contracts.SystemCaller, contracts.ValidatorSetContract, input, big.NewInt(0), 10000000000) require.NoError(t, result.Err) - t.Logf("Number of validators %d, Number of delegator %d, Gas used %+v\n", accSet.Len(), accSet.Len()*delegatorsPerValidator, result.GasUsed) + t.Logf("Number of validators %d on commit epoch, Gas used %+v\n", accSet.Len(), result.GasUsed) + + distributeRewards = createTestDistributeRewardsInput(t, 2, accSet, polyBFTConfig.EpochSize) + input, err = distributeRewards.EncodeAbi() + require.NoError(t, err) + + // call reward distributor + result = transition.Call2(contracts.SystemCaller, contracts.RewardPoolContract, input, big.NewInt(0), 10000000000) + require.NoError(t, result.Err) + t.Logf("Number of validators %d on reward distribution, Gas used %+v\n", accSet.Len(), result.GasUsed) } } @@ -331,17 +391,16 @@ func deployAndInitContract(t *testing.T, transition *state.Transition, scArtifac initCallback func() ([]byte, error)) types.Address { t.Helper() - result := transition.Create2(sender, scArtifact.Bytecode, big.NewInt(0), 1e9) - assert.NoError(t, result.Err) - addr := result.Address + deployResult := transition.Create2(sender, scArtifact.Bytecode, big.NewInt(0), 1e9) + assert.NoError(t, deployResult.Err) if initCallback != nil { initInput, err := initCallback() require.NoError(t, err) - result = transition.Call2(sender, addr, initInput, big.NewInt(0), 1e9) + result := transition.Call2(sender, deployResult.Address, initInput, big.NewInt(0), 1e9) require.NoError(t, result.Err) } - return addr + return deployResult.Address } diff --git a/consensus/polybft/signer/common.go b/consensus/polybft/signer/common.go index 5ca4ea4c07..e39f26cbe6 100644 --- a/consensus/polybft/signer/common.go +++ b/consensus/polybft/signer/common.go @@ -12,6 +12,13 @@ import ( bn256 "github.com/umbracle/go-eth-bn256" ) +const ( + DomainValidatorSetString = "DOMAIN_CHILD_VALIDATOR_SET" + DomainCheckpointManagerString = "DOMAIN_CHECKPOINT_MANAGER" + DomainCommonSigningString = "DOMAIN_COMMON_SIGNING" + DomainStateReceiverString = "DOMAIN_STATE_RECEIVER" +) + var errInfinityPoint = fmt.Errorf("infinity point") var ( @@ -22,13 +29,13 @@ var ( g2Point = mustG2Point("198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa") //nolint // domain used to map hash to G1 used by (child) validator set - DomainValidatorSet = pcrypto.Keccak256([]byte("DOMAIN_CHILD_VALIDATOR_SET")) + DomainValidatorSet = pcrypto.Keccak256([]byte(DomainValidatorSetString)) // domain used to map hash to G1 used by child checkpoint manager - DomainCheckpointManager = pcrypto.Keccak256([]byte("DOMAIN_CHECKPOINT_MANAGER")) + DomainCheckpointManager = pcrypto.Keccak256([]byte(DomainCheckpointManagerString)) - DomainCommonSigning = pcrypto.Keccak256([]byte("DOMAIN_COMMON_SIGNING")) - DomainStateReceiver = pcrypto.Keccak256([]byte("DOMAIN_STATE_RECEIVER")) + DomainCommonSigning = pcrypto.Keccak256([]byte(DomainCommonSigningString)) + DomainStateReceiver = pcrypto.Keccak256([]byte(DomainStateReceiverString)) ) func mustG2Point(str string) *bn256.G2 { diff --git a/consensus/polybft/signer/utils.go b/consensus/polybft/signer/utils.go index b8d24f3ed6..0117714517 100644 --- a/consensus/polybft/signer/utils.go +++ b/consensus/polybft/signer/utils.go @@ -1,8 +1,17 @@ package bls import ( + "bytes" "crypto/rand" "math/big" + + "github.com/0xPolygon/polygon-edge/types" + "github.com/umbracle/ethgo/abi" +) + +var ( + addressABIType = abi.MustNewType("address") + uint256ABIType = abi.MustNewType("uint256") ) // GenerateBlsKey creates a random private and its corresponding public keys @@ -46,3 +55,28 @@ func MarshalMessageToBigInt(message, domain []byte) ([2]*big.Int, error) { new(big.Int).SetBytes(buf[32:64]), }, nil } + +// MakeKOSKSignature creates KOSK signature which prevents rogue attack +func MakeKOSKSignature(privateKey *PrivateKey, address types.Address, + chainID int64, domain []byte, supernetManagerAddr types.Address) (*Signature, error) { + spenderABI, err := addressABIType.Encode(address) + if err != nil { + return nil, err + } + + supernetManagerABI, err := addressABIType.Encode(supernetManagerAddr) + if err != nil { + return nil, err + } + + chainIDABI, err := uint256ABIType.Encode(big.NewInt(chainID)) + if err != nil { + return nil, err + } + + // ethgo pads address to 32 bytes, but solidity doesn't (keeps it 20 bytes) + // that's why we are skipping first 12 bytes + message := bytes.Join([][]byte{spenderABI[12:], supernetManagerABI[12:], chainIDABI}, nil) + + return privateKey.Sign(message, domain) +} diff --git a/consensus/polybft/signer/utils_test.go b/consensus/polybft/signer/utils_test.go index 5cb95107d4..56646de1ea 100644 --- a/consensus/polybft/signer/utils_test.go +++ b/consensus/polybft/signer/utils_test.go @@ -1,8 +1,10 @@ package bls import ( + "encoding/hex" "testing" + "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -66,3 +68,32 @@ func Test_AggregatedSign(t *testing.T) { assert.False(t, isOk) } } + +func Test_MakeKOSKSignature(t *testing.T) { + t.Parallel() + + expected := "03441ebc4bbca37664455b293cfc371ccf9a4f21e40c19a3a25beee77bf6e97d16cdd264c188a01d415ee99865f52567a402044a1c13aa6915a1237a41d35e9e" + bytes, _ := hex.DecodeString("3139343634393730313533353434353137333331343333303931343932303731313035313730303336303738373134363131303435323837383335373237343933383834303135343336383231") + + pk, err := UnmarshalPrivateKey(bytes) + require.NoError(t, err) + + supernetManagerAddr := types.StringToAddress("0x1010101") + address := types.BytesToAddress((pk.PublicKey().Marshal())[:types.AddressLength]) + + signature, err := MakeKOSKSignature(pk, address, 10, DomainValidatorSet, supernetManagerAddr) + require.NoError(t, err) + + signatureBytes, err := signature.Marshal() + require.NoError(t, err) + + assert.Equal(t, expected, hex.EncodeToString(signatureBytes)) + + signature, err = MakeKOSKSignature(pk, address, 100, DomainValidatorSet, supernetManagerAddr) + require.NoError(t, err) + + signatureBytes, err = signature.Marshal() + require.NoError(t, err) + + assert.NotEqual(t, expected, hex.EncodeToString(signatureBytes)) +} diff --git a/consensus/polybft/stake_manager.go b/consensus/polybft/stake_manager.go new file mode 100644 index 0000000000..e140ca6eee --- /dev/null +++ b/consensus/polybft/stake_manager.go @@ -0,0 +1,437 @@ +package polybft + +import ( + "bytes" + "encoding/json" + "fmt" + "math/big" + "sort" + "strings" + + "github.com/0xPolygon/polygon-edge/blockchain" + "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" + "github.com/hashicorp/go-hclog" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/abi" +) + +var ( + bigZero = big.NewInt(0) + validatorTypeABI = abi.MustNewType("tuple(uint256[4] blsKey, uint256 stake, bool isWhitelisted, bool isActive)") +) + +// StakeManager interface provides functions for handling stake change of validators +// and updating validator set based on changed stake +type StakeManager interface { + PostBlock(req *PostBlockRequest) error + PostEpoch(req *PostEpochRequest) error + UpdateValidatorSet(epoch uint64, currentValidatorSet validator.AccountSet) (*validator.ValidatorSetDelta, error) +} + +// dummyStakeManager is a dummy implementation of StakeManager interface +// used only for unit testing +type dummyStakeManager struct{} + +func (d *dummyStakeManager) PostBlock(req *PostBlockRequest) error { return nil } +func (d *dummyStakeManager) PostEpoch(req *PostEpochRequest) error { return nil } +func (d *dummyStakeManager) UpdateValidatorSet(epoch uint64, + currentValidatorSet validator.AccountSet) (*validator.ValidatorSetDelta, error) { + return &validator.ValidatorSetDelta{}, nil +} + +var _ StakeManager = (*stakeManager)(nil) + +// stakeManager saves transfer events that happened in each block +// and calculates updated validator set based on changed stake +type stakeManager struct { + logger hclog.Logger + state *State + rootChainRelayer txrelayer.TxRelayer + key ethgo.Key + validatorSetContract types.Address + supernetManagerContract types.Address + maxValidatorSetSize int + blockchain blockchainBackend +} + +// newStakeManager returns a new instance of stake manager +func newStakeManager( + logger hclog.Logger, + state *State, + rootchainRelayer txrelayer.TxRelayer, + key ethgo.Key, + validatorSetAddr, supernetManagerAddr types.Address, + blockchain blockchainBackend, + maxValidatorSetSize int, +) *stakeManager { + return &stakeManager{ + logger: logger, + state: state, + rootChainRelayer: rootchainRelayer, + key: key, + validatorSetContract: validatorSetAddr, + supernetManagerContract: supernetManagerAddr, + maxValidatorSetSize: maxValidatorSetSize, + blockchain: blockchain, + } +} + +// PostEpoch saves the initial validator set to db +func (s *stakeManager) PostEpoch(req *PostEpochRequest) error { + if req.NewEpochID != 1 { + return nil + } + + // save initial validator set as full validator set in db + return s.state.StakeStore.insertFullValidatorSet(validatorSetState{ + BlockNumber: 0, + EpochID: 0, + UpdatedAtBlockNumber: 0, + Validators: newValidatorStakeMap(req.ValidatorSet.Accounts()), + }) +} + +// PostBlock is called on every insert of finalized block (either from consensus or syncer) +// It will read any transfer event that happened in block and update full validator set in db +func (s *stakeManager) PostBlock(req *PostBlockRequest) error { + fullValidatorSet, err := s.state.StakeStore.getFullValidatorSet() + if err != nil { + return err + } + + s.logger.Debug("Stake manager on post block", "block", req.FullBlock.Block.Number(), + "last saved", fullValidatorSet.BlockNumber, "last updated", fullValidatorSet.UpdatedAtBlockNumber) + + // update with missing blocks + for i := fullValidatorSet.BlockNumber + 1; i < req.FullBlock.Block.Number(); i++ { + blockHeader, found := s.blockchain.GetHeaderByNumber(i) + if !found { + return blockchain.ErrNoBlock + } + + receipts, err := s.blockchain.GetReceiptsByHash(blockHeader.Hash) + if err != nil { + return err + } + + if err := s.updateWithReceipts(&fullValidatorSet, receipts, i); err != nil { + return err + } + } + + // finally update with received block + err = s.updateWithReceipts(&fullValidatorSet, req.FullBlock.Receipts, req.FullBlock.Block.Number()) + if err != nil { + return err + } + + fullValidatorSet.EpochID = req.Epoch + fullValidatorSet.BlockNumber = req.FullBlock.Block.Number() + + return s.state.StakeStore.insertFullValidatorSet(fullValidatorSet) +} + +func (s *stakeManager) updateWithReceipts( + fullValidatorSet *validatorSetState, receipts []*types.Receipt, block uint64) error { + events, err := s.getTransferEventsFromReceipts(receipts) + if err != nil { + return err + } + + s.logger.Debug("Full validator set before", + "block", block-1, "evnts", len(events), "data", fullValidatorSet.Validators) + + if len(events) == 0 { + return nil + } + + for _, event := range events { + if event.IsStake() { + s.logger.Debug("Stake transfer event", "to", event.To, "value", event.Value) + + // then this amount was minted To validator address + fullValidatorSet.Validators.addStake(event.To, event.Value) + } else if event.IsUnstake() { + s.logger.Debug("Unstake transfer event", "from", event.From, "value", event.Value) + + // then this amount was burned From validator address + fullValidatorSet.Validators.removeStake(event.From, event.Value) + } else { + // this should not happen, but lets log it if it does + s.logger.Warn("Found a transfer event that represents neither stake nor unstake") + } + } + + for addr, data := range fullValidatorSet.Validators { + if data.BlsKey == nil { + data.BlsKey, err = s.getBlsKey(data.Address) + if err != nil { + s.logger.Warn("Could not get info for new validator", "block", block, "address", addr) + } + } + + data.IsActive = data.VotingPower.Cmp(bigZero) > 0 + } + + fullValidatorSet.UpdatedAtBlockNumber = block // mark on which block validator set has been updated + + s.logger.Debug("Full validator set after", "block", block, "data", fullValidatorSet.Validators) + + return nil +} + +// UpdateValidatorSet returns an updated validator set +// based on stake change (transfer) events from ValidatorSet contract +func (s *stakeManager) UpdateValidatorSet( + epoch uint64, oldValidatorSet validator.AccountSet) (*validator.ValidatorSetDelta, error) { + s.logger.Info("Calculating validators set update...", "epoch", epoch) + + fullValidatorSet, err := s.state.StakeStore.getFullValidatorSet() + if err != nil { + return nil, fmt.Errorf("failed to get full validators set. Epoch: %d. Error: %w", epoch, err) + } + + // stake map that holds stakes for all validators + stakeMap := fullValidatorSet.Validators + + // slice of all validator set + newValidatorSet := stakeMap.getSorted(s.maxValidatorSetSize) + // set of all addresses that will be in next validator set + addressesSet := make(map[types.Address]struct{}, len(newValidatorSet)) + + for _, si := range newValidatorSet { + addressesSet[si.Address] = struct{}{} + } + + removedBitmap := bitmap.Bitmap{} + updatedValidators := validator.AccountSet{} + addedValidators := validator.AccountSet{} + oldActiveMap := make(map[types.Address]*validator.ValidatorMetadata) + + for i, validator := range oldValidatorSet { + oldActiveMap[validator.Address] = validator + // remove existing validators from validator set if they did not make it to the set + if _, exists := addressesSet[validator.Address]; !exists { + removedBitmap.Set(uint64(i)) + } + } + + for _, newValidator := range newValidatorSet { + // check if its already in existing validator set + if oldValidator, exists := oldActiveMap[newValidator.Address]; exists { + if oldValidator.VotingPower.Cmp(newValidator.VotingPower) != 0 { + updatedValidators = append(updatedValidators, newValidator) + } + } else { + if newValidator.BlsKey == nil { + newValidator.BlsKey, err = s.getBlsKey(newValidator.Address) + if err != nil { + return nil, fmt.Errorf("could not retrieve validator data. Address: %v. Error: %w", + newValidator.Address, err) + } + } + + addedValidators = append(addedValidators, newValidator) + } + } + + s.logger.Info("Calculating validators set update finished.", "epoch", epoch) + + delta := &validator.ValidatorSetDelta{ + Added: addedValidators, + Updated: updatedValidators, + Removed: removedBitmap, + } + + if s.logger.IsDebug() { + newValidatorSet, err := oldValidatorSet.Copy().ApplyDelta(delta) + if err != nil { + return nil, err + } + + s.logger.Debug("New validator set", "validatorSet", newValidatorSet) + } + + return delta, nil +} + +// getTransferEventsFromReceipts parses logs from receipts to find transfer events +func (s *stakeManager) getTransferEventsFromReceipts(receipts []*types.Receipt) ([]*contractsapi.TransferEvent, error) { + events := make([]*contractsapi.TransferEvent, 0) + + for i := 0; i < len(receipts); i++ { + if receipts[i].Status == nil || *receipts[i].Status != types.ReceiptSuccess { + continue + } + + for _, log := range receipts[i].Logs { + if log.Address != s.validatorSetContract { + continue + } + + var transferEvent contractsapi.TransferEvent + + doesMatch, err := transferEvent.ParseLog(convertLog(log)) + if err != nil { + return nil, err + } + + if !doesMatch { + continue + } + + events = append(events, &transferEvent) + } + } + + return events, nil +} + +// getBlsKey returns bls key for validator from the supernet contract +func (s *stakeManager) getBlsKey(address types.Address) (*bls.PublicKey, error) { + getValidatorFn := &contractsapi.GetValidatorCustomSupernetManagerFn{ + Validator_: address, + } + + encoded, err := getValidatorFn.EncodeAbi() + if err != nil { + return nil, err + } + + response, err := s.rootChainRelayer.Call( + s.key.Address(), + ethgo.Address(s.supernetManagerContract), + encoded) + if err != nil { + return nil, fmt.Errorf("failed to invoke validators function on the supernet manager: %w", err) + } + + byteResponse, err := hex.DecodeHex(response) + if err != nil { + return nil, fmt.Errorf("unable to decode hex response, %w", err) + } + + decoded, err := validatorTypeABI.Decode(byteResponse) + if err != nil { + return nil, err + } + + output, ok := decoded.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("could not convert decoded outputs to map") + } + + blsKey, ok := output["blsKey"].([4]*big.Int) + if !ok { + return nil, fmt.Errorf("failed to decode blskey") + } + + pubKey, err := bls.UnmarshalPublicKeyFromBigInt(blsKey) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal BLS public key: %w", err) + } + + return pubKey, nil +} + +type validatorSetState struct { + BlockNumber uint64 `json:"block"` + EpochID uint64 `json:"epoch"` + UpdatedAtBlockNumber uint64 `json:"updated_at_block"` + Validators validatorStakeMap `json:"validators"` +} + +func (vs validatorSetState) Marshal() ([]byte, error) { + return json.Marshal(vs) +} + +func (vs *validatorSetState) Unmarshal(b []byte) error { + return json.Unmarshal(b, vs) +} + +// validatorStakeMap holds ValidatorMetadata for each validator address +type validatorStakeMap map[types.Address]*validator.ValidatorMetadata + +// newValidatorStakeMap returns a new instance of validatorStakeMap +func newValidatorStakeMap(validatorSet validator.AccountSet) validatorStakeMap { + stakeMap := make(validatorStakeMap, len(validatorSet)) + + for _, v := range validatorSet { + stakeMap[v.Address] = v.Copy() + } + + return stakeMap +} + +// addStake adds given amount to a validator defined by address +func (sc *validatorStakeMap) addStake(address types.Address, amount *big.Int) { + if metadata, exists := (*sc)[address]; exists { + metadata.VotingPower.Add(metadata.VotingPower, amount) + metadata.IsActive = metadata.VotingPower.Cmp(bigZero) > 0 + } else { + (*sc)[address] = &validator.ValidatorMetadata{ + VotingPower: new(big.Int).Set(amount), + Address: address, + IsActive: amount.Cmp(bigZero) > 0, + } + } +} + +// removeStake removes given amount from validator defined by address +func (sc *validatorStakeMap) removeStake(address types.Address, amount *big.Int) { + stakeData := (*sc)[address] + stakeData.VotingPower.Sub(stakeData.VotingPower, amount) + stakeData.IsActive = stakeData.VotingPower.Cmp(bigZero) > 0 +} + +// getSorted returns validators (*ValidatorMetadata) in sorted order +func (sc validatorStakeMap) getSorted(maxValidatorSetSize int) validator.AccountSet { + activeValidators := make(validator.AccountSet, 0, len(sc)) + + for _, v := range sc { + if v.VotingPower.Cmp(bigZero) > 0 { + activeValidators = append(activeValidators, v) + } + } + + sort.Slice(activeValidators, func(i, j int) bool { + v1, v2 := activeValidators[i], activeValidators[j] + + switch v1.VotingPower.Cmp(v2.VotingPower) { + case 1: + return true + case 0: + return bytes.Compare(v1.Address[:], v2.Address[:]) < 0 + default: + return false + } + }) + + if len(activeValidators) <= maxValidatorSetSize { + return activeValidators + } + + return activeValidators[:maxValidatorSetSize] +} + +func (sc validatorStakeMap) String() string { + var sb strings.Builder + + for _, x := range sc.getSorted(len(sc)) { + bls := "" + if x.BlsKey != nil { + bls = hex.EncodeToString(x.BlsKey.Marshal()) + } + + sb.WriteString(fmt.Sprintf("%s:%s:%s:%t\n", + x.Address, x.VotingPower, bls, x.IsActive)) + } + + return sb.String() +} diff --git a/consensus/polybft/stake_manager_fuzz_test.go b/consensus/polybft/stake_manager_fuzz_test.go new file mode 100644 index 0000000000..9f49f0f2e3 --- /dev/null +++ b/consensus/polybft/stake_manager_fuzz_test.go @@ -0,0 +1,286 @@ +package polybft + +import ( + "encoding/json" + "errors" + "fmt" + "math/big" + "reflect" + "testing" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" + "github.com/0xPolygon/polygon-edge/types" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/require" +) + +type epochIDValidatorsF struct { + EpochID uint64 + Validators []*validator.ValidatorMetadata +} + +type postBlockStructF struct { + EpochID uint64 + ValidatorID uint64 + BlockID uint64 + StakeValue uint64 +} + +type updateValidatorSetF struct { + EpochID uint64 + Index uint64 + VotingPower int64 +} + +func FuzzTestStakeManagerPostEpoch(f *testing.F) { + state := newTestState(f) + + seeds := []epochIDValidatorsF{ + { + EpochID: 0, + Validators: validator.NewTestValidators(f, 6).GetPublicIdentities(), + }, + { + EpochID: 1, + Validators: validator.NewTestValidators(f, 42).GetPublicIdentities(), + }, + { + EpochID: 42, + Validators: validator.NewTestValidators(f, 6).GetPublicIdentities(), + }, + } + + for _, seed := range seeds { + data, err := json.Marshal(seed) + if err != nil { + return + } + + f.Add(data) + } + + f.Fuzz(func(t *testing.T, input []byte) { + stakeManager := &stakeManager{ + logger: hclog.NewNullLogger(), + state: state, + maxValidatorSetSize: 10, + } + + var data epochIDValidatorsF + if err := json.Unmarshal(input, &data); err != nil { + t.Skip(err) + } + + invalidDataFormat := false + for _, v := range data.Validators { + if err := ValidateStruct(*v); err != nil { + invalidDataFormat = true + } + } + if invalidDataFormat { + t.Skip() + } + + err := stakeManager.PostEpoch(&PostEpochRequest{ + NewEpochID: data.EpochID, + ValidatorSet: validator.NewValidatorSet( + data.Validators, + stakeManager.logger, + ), + }) + require.NoError(t, err) + }) +} + +func FuzzTestStakeManagerPostBlock(f *testing.F) { + var ( + allAliases = []string{"A", "B", "C", "D", "E", "F"} + initialSetAliases = []string{"A", "B", "C", "D", "E"} + validators = validator.NewTestValidatorsWithAliases(f, allAliases) + state = newTestState(f) + ) + + seeds := []postBlockStructF{ + { + EpochID: 0, + ValidatorID: 1, + BlockID: 1, + StakeValue: 30, + }, + { + EpochID: 5, + ValidatorID: 30, + BlockID: 4, + StakeValue: 60, + }, + { + EpochID: 1, + ValidatorID: 42, + BlockID: 11, + StakeValue: 70, + }, + } + + for _, seed := range seeds { + data, err := json.Marshal(seed) + if err != nil { + return + } + + f.Add(data) + } + + f.Fuzz(func(t *testing.T, input []byte) { + t.Parallel() + + var data postBlockStructF + if err := json.Unmarshal(input, &data); err != nil { + t.Skip(err) + } + + if err := ValidateStruct(data); err != nil { + t.Skip(err) + } + + if data.ValidatorID > uint64(len(initialSetAliases)-1) { + t.Skip() + } + + stakeManager := newStakeManager( + hclog.NewNullLogger(), + state, + nil, + wallet.NewEcdsaSigner(validators.GetValidator("A").Key()), + types.StringToAddress("0x0001"), + types.StringToAddress("0x0002"), + nil, + 5, + ) + + // insert initial full validator set + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(validators.GetPublicIdentities(initialSetAliases...)), + })) + + receipt := &types.Receipt{ + Logs: []*types.Log{ + createTestLogForTransferEvent( + t, + stakeManager.validatorSetContract, + validators.GetValidator(initialSetAliases[data.ValidatorID]).Address(), + types.ZeroAddress, + data.StakeValue, + ), + }, + } + + req := &PostBlockRequest{ + FullBlock: &types.FullBlock{Block: &types.Block{Header: &types.Header{Number: data.BlockID}}, + Receipts: []*types.Receipt{receipt}, + }, + Epoch: data.EpochID, + } + err := stakeManager.PostBlock(req) + require.NoError(t, err) + }) +} + +func FuzzTestStakeManagerUpdateValidatorSet(f *testing.F) { + var ( + aliases = []string{"A", "B", "C", "D", "E"} + stakes = []uint64{10, 10, 10, 10, 10} + ) + + validators := validator.NewTestValidatorsWithAliases(f, aliases, stakes) + state := newTestState(f) + + stakeManager := newStakeManager( + hclog.NewNullLogger(), + state, + nil, + wallet.NewEcdsaSigner(validators.GetValidator("A").Key()), + types.StringToAddress("0x0001"), types.StringToAddress("0x0002"), + nil, + 10, + ) + + seeds := []updateValidatorSetF{ + { + EpochID: 0, + Index: 1, + VotingPower: 30, + }, + { + EpochID: 1, + Index: 4, + VotingPower: 1, + }, + { + EpochID: 2, + Index: 3, + VotingPower: -2, + }, + } + + for _, seed := range seeds { + data, err := json.Marshal(seed) + if err != nil { + return + } + + f.Add(data) + } + + f.Fuzz(func(t *testing.T, input []byte) { + var data updateValidatorSetF + if err := json.Unmarshal(input, &data); err != nil { + t.Skip(err) + } + + if err := ValidateStruct(data); err != nil { + t.Skip(err) + } + + if data.Index > uint64(len(aliases)-1) { + t.Skip() + } + + err := state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(validators.GetPublicIdentities())}) + require.NoError(t, err) + + _, err = stakeManager.UpdateValidatorSet(data.EpochID, validators.GetPublicIdentities(aliases[data.Index:]...)) + require.NoError(t, err) + + fullValidatorSet := validators.GetPublicIdentities().Copy() + validatorToUpdate := fullValidatorSet[data.Index] + validatorToUpdate.VotingPower = big.NewInt(data.VotingPower) + + _, err = stakeManager.UpdateValidatorSet(data.EpochID, validators.GetPublicIdentities()) + require.NoError(t, err) + }) +} + +func ValidateStruct(s interface{}) (err error) { + structType := reflect.TypeOf(s) + if structType.Kind() != reflect.Struct { + return errors.New("input param should be a struct") + } + + structVal := reflect.ValueOf(s) + fieldNum := structVal.NumField() + + for i := 0; i < fieldNum; i++ { + field := structVal.Field(i) + fieldName := structType.Field(i).Name + + isSet := field.IsValid() && !field.IsZero() + + if !isSet { + err = fmt.Errorf("%w%s is not set; ", err, fieldName) + } + } + + return err +} diff --git a/consensus/polybft/stake_manager_test.go b/consensus/polybft/stake_manager_test.go new file mode 100644 index 0000000000..5546216450 --- /dev/null +++ b/consensus/polybft/stake_manager_test.go @@ -0,0 +1,559 @@ +package polybft + +import ( + "math/big" + "testing" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" + "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/abi" + "github.com/umbracle/ethgo/jsonrpc" +) + +func TestStakeManager_PostEpoch(t *testing.T) { + validators := validator.NewTestValidators(t, 5).GetPublicIdentities() + state := newTestState(t) + + stakeManager := &stakeManager{ + logger: hclog.NewNullLogger(), + state: state, + maxValidatorSetSize: 10, + } + + t.Run("Not first epoch", func(t *testing.T) { + require.NoError(t, stakeManager.PostEpoch(&PostEpochRequest{ + NewEpochID: 2, + ValidatorSet: validator.NewValidatorSet(validators, stakeManager.logger), + })) + + _, err := state.StakeStore.getFullValidatorSet() + require.ErrorIs(t, errNoFullValidatorSet, err) + }) + + t.Run("First epoch", func(t *testing.T) { + require.NoError(t, stakeManager.PostEpoch(&PostEpochRequest{ + NewEpochID: 1, + ValidatorSet: validator.NewValidatorSet(validators, stakeManager.logger), + })) + + fullValidatorSet, err := state.StakeStore.getFullValidatorSet() + require.NoError(t, err) + require.Len(t, fullValidatorSet.Validators, len(validators)) + require.Equal(t, uint64(0), fullValidatorSet.EpochID) + require.Equal(t, uint64(0), fullValidatorSet.BlockNumber) + }) +} + +func TestStakeManager_PostBlock(t *testing.T) { + t.Parallel() + + var ( + allAliases = []string{"A", "B", "C", "D", "E", "F"} + initialSetAliases = []string{"A", "B", "C", "D", "E"} + epoch = uint64(1) + block = uint64(10) + newStake = uint64(100) + firstValidator = uint64(0) + secondValidator = uint64(1) + ) + + state := newTestState(t) + t.Run("PostBlock - unstake to zero", func(t *testing.T) { + t.Parallel() + + validators := validator.NewTestValidatorsWithAliases(t, allAliases) + stakeManager := newStakeManager( + hclog.NewNullLogger(), + state, + nil, + wallet.NewEcdsaSigner(validators.GetValidator("A").Key()), + types.StringToAddress("0x0001"), types.StringToAddress("0x0002"), + nil, + 5, + ) + + // insert initial full validator set + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(validators.GetPublicIdentities(initialSetAliases...)), + BlockNumber: block - 1, + })) + + receipt := &types.Receipt{ + Logs: []*types.Log{ + createTestLogForTransferEvent( + t, + stakeManager.validatorSetContract, + validators.GetValidator(initialSetAliases[firstValidator]).Address(), + types.ZeroAddress, + 1, // initial validator stake was 1 + ), + }, + } + + receipt.SetStatus(types.ReceiptSuccess) + + req := &PostBlockRequest{ + FullBlock: &types.FullBlock{Block: &types.Block{Header: &types.Header{Number: block}}, + Receipts: []*types.Receipt{receipt}, + }, + Epoch: epoch, + } + + require.NoError(t, stakeManager.PostBlock(req)) + + fullValidatorSet, err := state.StakeStore.getFullValidatorSet() + require.NoError(t, err) + var firstValidatorMeta *validator.ValidatorMetadata + firstValidatorMeta = nil + for _, validator := range fullValidatorSet.Validators { + if validator.Address.String() == validators.GetValidator(initialSetAliases[firstValidator]).Address().String() { + firstValidatorMeta = validator + } + } + require.NotNil(t, firstValidatorMeta) + require.Equal(t, bigZero, firstValidatorMeta.VotingPower) + require.False(t, firstValidatorMeta.IsActive) + }) + t.Run("PostBlock - add stake to one validator", func(t *testing.T) { + t.Parallel() + + validators := validator.NewTestValidatorsWithAliases(t, allAliases) + stakeManager := newStakeManager( + hclog.NewNullLogger(), + state, + nil, + wallet.NewEcdsaSigner(validators.GetValidator("A").Key()), + types.StringToAddress("0x0001"), types.StringToAddress("0x0002"), + nil, + 5, + ) + + // insert initial full validator set + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(validators.GetPublicIdentities(initialSetAliases...)), + BlockNumber: block - 1, + })) + + receipt := &types.Receipt{ + Logs: []*types.Log{ + createTestLogForTransferEvent( + t, + stakeManager.validatorSetContract, + types.ZeroAddress, + validators.GetValidator(initialSetAliases[secondValidator]).Address(), + 250, + ), + }, + } + + receipt.SetStatus(types.ReceiptSuccess) + + req := &PostBlockRequest{ + FullBlock: &types.FullBlock{Block: &types.Block{Header: &types.Header{Number: block}}, + Receipts: []*types.Receipt{receipt}, + }, + Epoch: epoch, + } + + require.NoError(t, stakeManager.PostBlock(req)) + + fullValidatorSet, err := state.StakeStore.getFullValidatorSet() + require.NoError(t, err) + var firstValidaotor *validator.ValidatorMetadata + firstValidaotor = nil + for _, validator := range fullValidatorSet.Validators { + if validator.Address.String() == validators.GetValidator(initialSetAliases[secondValidator]).Address().String() { + firstValidaotor = validator + } + } + require.NotNil(t, firstValidaotor) + require.Equal(t, big.NewInt(251), firstValidaotor.VotingPower) // 250 + initial 1 + require.True(t, firstValidaotor.IsActive) + }) + + t.Run("PostBlock - add validator and stake", func(t *testing.T) { + t.Parallel() + + validators := validator.NewTestValidatorsWithAliases(t, allAliases, []uint64{1, 2, 3, 4, 5, 6}) + + txRelayerMock := newDummyStakeTxRelayer(t, func() *validator.ValidatorMetadata { + return validators.GetValidator("F").ValidatorMetadata() + }) + + // just mock the call however, the dummy relayer should do its magic + txRelayerMock.On("Call", mock.Anything, mock.Anything, mock.Anything). + Return(nil, error(nil)) + + stakeManager := newStakeManager( + hclog.NewNullLogger(), + state, + txRelayerMock, + wallet.NewEcdsaSigner(validators.GetValidator("A").Key()), + types.StringToAddress("0x0001"), types.StringToAddress("0x0002"), + nil, + 5, + ) + + // insert initial full validator set + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(validators.GetPublicIdentities(initialSetAliases...)), + BlockNumber: block - 1, + })) + + receipts := make([]*types.Receipt, len(allAliases)) + for i := 0; i < len(allAliases); i++ { + receipts[i] = &types.Receipt{Logs: []*types.Log{ + createTestLogForTransferEvent( + t, + stakeManager.validatorSetContract, + types.ZeroAddress, + validators.GetValidator(allAliases[i]).Address(), + newStake, + ), + }} + receipts[i].SetStatus(types.ReceiptSuccess) + } + + req := &PostBlockRequest{ + FullBlock: &types.FullBlock{Block: &types.Block{Header: &types.Header{Number: block}}, + Receipts: receipts}, + Epoch: epoch, + } + + require.NoError(t, stakeManager.PostBlock(req)) + + fullValidatorSet, err := state.StakeStore.getFullValidatorSet() + require.NoError(t, err) + require.Len(t, fullValidatorSet.Validators, len(allAliases)) + + validatorsCount := validators.ToValidatorSet().Len() + for i, v := range fullValidatorSet.Validators.getSorted(validatorsCount) { + require.Equal(t, newStake+uint64(validatorsCount)-uint64(i)-1, v.VotingPower.Uint64()) + } + }) + + t.Run("PostBlock - add stake to one validator + missing block", func(t *testing.T) { + t.Parallel() + + receipt := &types.Receipt{} + header1, header2 := &types.Header{Hash: types.Hash{3, 2}}, &types.Header{Hash: types.Hash{6, 4}} + + bcMock := new(blockchainMock) + bcMock.On("GetHeaderByNumber", block-2).Return(header1, true).Once() + bcMock.On("GetHeaderByNumber", block-1).Return(header2, true).Once() + bcMock.On("GetReceiptsByHash", header1.Hash).Return([]*types.Receipt{receipt}, error(nil)).Once() + bcMock.On("GetReceiptsByHash", header2.Hash).Return([]*types.Receipt{}, error(nil)).Once() + + validators := validator.NewTestValidatorsWithAliases(t, allAliases) + stakeManager := newStakeManager( + hclog.NewNullLogger(), + state, + nil, + wallet.NewEcdsaSigner(validators.GetValidator("A").Key()), + types.StringToAddress("0x0001"), types.StringToAddress("0x0002"), + bcMock, + 5, + ) + + // insert initial full validator set + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(validators.GetPublicIdentities(initialSetAliases...)), + BlockNumber: block - 3, + })) + + receipt.Logs = []*types.Log{ + createTestLogForTransferEvent( + t, + stakeManager.validatorSetContract, + types.ZeroAddress, + validators.GetValidator(initialSetAliases[secondValidator]).Address(), + 250, + ), + } + receipt.SetStatus(types.ReceiptSuccess) + + req := &PostBlockRequest{ + FullBlock: &types.FullBlock{Block: &types.Block{Header: &types.Header{Number: block}}, + Receipts: []*types.Receipt{receipt}, + }, + Epoch: epoch, + } + + require.NoError(t, stakeManager.PostBlock(req)) + + fullValidatorSet, err := state.StakeStore.getFullValidatorSet() + require.NoError(t, err) + var firstValidaotor *validator.ValidatorMetadata + firstValidaotor = nil + for _, validator := range fullValidatorSet.Validators { + if validator.Address.String() == validators.GetValidator(initialSetAliases[secondValidator]).Address().String() { + firstValidaotor = validator + } + } + require.NotNil(t, firstValidaotor) + require.Equal(t, big.NewInt(501), firstValidaotor.VotingPower) // 250 + 250 + initial 1 + require.True(t, firstValidaotor.IsActive) + + bcMock.AssertExpectations(t) + }) +} + +func TestStakeManager_UpdateValidatorSet(t *testing.T) { + var ( + aliases = []string{"A", "B", "C", "D", "E"} + stakes = []uint64{10, 10, 10, 10, 10} + epoch = uint64(1) + ) + + validators := validator.NewTestValidatorsWithAliases(t, aliases, stakes) + state := newTestState(t) + + stakeManager := newStakeManager( + hclog.NewNullLogger(), + state, + nil, + wallet.NewEcdsaSigner(validators.GetValidator("A").Key()), + types.StringToAddress("0x0001"), types.StringToAddress("0x0002"), + nil, + 10, + ) + + t.Run("UpdateValidatorSet - only update", func(t *testing.T) { + fullValidatorSet := validators.GetPublicIdentities().Copy() + validatorToUpdate := fullValidatorSet[0] + validatorToUpdate.VotingPower = big.NewInt(11) + + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(fullValidatorSet), + })) + + updateDelta, err := stakeManager.UpdateValidatorSet(epoch, validators.GetPublicIdentities()) + require.NoError(t, err) + require.Len(t, updateDelta.Added, 0) + require.Len(t, updateDelta.Updated, 1) + require.Len(t, updateDelta.Removed, 0) + require.Equal(t, updateDelta.Updated[0].Address, validatorToUpdate.Address) + require.Equal(t, updateDelta.Updated[0].VotingPower.Uint64(), validatorToUpdate.VotingPower.Uint64()) + }) + + t.Run("UpdateValidatorSet - one unstake", func(t *testing.T) { + fullValidatorSet := validators.GetPublicIdentities(aliases[1:]...) + + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(fullValidatorSet), + })) + + updateDelta, err := stakeManager.UpdateValidatorSet(epoch+1, validators.GetPublicIdentities()) + require.NoError(t, err) + require.Len(t, updateDelta.Added, 0) + require.Len(t, updateDelta.Updated, 0) + require.Len(t, updateDelta.Removed, 1) + }) + + t.Run("UpdateValidatorSet - one new validator", func(t *testing.T) { + addedValidator := validators.GetValidator("A") + + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(validators.GetPublicIdentities()), + })) + + updateDelta, err := stakeManager.UpdateValidatorSet(epoch+2, + validators.GetPublicIdentities(aliases[1:]...)) + require.NoError(t, err) + require.Len(t, updateDelta.Added, 1) + require.Len(t, updateDelta.Updated, 0) + require.Len(t, updateDelta.Removed, 0) + require.Equal(t, addedValidator.Address(), updateDelta.Added[0].Address) + require.Equal(t, addedValidator.VotingPower, updateDelta.Added[0].VotingPower.Uint64()) + }) + t.Run("UpdateValidatorSet - remove some stake", func(t *testing.T) { + fullValidatorSet := validators.GetPublicIdentities().Copy() + validatorToUpdate := fullValidatorSet[2] + validatorToUpdate.VotingPower = big.NewInt(5) + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(fullValidatorSet), + })) + + updateDelta, err := stakeManager.UpdateValidatorSet(epoch+3, validators.GetPublicIdentities()) + require.NoError(t, err) + require.Len(t, updateDelta.Added, 0) + require.Len(t, updateDelta.Updated, 1) + require.Len(t, updateDelta.Removed, 0) + require.Equal(t, updateDelta.Updated[0].Address, validatorToUpdate.Address) + require.Equal(t, updateDelta.Updated[0].VotingPower.Uint64(), validatorToUpdate.VotingPower.Uint64()) + }) + t.Run("UpdateValidatorSet - remove entire stake", func(t *testing.T) { + fullValidatorSet := validators.GetPublicIdentities().Copy() + validatorToUpdate := fullValidatorSet[3] + validatorToUpdate.VotingPower = bigZero + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(fullValidatorSet), + })) + + updateDelta, err := stakeManager.UpdateValidatorSet(epoch+4, validators.GetPublicIdentities()) + require.NoError(t, err) + require.Len(t, updateDelta.Added, 0) + require.Len(t, updateDelta.Updated, 0) + require.Len(t, updateDelta.Removed, 1) + }) + t.Run("UpdateValidatorSet - voting power negative", func(t *testing.T) { + fullValidatorSet := validators.GetPublicIdentities().Copy() + validatorsToUpdate := fullValidatorSet[4] + validatorsToUpdate.VotingPower = bigZero + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(fullValidatorSet), + })) + + updateDelta, err := stakeManager.UpdateValidatorSet(epoch+5, validators.GetPublicIdentities()) + require.NoError(t, err) + require.Len(t, updateDelta.Added, 0) + require.Len(t, updateDelta.Updated, 0) + require.Len(t, updateDelta.Removed, 1) + }) + + t.Run("UpdateValidatorSet - max validator set size reached", func(t *testing.T) { + // because we now have 5 validators, and the new validator has more stake + stakeManager.maxValidatorSetSize = 4 + + fullValidatorSet := validators.GetPublicIdentities().Copy() + validatorToAdd := fullValidatorSet[0] + validatorToAdd.VotingPower = big.NewInt(11) + + require.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + Validators: newValidatorStakeMap(fullValidatorSet), + })) + + updateDelta, err := stakeManager.UpdateValidatorSet(epoch+6, + validators.GetPublicIdentities(aliases[1:]...)) + + require.NoError(t, err) + require.Len(t, updateDelta.Added, 1) + require.Len(t, updateDelta.Updated, 0) + require.Len(t, updateDelta.Removed, 1) + require.Equal(t, validatorToAdd.Address, updateDelta.Added[0].Address) + require.Equal(t, validatorToAdd.VotingPower.Uint64(), updateDelta.Added[0].VotingPower.Uint64()) + }) +} + +func TestStakeCounter_ShouldBeDeterministic(t *testing.T) { + t.Parallel() + + const timesToExecute = 100 + + stakes := [][]uint64{ + {103, 102, 101, 51, 50, 30, 10}, + {100, 100, 100, 50, 50, 30, 10}, + {103, 102, 101, 51, 50, 30, 10}, + {100, 100, 100, 50, 50, 30, 10}, + } + maxValidatorSetSizes := []int{1000, 1000, 5, 6} + + for ind, stake := range stakes { + maxValidatorSetSize := maxValidatorSetSizes[ind] + + aliases := []string{"A", "B", "C", "D", "E", "F", "G"} + validators := validator.NewTestValidatorsWithAliases(t, aliases, stake) + + test := func() []*validator.ValidatorMetadata { + stakeCounter := newValidatorStakeMap(validators.GetPublicIdentities("A", "B", "C", "D", "E")) + + return stakeCounter.getSorted(maxValidatorSetSize) + } + + initialSlice := test() + + // stake counter and stake map should always be deterministic + for i := 0; i < timesToExecute; i++ { + currentSlice := test() + + require.Len(t, currentSlice, len(initialSlice)) + + for i, si := range currentSlice { + initialSi := initialSlice[i] + require.Equal(t, si.Address, initialSi.Address) + require.Equal(t, si.VotingPower.Uint64(), initialSi.VotingPower.Uint64()) + } + } + } +} + +func createTestLogForTransferEvent(t *testing.T, validatorSet, from, to types.Address, stake uint64) *types.Log { + t.Helper() + + var transferEvent contractsapi.TransferEvent + + topics := make([]types.Hash, 3) + topics[0] = types.Hash(transferEvent.Sig()) + topics[1] = types.BytesToHash(from.Bytes()) + topics[2] = types.BytesToHash(to.Bytes()) + encodedData, err := abi.MustNewType("uint256").Encode(new(big.Int).SetUint64(stake)) + require.NoError(t, err) + + return &types.Log{ + Address: validatorSet, + Topics: topics, + Data: encodedData, + } +} + +var _ txrelayer.TxRelayer = (*dummyStakeTxRelayer)(nil) + +type dummyStakeTxRelayer struct { + mock.Mock + callback func() *validator.ValidatorMetadata + t *testing.T +} + +func newDummyStakeTxRelayer(t *testing.T, callback func() *validator.ValidatorMetadata) *dummyStakeTxRelayer { + t.Helper() + + return &dummyStakeTxRelayer{ + t: t, + callback: callback, + } +} + +func (d *dummyStakeTxRelayer) Call(from ethgo.Address, to ethgo.Address, input []byte) (string, error) { + args := d.Called(from, to, input) + + if d.callback != nil { + validatorMetaData := d.callback() + encoded, err := validatorTypeABI.Encode(map[string]interface{}{ + "blsKey": validatorMetaData.BlsKey.ToBigInt(), + "stake": validatorMetaData.VotingPower, + "isWhitelisted": true, + "isActive": true, + }) + + require.NoError(d.t, err) + + return hex.EncodeToHex(encoded), nil + } + + return args.String(0), args.Error(1) +} + +func (d *dummyStakeTxRelayer) SendTransaction(transaction *ethgo.Transaction, key ethgo.Key) (*ethgo.Receipt, error) { + args := d.Called(transaction, key) + + return args.Get(0).(*ethgo.Receipt), args.Error(1) //nolint:forcetypeassert +} + +// SendTransactionLocal sends non-signed transaction (this is only for testing purposes) +func (d *dummyStakeTxRelayer) SendTransactionLocal(txn *ethgo.Transaction) (*ethgo.Receipt, error) { + args := d.Called(txn) + + return args.Get(0).(*ethgo.Receipt), args.Error(1) //nolint:forcetypeassert +} + +func (d *dummyStakeTxRelayer) Client() *jsonrpc.Client { + return nil +} diff --git a/consensus/polybft/state.go b/consensus/polybft/state.go index 83a71650f6..3e36e1ee01 100644 --- a/consensus/polybft/state.go +++ b/consensus/polybft/state.go @@ -54,6 +54,7 @@ type State struct { CheckpointStore *CheckpointStore EpochStore *EpochStore ProposerSnapshotStore *ProposerSnapshotStore + StakeStore *StakeStore } // newState creates new instance of State @@ -70,6 +71,7 @@ func newState(path string, logger hclog.Logger, closeCh chan struct{}) (*State, CheckpointStore: &CheckpointStore{db: db}, EpochStore: &EpochStore{db: db}, ProposerSnapshotStore: &ProposerSnapshotStore{db: db}, + StakeStore: &StakeStore{db: db}, } if err = s.initStorages(); err != nil { @@ -82,7 +84,7 @@ func newState(path string, logger hclog.Logger, closeCh chan struct{}) (*State, // initStorages initializes data storages func (s *State) initStorages() error { // init the buckets - err := s.db.Update(func(tx *bolt.Tx) error { + return s.db.Update(func(tx *bolt.Tx) error { if err := s.StateSyncStore.initialize(tx); err != nil { return err } @@ -96,10 +98,8 @@ func (s *State) initStorages() error { return err } - return nil + return s.StakeStore.initialize(tx) }) - - return err } // bucketStats returns stats for the given bucket in db diff --git a/consensus/polybft/state_store_checkpoint.go b/consensus/polybft/state_store_checkpoint.go index 6f5803baa2..4f56a36af8 100644 --- a/consensus/polybft/state_store_checkpoint.go +++ b/consensus/polybft/state_store_checkpoint.go @@ -173,14 +173,14 @@ func decodeExitEvent(log *ethgo.Log, epoch, block uint64) (*ExitEvent, error) { var l2StateSyncedEvent contractsapi.L2StateSyncedEvent doesMatch, err := l2StateSyncedEvent.ParseLog(log) - if !doesMatch { - return nil, nil - } - if err != nil { return nil, err } + if !doesMatch { + return nil, nil + } + return &ExitEvent{ ID: l2StateSyncedEvent.ID.Uint64(), Sender: ethgo.Address(l2StateSyncedEvent.Sender), @@ -195,10 +195,12 @@ func decodeExitEvent(log *ethgo.Log, epoch, block uint64) (*ExitEvent, error) { func convertLog(log *types.Log) *ethgo.Log { l := ðgo.Log{ Address: ethgo.Address(log.Address), - Data: log.Data, + Data: make([]byte, len(log.Data)), Topics: make([]ethgo.Hash, len(log.Topics)), } + copy(l.Data, log.Data) + for i, topic := range log.Topics { l.Topics[i] = ethgo.Hash(topic) } diff --git a/consensus/polybft/state_store_epoch.go b/consensus/polybft/state_store_epoch.go index 88b1fd3fbf..e1b7e5e983 100644 --- a/consensus/polybft/state_store_epoch.go +++ b/consensus/polybft/state_store_epoch.go @@ -33,6 +33,9 @@ epochs/ |--> epochNumber |--> hash -> []*MessageSignatures (json marshalled) +epochs/ +|--> epochNumber -> []*TransferEvent (json marshalled) + validatorSnapshots/ |--> epochNumber -> *AccountSet (json marshalled) */ @@ -110,6 +113,9 @@ func (s *EpochStore) insertEpoch(epoch uint64) error { return err } _, err = epochBucket.CreateBucketIfNotExists(messageVotesBucket) + if err != nil { + return err + } return err }) @@ -217,3 +223,18 @@ func (s *EpochStore) epochsDBStats() (*bolt.BucketStats, error) { func (s *EpochStore) validatorSnapshotsDBStats() (*bolt.BucketStats, error) { return bucketStats(validatorSnapshotsBucket, s.db) } + +// getNestedBucketInEpoch returns a nested (child) bucket from db associated with given epoch +func getNestedBucketInEpoch(tx *bolt.Tx, epoch uint64, bucketKey []byte) (*bolt.Bucket, error) { + epochBucket, err := getEpochBucket(tx, epoch) + if err != nil { + return nil, err + } + + bucket := epochBucket.Bucket(bucketKey) + if bucket == nil { + return nil, fmt.Errorf("could not find %v bucket for epoch: %v", string(bucketKey), epoch) + } + + return bucket, nil +} diff --git a/consensus/polybft/state_store_epoch_test.go b/consensus/polybft/state_store_epoch_test.go index 34a32a7b2d..15fb4604c3 100644 --- a/consensus/polybft/state_store_epoch_test.go +++ b/consensus/polybft/state_store_epoch_test.go @@ -6,6 +6,7 @@ import ( "testing" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -24,10 +25,10 @@ func TestState_insertAndGetValidatorSnapshot(t *testing.T) { require.NoError(t, err) - snapshot := AccountSet{ - &ValidatorMetadata{Address: types.BytesToAddress([]byte{0x18}), BlsKey: keys[0].PublicKey()}, - &ValidatorMetadata{Address: types.BytesToAddress([]byte{0x23}), BlsKey: keys[1].PublicKey()}, - &ValidatorMetadata{Address: types.BytesToAddress([]byte{0x37}), BlsKey: keys[2].PublicKey()}, + snapshot := validator.AccountSet{ + &validator.ValidatorMetadata{Address: types.BytesToAddress([]byte{0x18}), BlsKey: keys[0].PublicKey()}, + &validator.ValidatorMetadata{Address: types.BytesToAddress([]byte{0x23}), BlsKey: keys[1].PublicKey()}, + &validator.ValidatorMetadata{Address: types.BytesToAddress([]byte{0x37}), BlsKey: keys[2].PublicKey()}, } assert.NoError(t, state.EpochStore.insertValidatorSnapshot(&validatorSnapshot{epoch, epochEndingBlock, snapshot})) @@ -53,10 +54,10 @@ func TestState_cleanValidatorSnapshotsFromDb(t *testing.T) { keys, err := bls.CreateRandomBlsKeys(3) require.NoError(t, err) - snapshot := AccountSet{ - &ValidatorMetadata{Address: types.BytesToAddress([]byte{0x18}), BlsKey: keys[0].PublicKey()}, - &ValidatorMetadata{Address: types.BytesToAddress([]byte{0x23}), BlsKey: keys[1].PublicKey()}, - &ValidatorMetadata{Address: types.BytesToAddress([]byte{0x37}), BlsKey: keys[2].PublicKey()}, + snapshot := validator.AccountSet{ + &validator.ValidatorMetadata{Address: types.BytesToAddress([]byte{0x18}), BlsKey: keys[0].PublicKey()}, + &validator.ValidatorMetadata{Address: types.BytesToAddress([]byte{0x23}), BlsKey: keys[1].PublicKey()}, + &validator.ValidatorMetadata{Address: types.BytesToAddress([]byte{0x37}), BlsKey: keys[2].PublicKey()}, } var epoch uint64 @@ -198,9 +199,9 @@ func TestState_getLastSnapshot(t *testing.T) { require.NoError(t, err) - var snapshot AccountSet + var snapshot validator.AccountSet for j := 0; j < numberOfValidators; j++ { - snapshot = append(snapshot, &ValidatorMetadata{Address: types.BytesToAddress(generateRandomBytes(t)), BlsKey: keys[j].PublicKey()}) + snapshot = append(snapshot, &validator.ValidatorMetadata{Address: types.BytesToAddress(generateRandomBytes(t)), BlsKey: keys[j].PublicKey()}) } require.NoError(t, state.EpochStore.insertValidatorSnapshot(&validatorSnapshot{i, i * fixedEpochSize, snapshot})) diff --git a/consensus/polybft/state_store_stake.go b/consensus/polybft/state_store_stake.go new file mode 100644 index 0000000000..ae2080c662 --- /dev/null +++ b/consensus/polybft/state_store_stake.go @@ -0,0 +1,58 @@ +package polybft + +import ( + "errors" + "fmt" + + bolt "go.etcd.io/bbolt" +) + +var ( + // bucket to store full validator set + validatorSetBucket = []byte("fullValidatorSetBucket") + // key of the full validator set in bucket + fullValidatorSetKey = []byte("fullValidatorSet") + // error returned if full validator set does not exists in db + errNoFullValidatorSet = errors.New("full validator set not in db") +) + +type StakeStore struct { + db *bolt.DB +} + +// initialize creates necessary buckets in DB if they don't already exist +func (s *StakeStore) initialize(tx *bolt.Tx) error { + if _, err := tx.CreateBucketIfNotExists(validatorSetBucket); err != nil { + return fmt.Errorf("failed to create bucket=%s: %w", string(epochsBucket), err) + } + + return nil +} + +// insertFullValidatorSet inserts full validator set to its bucket (or updates it if exists) +func (s *StakeStore) insertFullValidatorSet(fullValidatorSet validatorSetState) error { + return s.db.Update(func(tx *bolt.Tx) error { + raw, err := fullValidatorSet.Marshal() + if err != nil { + return err + } + + return tx.Bucket(validatorSetBucket).Put(fullValidatorSetKey, raw) + }) +} + +// getFullValidatorSet returns full validator set from its bucket if exists +func (s *StakeStore) getFullValidatorSet() (validatorSetState, error) { + var fullValidatorSet validatorSetState + + err := s.db.View(func(tx *bolt.Tx) error { + raw := tx.Bucket(validatorSetBucket).Get(fullValidatorSetKey) + if raw == nil { + return errNoFullValidatorSet + } + + return fullValidatorSet.Unmarshal(raw) + }) + + return fullValidatorSet, err +} diff --git a/consensus/polybft/state_store_stake_test.go b/consensus/polybft/state_store_stake_test.go new file mode 100644 index 0000000000..4db0c2dc34 --- /dev/null +++ b/consensus/polybft/state_store_stake_test.go @@ -0,0 +1,51 @@ +package polybft + +import ( + "testing" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestState_Insert_And_Get_FullValidatorSet(t *testing.T) { + state := newTestState(t) + + t.Run("No full validator set", func(t *testing.T) { + _, err := state.StakeStore.getFullValidatorSet() + + require.ErrorIs(t, err, errNoFullValidatorSet) + }) + + t.Run("Insert validator set", func(t *testing.T) { + validators := validator.NewTestValidators(t, 5).GetPublicIdentities() + + assert.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + BlockNumber: 100, + EpochID: 10, + Validators: newValidatorStakeMap(validators), + })) + + fullValidatorSet, err := state.StakeStore.getFullValidatorSet() + require.NoError(t, err) + assert.Equal(t, uint64(100), fullValidatorSet.BlockNumber) + assert.Equal(t, uint64(10), fullValidatorSet.EpochID) + assert.Len(t, fullValidatorSet.Validators, len(validators)) + }) + + t.Run("Update validator set", func(t *testing.T) { + validators := validator.NewTestValidators(t, 10).GetPublicIdentities() + + assert.NoError(t, state.StakeStore.insertFullValidatorSet(validatorSetState{ + BlockNumber: 40, + EpochID: 4, + Validators: newValidatorStakeMap(validators), + })) + + fullValidatorSet, err := state.StakeStore.getFullValidatorSet() + require.NoError(t, err) + assert.Len(t, fullValidatorSet.Validators, len(validators)) + assert.Equal(t, uint64(40), fullValidatorSet.BlockNumber) + assert.Equal(t, uint64(4), fullValidatorSet.EpochID) + }) +} diff --git a/consensus/polybft/state_store_state_sync.go b/consensus/polybft/state_store_state_sync.go index 67cfb91db3..d15606500b 100644 --- a/consensus/polybft/state_store_state_sync.go +++ b/consensus/polybft/state_store_state_sync.go @@ -59,10 +59,6 @@ func (s *StateSyncStore) initialize(tx *bolt.Tx) error { return fmt.Errorf("failed to create bucket=%s: %w", string(stateSyncProofsBucket), err) } - if _, err := tx.CreateBucketIfNotExists(messageVotesBucket); err != nil { - return fmt.Errorf("failed to create bucket=%s: %w", string(messageVotesBucket), err) - } - return nil } @@ -224,11 +220,7 @@ func (s *StateSyncStore) insertMessageVote(epoch uint64, key []byte, vote *Messa return err } - if err := bucket.Put(key, raw); err != nil { - return err - } - - return nil + return bucket.Put(key, raw) }) if err != nil { @@ -279,21 +271,6 @@ func (s *StateSyncStore) getMessageVotesLocked(tx *bolt.Tx, epoch uint64, hash [ return signatures, nil } -// getNestedBucketInEpoch returns a nested (child) bucket from db associated with given epoch -func getNestedBucketInEpoch(tx *bolt.Tx, epoch uint64, bucketKey []byte) (*bolt.Bucket, error) { - epochBucket, err := getEpochBucket(tx, epoch) - if err != nil { - return nil, err - } - - bucket := epochBucket.Bucket(bucketKey) - if bucket == nil { - return nil, fmt.Errorf("could not find %v bucket for epoch: %v", string(bucketKey), epoch) - } - - return bucket, nil -} - // insertStateSyncProofs inserts the provided state sync proofs to db func (s *StateSyncStore) insertStateSyncProofs(stateSyncProof []*StateSyncProof) error { return s.db.Update(func(tx *bolt.Tx) error { diff --git a/consensus/polybft/state_sync_commitment.go b/consensus/polybft/state_sync_commitment.go new file mode 100644 index 0000000000..6f109d834f --- /dev/null +++ b/consensus/polybft/state_sync_commitment.go @@ -0,0 +1,202 @@ +package polybft + +import ( + "bytes" + "errors" + "fmt" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/crypto" + "github.com/0xPolygon/polygon-edge/merkle-tree" + "github.com/0xPolygon/polygon-edge/state/runtime/precompiled" + "github.com/0xPolygon/polygon-edge/types" +) + +const ( + stTypeBridgeCommitment = "commitment" + stTypeEndEpoch = "end-epoch" +) + +// PendingCommitment holds merkle trie of bridge transactions accompanied by epoch number +type PendingCommitment struct { + *contractsapi.StateSyncCommitment + MerkleTree *merkle.MerkleTree + Epoch uint64 +} + +// NewPendingCommitment creates a new commitment object +func NewPendingCommitment(epoch uint64, stateSyncEvents []*contractsapi.StateSyncedEvent) (*PendingCommitment, error) { + tree, err := createMerkleTree(stateSyncEvents) + if err != nil { + return nil, err + } + + return &PendingCommitment{ + MerkleTree: tree, + Epoch: epoch, + StateSyncCommitment: &contractsapi.StateSyncCommitment{ + StartID: stateSyncEvents[0].ID, + EndID: stateSyncEvents[len(stateSyncEvents)-1].ID, + Root: tree.Hash(), + }, + }, nil +} + +// Hash calculates hash value for commitment object. +func (cm *PendingCommitment) Hash() (types.Hash, error) { + data, err := cm.StateSyncCommitment.EncodeAbi() + if err != nil { + return types.Hash{}, err + } + + return crypto.Keccak256Hash(data), nil +} + +var _ contractsapi.StateTransactionInput = &CommitmentMessageSigned{} + +// CommitmentMessageSigned encapsulates commitment message with aggregated signatures +type CommitmentMessageSigned struct { + Message *contractsapi.StateSyncCommitment + AggSignature Signature + PublicKeys [][]byte +} + +// Hash calculates hash value for commitment object. +func (cm *CommitmentMessageSigned) Hash() (types.Hash, error) { + data, err := cm.Message.EncodeAbi() + if err != nil { + return types.Hash{}, err + } + + return crypto.Keccak256Hash(data), nil +} + +// VerifyStateSyncProof validates given state sync proof +// against merkle tree root hash contained in the CommitmentMessage +func (cm *CommitmentMessageSigned) VerifyStateSyncProof(proof []types.Hash, + stateSync *contractsapi.StateSyncedEvent) error { + if stateSync == nil { + return errors.New("no state sync event") + } + + if stateSync.ID.Uint64() < cm.Message.StartID.Uint64() || + stateSync.ID.Uint64() > cm.Message.EndID.Uint64() { + return errors.New("invalid state sync ID") + } + + hash, err := stateSync.EncodeAbi() + if err != nil { + return err + } + + return merkle.VerifyProof(stateSync.ID.Uint64()-cm.Message.StartID.Uint64(), + hash, proof, cm.Message.Root) +} + +// ContainsStateSync checks if commitment contains given state sync event +func (cm *CommitmentMessageSigned) ContainsStateSync(stateSyncID uint64) bool { + return cm.Message.StartID.Uint64() <= stateSyncID && cm.Message.EndID.Uint64() >= stateSyncID +} + +// EncodeAbi contains logic for encoding arbitrary data into ABI format +func (cm *CommitmentMessageSigned) EncodeAbi() ([]byte, error) { + blsVerificationPart, err := precompiled.BlsVerificationABIType.Encode( + [2]interface{}{cm.PublicKeys, cm.AggSignature.Bitmap}) + if err != nil { + return nil, err + } + + commit := &contractsapi.CommitStateReceiverFn{ + Commitment: cm.Message, + Signature: cm.AggSignature.AggregatedSignature, + Bitmap: blsVerificationPart, + } + + return commit.EncodeAbi() +} + +// DecodeAbi contains logic for decoding given ABI data +func (cm *CommitmentMessageSigned) DecodeAbi(txData []byte) error { + if len(txData) < abiMethodIDLength { + return fmt.Errorf("invalid commitment data, len = %d", len(txData)) + } + + commit := contractsapi.CommitStateReceiverFn{} + + err := commit.DecodeAbi(txData) + if err != nil { + return err + } + + decoded, err := precompiled.BlsVerificationABIType.Decode(commit.Bitmap) + if err != nil { + return err + } + + blsMap, isOk := decoded.(map[string]interface{}) + if !isOk { + return fmt.Errorf("invalid commitment data. Bls verification part not in correct format") + } + + publicKeys, isOk := blsMap["0"].([][]byte) + if !isOk { + return fmt.Errorf("invalid commitment data. Could not find public keys part") + } + + bitmap, isOk := blsMap["1"].([]byte) + if !isOk { + return fmt.Errorf("invalid commitment data. Could not find bitmap part") + } + + *cm = CommitmentMessageSigned{ + Message: commit.Commitment, + AggSignature: Signature{ + AggregatedSignature: commit.Signature, + Bitmap: bitmap, + }, + PublicKeys: publicKeys, + } + + return nil +} + +// getCommitmentMessageSignedTx returns a CommitmentMessageSigned object from a commit state transaction +func getCommitmentMessageSignedTx(txs []*types.Transaction) (*CommitmentMessageSigned, error) { + var commitFn contractsapi.CommitStateReceiverFn + for _, tx := range txs { + // skip non state CommitmentMessageSigned transactions + if tx.Type != types.StateTx || + len(tx.Input) < abiMethodIDLength || + !bytes.Equal(tx.Input[:abiMethodIDLength], commitFn.Sig()) { + continue + } + + obj := &CommitmentMessageSigned{} + + if err := obj.DecodeAbi(tx.Input); err != nil { + return nil, fmt.Errorf("get commitment message signed tx error: %w", err) + } + + return obj, nil + } + + return nil, nil +} + +// createMerkleTree creates a merkle tree from provided state sync events +// if only one state sync event is provided, a second, empty leaf will be added to merkle tree +// so that we can have a commitment with a single state sync event +func createMerkleTree(stateSyncEvents []*contractsapi.StateSyncedEvent) (*merkle.MerkleTree, error) { + stateSyncData := make([][]byte, len(stateSyncEvents)) + + for i, sse := range stateSyncEvents { + data, err := sse.EncodeAbi() + if err != nil { + return nil, err + } + + stateSyncData[i] = data + } + + return merkle.NewMerkleTree(stateSyncData) +} diff --git a/consensus/polybft/state_sync_commitment_test.go b/consensus/polybft/state_sync_commitment_test.go new file mode 100644 index 0000000000..61018f7517 --- /dev/null +++ b/consensus/polybft/state_sync_commitment_test.go @@ -0,0 +1,178 @@ +package polybft + +import ( + "math/big" + "testing" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCommitmentMessage_Hash(t *testing.T) { + t.Parallel() + + const ( + eventsCount = 10 + ) + + stateSyncEvents := generateStateSyncEvents(t, eventsCount, 0) + + trie1, err := createMerkleTree(stateSyncEvents) + require.NoError(t, err) + + trie2, err := createMerkleTree(stateSyncEvents[0 : len(stateSyncEvents)-1]) + require.NoError(t, err) + + commitmentMessage1 := newTestCommitmentSigned(t, trie1.Hash(), 2, 8) + commitmentMessage2 := newTestCommitmentSigned(t, trie1.Hash(), 2, 8) + commitmentMessage3 := newTestCommitmentSigned(t, trie1.Hash(), 6, 10) + commitmentMessage4 := newTestCommitmentSigned(t, trie2.Hash(), 2, 8) + + hash1, err := commitmentMessage1.Hash() + require.NoError(t, err) + hash2, err := commitmentMessage2.Hash() + require.NoError(t, err) + hash3, err := commitmentMessage3.Hash() + require.NoError(t, err) + hash4, err := commitmentMessage4.Hash() + require.NoError(t, err) + + require.Equal(t, hash1, hash2) + require.NotEqual(t, hash1, hash3) + require.NotEqual(t, hash1, hash4) + require.NotEqual(t, hash3, hash4) +} + +func TestCommitmentMessage_ToRegisterCommitmentInputData(t *testing.T) { + t.Parallel() + + const epoch, eventsCount = uint64(100), 11 + pendingCommitment, _, _ := buildCommitmentAndStateSyncs(t, eventsCount, epoch, uint64(2)) + expectedSignedCommitmentMsg := &CommitmentMessageSigned{ + Message: pendingCommitment.StateSyncCommitment, + AggSignature: Signature{ + Bitmap: []byte{5, 1}, + AggregatedSignature: []byte{1, 1}, + }, + PublicKeys: [][]byte{{0, 1}, {2, 3}, {4, 5}}, + } + inputData, err := expectedSignedCommitmentMsg.EncodeAbi() + require.NoError(t, err) + require.NotEmpty(t, inputData) + + var actualSignedCommitmentMsg CommitmentMessageSigned + + require.NoError(t, actualSignedCommitmentMsg.DecodeAbi(inputData)) + require.NoError(t, err) + require.Equal(t, *expectedSignedCommitmentMsg.Message, *actualSignedCommitmentMsg.Message) + require.Equal(t, expectedSignedCommitmentMsg.AggSignature, actualSignedCommitmentMsg.AggSignature) +} + +func TestCommitmentMessage_VerifyProof(t *testing.T) { + t.Parallel() + + const epoch, eventsCount = uint64(100), 11 + commitment, commitmentSigned, stateSyncs := buildCommitmentAndStateSyncs(t, eventsCount, epoch, 0) + require.Equal(t, uint64(10), commitment.EndID.Sub(commitment.EndID, commitment.StartID).Uint64()) + + for _, stateSync := range stateSyncs { + leaf, err := stateSync.EncodeAbi() + require.NoError(t, err) + + proof, err := commitment.MerkleTree.GenerateProof(leaf) + require.NoError(t, err) + + execute := &contractsapi.ExecuteStateReceiverFn{ + Proof: proof, + Obj: (*contractsapi.StateSync)(stateSync), + } + + inputData, err := execute.EncodeAbi() + require.NoError(t, err) + + executionStateSync := &contractsapi.ExecuteStateReceiverFn{} + require.NoError(t, executionStateSync.DecodeAbi(inputData)) + require.Equal(t, stateSync.ID.Uint64(), executionStateSync.Obj.ID.Uint64()) + require.Equal(t, stateSync.Sender, executionStateSync.Obj.Sender) + require.Equal(t, stateSync.Receiver, executionStateSync.Obj.Receiver) + require.Equal(t, stateSync.Data, executionStateSync.Obj.Data) + require.Equal(t, proof, executionStateSync.Proof) + + err = commitmentSigned.VerifyStateSyncProof(executionStateSync.Proof, + (*contractsapi.StateSyncedEvent)(executionStateSync.Obj)) + require.NoError(t, err) + } +} + +func TestCommitmentMessage_VerifyProof_NoStateSyncsInCommitment(t *testing.T) { + t.Parallel() + + commitment := &CommitmentMessageSigned{Message: &contractsapi.StateSyncCommitment{StartID: big.NewInt(1), EndID: big.NewInt(10)}} + err := commitment.VerifyStateSyncProof([]types.Hash{}, nil) + assert.ErrorContains(t, err, "no state sync event") +} + +func TestCommitmentMessage_VerifyProof_StateSyncHashNotEqualToProof(t *testing.T) { + t.Parallel() + + const ( + fromIndex = 0 + toIndex = 4 + ) + + stateSyncs := generateStateSyncEvents(t, 5, 0) + tree, err := createMerkleTree(stateSyncs) + require.NoError(t, err) + + leaf, err := stateSyncs[0].EncodeAbi() + require.NoError(t, err) + + proof, err := tree.GenerateProof(leaf) + require.NoError(t, err) + + commitment := &CommitmentMessageSigned{ + Message: &contractsapi.StateSyncCommitment{ + StartID: big.NewInt(fromIndex), + EndID: big.NewInt(toIndex), + Root: tree.Hash(), + }, + } + + assert.ErrorContains(t, commitment.VerifyStateSyncProof(proof, stateSyncs[4]), "not a member of merkle tree") +} + +func newTestCommitmentSigned(t *testing.T, root types.Hash, startID, endID int64) *CommitmentMessageSigned { + t.Helper() + + return &CommitmentMessageSigned{ + Message: &contractsapi.StateSyncCommitment{ + StartID: big.NewInt(startID), + EndID: big.NewInt(endID), + Root: root, + }, + AggSignature: Signature{}, + PublicKeys: [][]byte{}, + } +} + +func buildCommitmentAndStateSyncs(t *testing.T, stateSyncsCount int, + epoch, startIdx uint64) (*PendingCommitment, *CommitmentMessageSigned, []*contractsapi.StateSyncedEvent) { + t.Helper() + + stateSyncEvents := generateStateSyncEvents(t, stateSyncsCount, startIdx) + commitment, err := NewPendingCommitment(epoch, stateSyncEvents) + require.NoError(t, err) + + commitmentSigned := &CommitmentMessageSigned{ + Message: commitment.StateSyncCommitment, + AggSignature: Signature{ + AggregatedSignature: []byte{}, + Bitmap: []byte{}, + }, + PublicKeys: [][]byte{}, + } + + return commitment, commitmentSigned, stateSyncEvents +} diff --git a/consensus/polybft/state_sync_manager.go b/consensus/polybft/state_sync_manager.go index 4a8959bd32..3d7d3d352d 100644 --- a/consensus/polybft/state_sync_manager.go +++ b/consensus/polybft/state_sync_manager.go @@ -13,6 +13,7 @@ import ( "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" polybftProto "github.com/0xPolygon/polygon-edge/consensus/polybft/proto" bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/tracker" "github.com/0xPolygon/polygon-edge/types" @@ -22,12 +23,6 @@ import ( "google.golang.org/protobuf/proto" ) -const ( - // minimum number of stateSyncEvents that a commitment can have - // (minimum number is 2 because smart contract expects that the merkle tree has at least two leaves) - minCommitmentSize = 2 -) - type StateSyncProof struct { Proof []types.Hash StateSync *contractsapi.StateSyncedEvent @@ -83,7 +78,7 @@ type stateSyncManager struct { // per epoch fields lock sync.RWMutex pendingCommitments []*PendingCommitment - validatorSet ValidatorSet + validatorSet validator.ValidatorSet epoch uint64 nextCommittedIndex uint64 } @@ -95,15 +90,13 @@ type topic interface { } // newStateSyncManager creates a new instance of state sync manager -func newStateSyncManager(logger hclog.Logger, state *State, config *stateSyncConfig) (*stateSyncManager, error) { - s := &stateSyncManager{ +func newStateSyncManager(logger hclog.Logger, state *State, config *stateSyncConfig) *stateSyncManager { + return &stateSyncManager{ logger: logger, state: state, config: config, closeCh: make(chan struct{}), } - - return s, nil } // Init subscribes to bridge topics (getting votes) and start the event tracker routine @@ -205,7 +198,7 @@ func (s *stateSyncManager) saveVote(msg *TransportMessage) error { } // Verifies signature of the message against the public key of the signer and checks if the signer is a validator -func (s *stateSyncManager) verifyVoteSignature(valSet ValidatorSet, signer types.Address, signature []byte, +func (s *stateSyncManager) verifyVoteSignature(valSet validator.ValidatorSet, signer types.Address, signature []byte, hash []byte) error { validator := valSet.Accounts().GetValidatorMetadata(signer) if validator == nil { @@ -502,17 +495,14 @@ func (s *stateSyncManager) buildCommitment() error { s.lock.Lock() defer s.lock.Unlock() - epoch := s.epoch - fromIndex := s.nextCommittedIndex - - stateSyncEvents, err := s.state.StateSyncStore.getStateSyncEventsForCommitment(fromIndex, - fromIndex+s.config.maxCommitmentSize-1) + stateSyncEvents, err := s.state.StateSyncStore.getStateSyncEventsForCommitment(s.nextCommittedIndex, + s.nextCommittedIndex+s.config.maxCommitmentSize-1) if err != nil && !errors.Is(err, errNotEnoughStateSyncs) { return fmt.Errorf("failed to get state sync events for commitment. Error: %w", err) } - if len(stateSyncEvents) < minCommitmentSize { - // there is not enough state sync events to build at least the minimum commitment + if len(stateSyncEvents) == 0 { + // there are no state sync events return nil } @@ -522,7 +512,7 @@ func (s *stateSyncManager) buildCommitment() error { return nil } - commitment, err := NewPendingCommitment(epoch, stateSyncEvents) + commitment, err := NewPendingCommitment(s.epoch, stateSyncEvents) if err != nil { return err } @@ -544,7 +534,7 @@ func (s *stateSyncManager) buildCommitment() error { Signature: signature, } - if _, err = s.state.StateSyncStore.insertMessageVote(epoch, hashBytes, sig); err != nil { + if _, err = s.state.StateSyncStore.insertMessageVote(s.epoch, hashBytes, sig); err != nil { return fmt.Errorf( "failed to insert signature for hash=%v to the state. Error: %w", hex.EncodeToString(hashBytes), @@ -557,7 +547,7 @@ func (s *stateSyncManager) buildCommitment() error { Hash: hashBytes, Signature: signature, From: s.config.key.String(), - EpochNumber: epoch, + EpochNumber: s.epoch, }) s.logger.Debug( diff --git a/consensus/polybft/state_sync_manager_test.go b/consensus/polybft/state_sync_manager_test.go index f5db485169..b716338792 100644 --- a/consensus/polybft/state_sync_manager_test.go +++ b/consensus/polybft/state_sync_manager_test.go @@ -7,10 +7,6 @@ import ( "testing" "time" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" - "github.com/0xPolygon/polygon-edge/merkle-tree" - "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" "github.com/libp2p/go-libp2p/core/peer" "github.com/stretchr/testify/require" @@ -18,9 +14,15 @@ import ( "github.com/umbracle/ethgo/abi" "github.com/umbracle/ethgo/testutil" "google.golang.org/protobuf/proto" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/merkle-tree" + "github.com/0xPolygon/polygon-edge/types" ) -func newTestStateSyncManager(t *testing.T, key *testValidator) *stateSyncManager { +func newTestStateSyncManager(t *testing.T, key *validator.TestValidator) *stateSyncManager { t.Helper() tmpDir, err := os.MkdirTemp("/tmp", "test-data-dir-state-sync") @@ -31,7 +33,7 @@ func newTestStateSyncManager(t *testing.T, key *testValidator) *stateSyncManager topic := &mockTopic{} - s, err := newStateSyncManager(hclog.NewNullLogger(), state, + s := newStateSyncManager(hclog.NewNullLogger(), state, &stateSyncConfig{ stateSenderAddr: types.Address{}, jsonrpcAddr: "", @@ -41,8 +43,6 @@ func newTestStateSyncManager(t *testing.T, key *testValidator) *stateSyncManager maxCommitmentSize: maxCommitmentSize, }) - require.NoError(t, err) - t.Cleanup(func() { os.RemoveAll(tmpDir) }) @@ -51,8 +51,8 @@ func newTestStateSyncManager(t *testing.T, key *testValidator) *stateSyncManager } func TestStateSyncManager_PostEpoch_BuildCommitment(t *testing.T) { - vals := newTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) + vals := validator.NewTestValidators(t, 5) + s := newTestStateSyncManager(t, vals.GetValidator("0")) // there are no state syncs require.NoError(t, s.buildCommitment()) @@ -87,9 +87,9 @@ func TestStateSyncManager_PostEpoch_BuildCommitment(t *testing.T) { } func TestStateSyncManager_MessagePool_OldEpoch(t *testing.T) { - vals := newTestValidators(t, 5) + vals := validator.NewTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) + s := newTestStateSyncManager(t, vals.GetValidator("0")) s.epoch = 1 msg := &TransportMessage{ @@ -117,8 +117,8 @@ func (m *mockMsg) WithHash(hash []byte) *mockMsg { return m } -func (m *mockMsg) sign(val *testValidator, domain []byte) (*TransportMessage, error) { - signature, err := val.mustSign(m.hash, domain).Marshal() +func (m *mockMsg) sign(val *validator.TestValidator, domain []byte) (*TransportMessage, error) { + signature, err := val.MustSign(m.hash, domain).Marshal() if err != nil { return nil, err } @@ -132,12 +132,12 @@ func (m *mockMsg) sign(val *testValidator, domain []byte) (*TransportMessage, er } func TestStateSyncManager_MessagePool_SenderIsNoValidator(t *testing.T) { - vals := newTestValidators(t, 5) + vals := validator.NewTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) - s.validatorSet = vals.toValidatorSet() + s := newTestStateSyncManager(t, vals.GetValidator("0")) + s.validatorSet = vals.ToValidatorSet() - badVal := newTestValidator(t, "a", 0) + badVal := validator.NewTestValidator(t, "a", 0) msg, err := newMockMsg().sign(badVal, bls.DomainStateReceiver) require.NoError(t, err) @@ -147,13 +147,13 @@ func TestStateSyncManager_MessagePool_SenderIsNoValidator(t *testing.T) { func TestStateSyncManager_MessagePool_InvalidEpoch(t *testing.T) { t.Parallel() - vals := newTestValidators(t, 5) + vals := validator.NewTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) - s.validatorSet = vals.toValidatorSet() + s := newTestStateSyncManager(t, vals.GetValidator("0")) + s.validatorSet = vals.ToValidatorSet() val := newMockMsg() - msg, err := val.sign(vals.getValidator("0"), bls.DomainStateReceiver) + msg, err := val.sign(vals.GetValidator("0"), bls.DomainStateReceiver) require.NoError(t, err) msg.EpochNumber = 1 @@ -173,39 +173,39 @@ func TestStateSyncManager_MessagePool_InvalidEpoch(t *testing.T) { func TestStateSyncManager_MessagePool_SenderAndSignatureMissmatch(t *testing.T) { t.Parallel() - vals := newTestValidators(t, 5) + vals := validator.NewTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) - s.validatorSet = vals.toValidatorSet() + s := newTestStateSyncManager(t, vals.GetValidator("0")) + s.validatorSet = vals.ToValidatorSet() // validator signs the msg in behalf of another validator val := newMockMsg() - msg, err := val.sign(vals.getValidator("0"), bls.DomainStateReceiver) + msg, err := val.sign(vals.GetValidator("0"), bls.DomainStateReceiver) require.NoError(t, err) - msg.From = vals.getValidator("1").Address().String() + msg.From = vals.GetValidator("1").Address().String() require.Error(t, s.saveVote(msg)) // non validator signs the msg in behalf of a validator - badVal := newTestValidator(t, "a", 0) + badVal := validator.NewTestValidator(t, "a", 0) msg, err = newMockMsg().sign(badVal, bls.DomainStateReceiver) require.NoError(t, err) - msg.From = vals.getValidator("1").Address().String() + msg.From = vals.GetValidator("1").Address().String() require.Error(t, s.saveVote(msg)) } func TestStateSyncManager_MessagePool_SenderVotes(t *testing.T) { - vals := newTestValidators(t, 5) + vals := validator.NewTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) - s.validatorSet = vals.toValidatorSet() + s := newTestStateSyncManager(t, vals.GetValidator("0")) + s.validatorSet = vals.ToValidatorSet() msg := newMockMsg() - val1signed, err := msg.sign(vals.getValidator("1"), bls.DomainStateReceiver) + val1signed, err := msg.sign(vals.GetValidator("1"), bls.DomainStateReceiver) require.NoError(t, err) - val2signed, err := msg.sign(vals.getValidator("2"), bls.DomainStateReceiver) + val2signed, err := msg.sign(vals.GetValidator("2"), bls.DomainStateReceiver) require.NoError(t, err) // vote with validator 1 @@ -227,10 +227,10 @@ func TestStateSyncManager_MessagePool_SenderVotes(t *testing.T) { } func TestStateSyncManager_BuildCommitment(t *testing.T) { - vals := newTestValidators(t, 5) + vals := validator.NewTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) - s.validatorSet = vals.toValidatorSet() + s := newTestStateSyncManager(t, vals.GetValidator("0")) + s.validatorSet = vals.ToValidatorSet() // commitment is empty commitment, err := s.Commitment() @@ -258,10 +258,10 @@ func TestStateSyncManager_BuildCommitment(t *testing.T) { // validators 0 and 1 vote for the proposal, there is not enough // voting power for the proposal - signedMsg1, err := msg.sign(vals.getValidator("0"), bls.DomainStateReceiver) + signedMsg1, err := msg.sign(vals.GetValidator("0"), bls.DomainStateReceiver) require.NoError(t, err) - signedMsg2, err := msg.sign(vals.getValidator("1"), bls.DomainStateReceiver) + signedMsg2, err := msg.sign(vals.GetValidator("1"), bls.DomainStateReceiver) require.NoError(t, err) require.NoError(t, s.saveVote(signedMsg1)) @@ -273,10 +273,10 @@ func TestStateSyncManager_BuildCommitment(t *testing.T) { // validator 2 and 3 vote for the proposal, there is enough voting power now - signedMsg1, err = msg.sign(vals.getValidator("2"), bls.DomainStateReceiver) + signedMsg1, err = msg.sign(vals.GetValidator("2"), bls.DomainStateReceiver) require.NoError(t, err) - signedMsg2, err = msg.sign(vals.getValidator("3"), bls.DomainStateReceiver) + signedMsg2, err = msg.sign(vals.GetValidator("3"), bls.DomainStateReceiver) require.NoError(t, err) require.NoError(t, s.saveVote(signedMsg1)) @@ -288,9 +288,9 @@ func TestStateSyncManager_BuildCommitment(t *testing.T) { } func TestStateSyncerManager_BuildProofs(t *testing.T) { - vals := newTestValidators(t, 5) + vals := validator.NewTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) + s := newTestStateSyncManager(t, vals.GetValidator("0")) for _, evnt := range generateStateSyncEvents(t, 20, 0) { require.NoError(t, s.state.StateSyncStore.insertStateSyncEvent(evnt)) @@ -330,9 +330,9 @@ func TestStateSyncerManager_BuildProofs(t *testing.T) { } func TestStateSyncerManager_AddLog_BuildCommitments(t *testing.T) { - vals := newTestValidators(t, 5) + vals := validator.NewTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) + s := newTestStateSyncManager(t, vals.GetValidator("0")) // empty log which is not an state sync s.AddLog(ðgo.Log{}) @@ -371,16 +371,18 @@ func TestStateSyncerManager_AddLog_BuildCommitments(t *testing.T) { stateSyncs, err = s.state.StateSyncStore.getStateSyncEventsForCommitment(0, 0) require.NoError(t, err) require.Len(t, stateSyncs, 1) - require.Len(t, s.pendingCommitments, 0) + require.Len(t, s.pendingCommitments, 1) + require.Equal(t, uint64(0), s.pendingCommitments[0].StartID.Uint64()) + require.Equal(t, uint64(0), s.pendingCommitments[0].EndID.Uint64()) // add one more log to have a minimum commitment goodLog2 := goodLog.Copy() goodLog2.Topics[1] = ethgo.BytesToHash([]byte{0x1}) // state sync index 1 s.AddLog(goodLog2) - require.Len(t, s.pendingCommitments, 1) - require.Equal(t, uint64(0), s.pendingCommitments[0].StartID.Uint64()) - require.Equal(t, uint64(1), s.pendingCommitments[0].EndID.Uint64()) + require.Len(t, s.pendingCommitments, 2) + require.Equal(t, uint64(0), s.pendingCommitments[1].StartID.Uint64()) + require.Equal(t, uint64(1), s.pendingCommitments[1].EndID.Uint64()) // add two more logs to have larger commitments goodLog3 := goodLog.Copy() @@ -391,52 +393,50 @@ func TestStateSyncerManager_AddLog_BuildCommitments(t *testing.T) { goodLog4.Topics[1] = ethgo.BytesToHash([]byte{0x3}) // state sync index 3 s.AddLog(goodLog4) - require.Len(t, s.pendingCommitments, 3) - require.Equal(t, uint64(0), s.pendingCommitments[2].StartID.Uint64()) - require.Equal(t, uint64(3), s.pendingCommitments[2].EndID.Uint64()) + require.Len(t, s.pendingCommitments, 4) + require.Equal(t, uint64(0), s.pendingCommitments[3].StartID.Uint64()) + require.Equal(t, uint64(3), s.pendingCommitments[3].EndID.Uint64()) } func TestStateSyncerManager_EventTracker_Sync(t *testing.T) { t.Parallel() - vals := newTestValidators(t, 5) - s := newTestStateSyncManager(t, vals.getValidator("0")) + vals := validator.NewTestValidators(t, 5) + s := newTestStateSyncManager(t, vals.GetValidator("0")) server := testutil.DeployTestServer(t, nil) - //nolint:godox - // TODO: Deploy local artifacts (to be fixed in EVM-542) - cc := &testutil.Contract{} - cc.AddCallback(func() string { - return ` - event StateSynced(uint256 indexed id, address indexed sender, address indexed receiver, bytes data); - uint256 indx; - - function emitEvent() public payable { - emit StateSynced(indx, msg.sender, msg.sender, bytes("")); - indx++; - } - ` + // Deploy contract + contractReceipt, err := server.SendTxn(ðgo.Transaction{ + Input: contractsapi.StateSender.Bytecode, }) + require.NoError(t, err) - _, addr, err := server.DeployContract(cc) + // Create contract function call payload + encodedSyncStateData, err := (&contractsapi.SyncStateStateSenderFn{ + Receiver: types.BytesToAddress(server.Account(0).Bytes()), + Data: []byte{}, + }).EncodeAbi() require.NoError(t, err) // prefill with 10 events for i := 0; i < 10; i++ { - receipt, err := server.TxnTo(addr, "emitEvent") + receipt, err := server.SendTxn(ðgo.Transaction{ + To: &contractReceipt.ContractAddress, + Input: encodedSyncStateData, + }) require.NoError(t, err) require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) } - s.config.stateSenderAddr = types.Address(addr) + s.config.stateSenderAddr = types.Address(contractReceipt.ContractAddress) s.config.jsonrpcAddr = server.HTTPAddr() require.NoError(t, s.initTracker()) time.Sleep(2 * time.Second) - events, err := s.state.StateSyncStore.getStateSyncEventsForCommitment(0, 9) + events, err := s.state.StateSyncStore.getStateSyncEventsForCommitment(1, 10) require.NoError(t, err) require.Len(t, events, 10) } @@ -444,7 +444,7 @@ func TestStateSyncerManager_EventTracker_Sync(t *testing.T) { func TestStateSyncManager_Close(t *testing.T) { t.Parallel() - mgr := newTestStateSyncManager(t, newTestValidator(t, "A", 100)) + mgr := newTestStateSyncManager(t, validator.NewTestValidator(t, "A", 100)) require.NotPanics(t, func() { mgr.Close() }) } diff --git a/consensus/polybft/state_transaction.go b/consensus/polybft/state_transaction.go index 6b59db3ce5..0d98d3faf4 100644 --- a/consensus/polybft/state_transaction.go +++ b/consensus/polybft/state_transaction.go @@ -2,164 +2,12 @@ package polybft import ( "bytes" - "errors" "fmt" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/crypto" - "github.com/0xPolygon/polygon-edge/merkle-tree" - "github.com/0xPolygon/polygon-edge/state/runtime/precompiled" - "github.com/0xPolygon/polygon-edge/types" ) -const ( - abiMethodIDLength = 4 - stTypeBridgeCommitment = "commitment" - stTypeEndEpoch = "end-epoch" -) - -// PendingCommitment holds merkle trie of bridge transactions accompanied by epoch number -type PendingCommitment struct { - *contractsapi.StateSyncCommitment - MerkleTree *merkle.MerkleTree - Epoch uint64 -} - -// NewPendingCommitment creates a new commitment object -func NewPendingCommitment(epoch uint64, stateSyncEvents []*contractsapi.StateSyncedEvent) (*PendingCommitment, error) { - tree, err := createMerkleTree(stateSyncEvents) - if err != nil { - return nil, err - } - - return &PendingCommitment{ - MerkleTree: tree, - Epoch: epoch, - StateSyncCommitment: &contractsapi.StateSyncCommitment{ - StartID: stateSyncEvents[0].ID, - EndID: stateSyncEvents[len(stateSyncEvents)-1].ID, - Root: tree.Hash(), - }, - }, nil -} - -// Hash calculates hash value for commitment object. -func (cm *PendingCommitment) Hash() (types.Hash, error) { - data, err := cm.StateSyncCommitment.EncodeAbi() - if err != nil { - return types.Hash{}, err - } - - return crypto.Keccak256Hash(data), nil -} - -var _ contractsapi.StateTransactionInput = &CommitmentMessageSigned{} - -// CommitmentMessageSigned encapsulates commitment message with aggregated signatures -type CommitmentMessageSigned struct { - Message *contractsapi.StateSyncCommitment - AggSignature Signature - PublicKeys [][]byte -} - -// Hash calculates hash value for commitment object. -func (cm *CommitmentMessageSigned) Hash() (types.Hash, error) { - data, err := cm.Message.EncodeAbi() - if err != nil { - return types.Hash{}, err - } - - return crypto.Keccak256Hash(data), nil -} - -// VerifyStateSyncProof validates given state sync proof -// against merkle tree root hash contained in the CommitmentMessage -func (cm *CommitmentMessageSigned) VerifyStateSyncProof(proof []types.Hash, - stateSync *contractsapi.StateSyncedEvent) error { - if stateSync == nil { - return errors.New("no state sync event") - } - - if stateSync.ID.Uint64() < cm.Message.StartID.Uint64() || - stateSync.ID.Uint64() > cm.Message.EndID.Uint64() { - return errors.New("invalid state sync ID") - } - - hash, err := stateSync.EncodeAbi() - if err != nil { - return err - } - - return merkle.VerifyProof(stateSync.ID.Uint64()-cm.Message.StartID.Uint64(), - hash, proof, cm.Message.Root) -} - -// ContainsStateSync checks if commitment contains given state sync event -func (cm *CommitmentMessageSigned) ContainsStateSync(stateSyncID uint64) bool { - return cm.Message.StartID.Uint64() <= stateSyncID && cm.Message.EndID.Uint64() >= stateSyncID -} - -// EncodeAbi contains logic for encoding arbitrary data into ABI format -func (cm *CommitmentMessageSigned) EncodeAbi() ([]byte, error) { - blsVerificationPart, err := precompiled.BlsVerificationABIType.Encode( - [2]interface{}{cm.PublicKeys, cm.AggSignature.Bitmap}) - if err != nil { - return nil, err - } - - commit := &contractsapi.CommitStateReceiverFn{ - Commitment: cm.Message, - Signature: cm.AggSignature.AggregatedSignature, - Bitmap: blsVerificationPart, - } - - return commit.EncodeAbi() -} - -// DecodeAbi contains logic for decoding given ABI data -func (cm *CommitmentMessageSigned) DecodeAbi(txData []byte) error { - if len(txData) < abiMethodIDLength { - return fmt.Errorf("invalid commitment data, len = %d", len(txData)) - } - - commit := contractsapi.CommitStateReceiverFn{} - - err := commit.DecodeAbi(txData) - if err != nil { - return err - } - - decoded, err := precompiled.BlsVerificationABIType.Decode(commit.Bitmap) - if err != nil { - return err - } - - blsMap, isOk := decoded.(map[string]interface{}) - if !isOk { - return fmt.Errorf("invalid commitment data. Bls verification part not in correct format") - } - - publicKeys, isOk := blsMap["0"].([][]byte) - if !isOk { - return fmt.Errorf("invalid commitment data. Could not find public keys part") - } - - bitmap, isOk := blsMap["1"].([]byte) - if !isOk { - return fmt.Errorf("invalid commitment data. Could not find bitmap part") - } - - *cm = CommitmentMessageSigned{ - Message: commit.Commitment, - AggSignature: Signature{ - AggregatedSignature: commit.Signature, - Bitmap: bitmap, - }, - PublicKeys: publicKeys, - } - - return nil -} +const abiMethodIDLength = 4 func decodeStateTransaction(txData []byte) (contractsapi.StateTransactionInput, error) { if len(txData) < abiMethodIDLength { @@ -169,9 +17,10 @@ func decodeStateTransaction(txData []byte) (contractsapi.StateTransactionInput, sig := txData[:abiMethodIDLength] var ( - commitFn contractsapi.CommitStateReceiverFn - commitEpochFn contractsapi.CommitEpochChildValidatorSetFn - obj contractsapi.StateTransactionInput + commitFn contractsapi.CommitStateReceiverFn + commitEpochFn contractsapi.CommitEpochValidatorSetFn + distributeRewardsFn contractsapi.DistributeRewardForRewardPoolFn + obj contractsapi.StateTransactionInput ) if bytes.Equal(sig, commitFn.Sig()) { @@ -179,7 +28,10 @@ func decodeStateTransaction(txData []byte) (contractsapi.StateTransactionInput, obj = &CommitmentMessageSigned{} } else if bytes.Equal(sig, commitEpochFn.Sig()) { // commit epoch - obj = &contractsapi.CommitEpochChildValidatorSetFn{} + obj = &contractsapi.CommitEpochValidatorSetFn{} + } else if bytes.Equal(sig, distributeRewardsFn.Sig()) { + // distribute rewards + obj = &contractsapi.DistributeRewardForRewardPoolFn{} } else { return nil, fmt.Errorf("unknown state transaction") } @@ -190,40 +42,3 @@ func decodeStateTransaction(txData []byte) (contractsapi.StateTransactionInput, return obj, nil } - -func getCommitmentMessageSignedTx(txs []*types.Transaction) (*CommitmentMessageSigned, error) { - var commitFn contractsapi.CommitStateReceiverFn - for _, tx := range txs { - // skip non state CommitmentMessageSigned transactions - if tx.Type != types.StateTx || - len(tx.Input) < abiMethodIDLength || - !bytes.Equal(tx.Input[:abiMethodIDLength], commitFn.Sig()) { - continue - } - - obj := &CommitmentMessageSigned{} - - if err := obj.DecodeAbi(tx.Input); err != nil { - return nil, fmt.Errorf("get commitment message signed tx error: %w", err) - } - - return obj, nil - } - - return nil, nil -} - -func createMerkleTree(stateSyncEvents []*contractsapi.StateSyncedEvent) (*merkle.MerkleTree, error) { - ssh := make([][]byte, len(stateSyncEvents)) - - for i, sse := range stateSyncEvents { - data, err := sse.EncodeAbi() - if err != nil { - return nil, err - } - - ssh[i] = data - } - - return merkle.NewMerkleTree(ssh) -} diff --git a/consensus/polybft/state_transaction_test.go b/consensus/polybft/state_transaction_test.go index 89407db5ed..78129342e9 100644 --- a/consensus/polybft/state_transaction_test.go +++ b/consensus/polybft/state_transaction_test.go @@ -13,171 +13,6 @@ import ( "github.com/umbracle/ethgo/abi" ) -func newTestCommitmentSigned(root types.Hash, startID, endID int64) *CommitmentMessageSigned { - return &CommitmentMessageSigned{ - Message: &contractsapi.StateSyncCommitment{ - StartID: big.NewInt(startID), - EndID: big.NewInt(endID), - Root: root, - }, - AggSignature: Signature{}, - PublicKeys: [][]byte{}, - } -} - -func TestCommitmentMessage_Hash(t *testing.T) { - t.Parallel() - - const ( - eventsCount = 10 - ) - - stateSyncEvents := generateStateSyncEvents(t, eventsCount, 0) - - trie1, err := createMerkleTree(stateSyncEvents) - require.NoError(t, err) - - trie2, err := createMerkleTree(stateSyncEvents[0 : len(stateSyncEvents)-1]) - require.NoError(t, err) - - commitmentMessage1 := newTestCommitmentSigned(trie1.Hash(), 2, 8) - commitmentMessage2 := newTestCommitmentSigned(trie1.Hash(), 2, 8) - commitmentMessage3 := newTestCommitmentSigned(trie1.Hash(), 6, 10) - commitmentMessage4 := newTestCommitmentSigned(trie2.Hash(), 2, 8) - - hash1, err := commitmentMessage1.Hash() - require.NoError(t, err) - hash2, err := commitmentMessage2.Hash() - require.NoError(t, err) - hash3, err := commitmentMessage3.Hash() - require.NoError(t, err) - hash4, err := commitmentMessage4.Hash() - require.NoError(t, err) - - require.Equal(t, hash1, hash2) - require.NotEqual(t, hash1, hash3) - require.NotEqual(t, hash1, hash4) - require.NotEqual(t, hash3, hash4) -} - -func TestCommitmentMessage_ToRegisterCommitmentInputData(t *testing.T) { - t.Parallel() - - const epoch, eventsCount = uint64(100), 11 - pendingCommitment, _, _ := buildCommitmentAndStateSyncs(t, eventsCount, epoch, uint64(2)) - expectedSignedCommitmentMsg := &CommitmentMessageSigned{ - Message: pendingCommitment.StateSyncCommitment, - AggSignature: Signature{ - Bitmap: []byte{5, 1}, - AggregatedSignature: []byte{1, 1}, - }, - PublicKeys: [][]byte{{0, 1}, {2, 3}, {4, 5}}, - } - inputData, err := expectedSignedCommitmentMsg.EncodeAbi() - require.NoError(t, err) - require.NotEmpty(t, inputData) - - var actualSignedCommitmentMsg CommitmentMessageSigned - - require.NoError(t, actualSignedCommitmentMsg.DecodeAbi(inputData)) - require.NoError(t, err) - require.Equal(t, *expectedSignedCommitmentMsg.Message, *actualSignedCommitmentMsg.Message) - require.Equal(t, expectedSignedCommitmentMsg.AggSignature, actualSignedCommitmentMsg.AggSignature) -} - -func TestCommitmentMessage_VerifyProof(t *testing.T) { - t.Parallel() - - const epoch, eventsCount = uint64(100), 11 - commitment, commitmentSigned, stateSyncs := buildCommitmentAndStateSyncs(t, eventsCount, epoch, 0) - require.Equal(t, uint64(10), commitment.EndID.Sub(commitment.EndID, commitment.StartID).Uint64()) - - for _, stateSync := range stateSyncs { - leaf, err := stateSync.EncodeAbi() - require.NoError(t, err) - - proof, err := commitment.MerkleTree.GenerateProof(leaf) - require.NoError(t, err) - - execute := &contractsapi.ExecuteStateReceiverFn{ - Proof: proof, - Obj: (*contractsapi.StateSync)(stateSync), - } - - inputData, err := execute.EncodeAbi() - require.NoError(t, err) - - executionStateSync := &contractsapi.ExecuteStateReceiverFn{} - require.NoError(t, executionStateSync.DecodeAbi(inputData)) - require.Equal(t, stateSync.ID.Uint64(), executionStateSync.Obj.ID.Uint64()) - require.Equal(t, stateSync.Sender, executionStateSync.Obj.Sender) - require.Equal(t, stateSync.Receiver, executionStateSync.Obj.Receiver) - require.Equal(t, stateSync.Data, executionStateSync.Obj.Data) - require.Equal(t, proof, executionStateSync.Proof) - - err = commitmentSigned.VerifyStateSyncProof(executionStateSync.Proof, - (*contractsapi.StateSyncedEvent)(executionStateSync.Obj)) - require.NoError(t, err) - } -} - -func TestCommitmentMessage_VerifyProof_NoStateSyncsInCommitment(t *testing.T) { - t.Parallel() - - commitment := &CommitmentMessageSigned{Message: &contractsapi.StateSyncCommitment{StartID: big.NewInt(1), EndID: big.NewInt(10)}} - err := commitment.VerifyStateSyncProof([]types.Hash{}, nil) - assert.ErrorContains(t, err, "no state sync event") -} - -func TestCommitmentMessage_VerifyProof_StateSyncHashNotEqualToProof(t *testing.T) { - t.Parallel() - - const ( - fromIndex = 0 - toIndex = 4 - ) - - stateSyncs := generateStateSyncEvents(t, 5, 0) - tree, err := createMerkleTree(stateSyncs) - require.NoError(t, err) - - leaf, err := stateSyncs[0].EncodeAbi() - require.NoError(t, err) - - proof, err := tree.GenerateProof(leaf) - require.NoError(t, err) - - commitment := &CommitmentMessageSigned{ - Message: &contractsapi.StateSyncCommitment{ - StartID: big.NewInt(fromIndex), - EndID: big.NewInt(toIndex), - Root: tree.Hash(), - }, - } - - assert.ErrorContains(t, commitment.VerifyStateSyncProof(proof, stateSyncs[4]), "not a member of merkle tree") -} - -func buildCommitmentAndStateSyncs(t *testing.T, stateSyncsCount int, - epoch, startIdx uint64) (*PendingCommitment, *CommitmentMessageSigned, []*contractsapi.StateSyncedEvent) { - t.Helper() - - stateSyncEvents := generateStateSyncEvents(t, stateSyncsCount, startIdx) - commitment, err := NewPendingCommitment(epoch, stateSyncEvents) - require.NoError(t, err) - - commitmentSigned := &CommitmentMessageSigned{ - Message: commitment.StateSyncCommitment, - AggSignature: Signature{ - AggregatedSignature: []byte{}, - Bitmap: []byte{}, - }, - PublicKeys: [][]byte{}, - } - - return commitment, commitmentSigned, stateSyncEvents -} - func TestStateTransaction_Signature(t *testing.T) { t.Parallel() @@ -186,8 +21,8 @@ func TestStateTransaction_Signature(t *testing.T) { sig string }{ { - contractsapi.ChildValidatorSet.Abi.GetMethod("commitEpoch"), - "410899c9", + contractsapi.ValidatorSet.Abi.GetMethod("commitEpoch"), + "0f50287c", }, } for _, c := range cases { @@ -200,18 +35,13 @@ func TestStateTransaction_Encoding(t *testing.T) { t.Parallel() cases := []contractsapi.StateTransactionInput{ - &contractsapi.CommitEpochChildValidatorSetFn{ + &contractsapi.CommitEpochValidatorSetFn{ ID: big.NewInt(1), Epoch: &contractsapi.Epoch{ StartBlock: big.NewInt(1), EndBlock: big.NewInt(10), EpochRoot: types.Hash{}, }, - Uptime: &contractsapi.Uptime{ - EpochID: big.NewInt(1), - TotalBlocks: big.NewInt(10), - UptimeData: []*contractsapi.UptimeData{}, - }, }, } diff --git a/consensus/polybft/statesyncrelayer/state_sync_relayer.go b/consensus/polybft/statesyncrelayer/state_sync_relayer.go index e1c0cc33b8..26ca56bce2 100644 --- a/consensus/polybft/statesyncrelayer/state_sync_relayer.go +++ b/consensus/polybft/statesyncrelayer/state_sync_relayer.go @@ -38,7 +38,7 @@ func sanitizeRPCEndpoint(rpcEndpoint string) string { if err == nil { rpcEndpoint = fmt.Sprintf("http://%s:%s", "127.0.0.1", port) } else { - rpcEndpoint = "http://127.0.0.1:8545" + rpcEndpoint = txrelayer.DefaultRPCAddress } } @@ -196,11 +196,10 @@ func (r *StateSyncRelayer) executeStateSync(proof *types.Proof) error { // execute the state sync txn := ðgo.Transaction{ - From: r.key.Address(), - To: (*ethgo.Address)(&contracts.StateReceiverContract), - GasPrice: 0, - Gas: types.StateTransactionGasLimit, - Input: input, + From: r.key.Address(), + To: (*ethgo.Address)(&contracts.StateReceiverContract), + Gas: types.StateTransactionGasLimit, + Input: input, } receipt, err := r.txRelayer.SendTransaction(txn, r.key) diff --git a/consensus/polybft/statesyncrelayer/state_sync_relayer_test.go b/consensus/polybft/statesyncrelayer/state_sync_relayer_test.go index e2a2bc26f1..e523bb0b40 100644 --- a/consensus/polybft/statesyncrelayer/state_sync_relayer_test.go +++ b/consensus/polybft/statesyncrelayer/state_sync_relayer_test.go @@ -5,14 +5,18 @@ import ( "testing" "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/jsonrpc" "github.com/umbracle/ethgo/wallet" ) +var _ txrelayer.TxRelayer = (*txRelayerMock)(nil) + type txRelayerMock struct { mock.Mock } @@ -35,6 +39,10 @@ func (t *txRelayerMock) SendTransactionLocal(txn *ethgo.Transaction) (*ethgo.Rec return nil, args.Error(1) } +func (t *txRelayerMock) Client() *jsonrpc.Client { + return nil +} + func Test_executeStateSync(t *testing.T) { t.Parallel() @@ -93,7 +101,7 @@ func Test_sanitizeRPCEndpoint(t *testing.T) { { "empty endpoint", "", - "http://127.0.0.1:8545", + txrelayer.DefaultRPCAddress, }, } @@ -115,7 +123,7 @@ func TestStateSyncRelayer_Stop(t *testing.T) { key, err := wallet.GenerateKey() require.NoError(t, err) - r := NewRelayer("test-chain-1", "http://127.0.0.1:8545", ethgo.Address(contracts.StateReceiverContract), 0, hclog.NewNullLogger(), key) + r := NewRelayer("test-chain-1", txrelayer.DefaultRPCAddress, ethgo.Address(contracts.StateReceiverContract), 0, hclog.NewNullLogger(), key) require.NotPanics(t, func() { r.Stop() }) } diff --git a/consensus/polybft/system_state.go b/consensus/polybft/system_state.go index f4dfbee5e8..451b13adbd 100644 --- a/consensus/polybft/system_state.go +++ b/consensus/polybft/system_state.go @@ -1,12 +1,10 @@ package polybft import ( - "encoding/json" "fmt" "math/big" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" "github.com/0xPolygon/polygon-edge/types" "github.com/umbracle/ethgo" "github.com/umbracle/ethgo/contract" @@ -17,16 +15,13 @@ import ( type ValidatorInfo struct { Address ethgo.Address Stake *big.Int - TotalStake *big.Int - Commission *big.Int WithdrawableRewards *big.Int - Active bool + IsActive bool + IsWhitelisted bool } // SystemState is an interface to interact with the consensus system contracts in the chain type SystemState interface { - // GetValidatorSet retrieves current validator set from the smart contract - GetValidatorSet() (AccountSet, error) // GetEpoch retrieves current epoch number from the smart contract GetEpoch() (uint64, error) // GetNextCommittedIndex retrieves next committed bridge state sync index @@ -46,7 +41,7 @@ func NewSystemState(valSetAddr types.Address, stateRcvAddr types.Address, provid s := &SystemStateImpl{} s.validatorContract = contract.NewContract( ethgo.Address(valSetAddr), - contractsapi.ChildValidatorSet.Abi, contract.WithProvider(provider), + contractsapi.ValidatorSet.Abi, contract.WithProvider(provider), ) s.sidechainBridgeContract = contract.NewContract( ethgo.Address(stateRcvAddr), @@ -57,71 +52,6 @@ func NewSystemState(valSetAddr types.Address, stateRcvAddr types.Address, provid return s } -// GetValidatorSet retrieves current validator set from the smart contract -func (s *SystemStateImpl) GetValidatorSet() (AccountSet, error) { - output, err := s.validatorContract.Call("getCurrentValidatorSet", ethgo.Latest) - if err != nil { - return nil, err - } - - res := AccountSet{} - - addresses, isOk := output["0"].([]ethgo.Address) - if !isOk { - return nil, fmt.Errorf("failed to decode addresses of the current validator set") - } - - queryValidator := func(addr ethgo.Address) (*ValidatorMetadata, error) { - output, err := s.validatorContract.Call("getValidator", ethgo.Latest, addr) - if err != nil { - return nil, fmt.Errorf("failed to call getValidator function: %w", err) - } - - blsKey, ok := output["blsKey"].([4]*big.Int) - if !ok { - return nil, fmt.Errorf("failed to decode blskey") - } - - pubKey, err := bls.UnmarshalPublicKeyFromBigInt(blsKey) - if err != nil { - return nil, fmt.Errorf("failed to unmarshal BLS public key: %w", err) - } - - totalStake, ok := output["totalStake"].(*big.Int) - if !ok { - return nil, fmt.Errorf("failed to decode total stake") - } - - isActive, ok := output["active"].(bool) - if !ok { - return nil, fmt.Errorf("failed to decode active field") - } - - return &ValidatorMetadata{ - Address: types.Address(addr), - BlsKey: pubKey, - VotingPower: new(big.Int).Set(totalStake), - IsActive: isActive, - }, nil - } - - for _, addr := range addresses { - val, err := queryValidator(addr) - if err != nil { - return nil, err - } - - // filter out non active validators - if !val.IsActive { - continue - } - - res = append(res, val) - } - - return res, nil -} - // GetEpoch retrieves current epoch number from the smart contract func (s *SystemStateImpl) GetEpoch() (uint64, error) { rawResult, err := s.validatorContract.Call("currentEpochId", ethgo.Latest) @@ -151,23 +81,3 @@ func (s *SystemStateImpl) GetNextCommittedIndex() (uint64, error) { return nextCommittedIndex.Uint64() + 1, nil } - -func buildLogsFromReceipts(entry []*types.Receipt, header *types.Header) []*types.Log { - var logs []*types.Log - - for _, taskReceipt := range entry { - for _, taskLog := range taskReceipt.Logs { - log := new(types.Log) - *log = *taskLog - - data := map[string]interface{}{ - "Hash": header.Hash, - "Number": header.Number, - } - log.Data, _ = json.Marshal(&data) - logs = append(logs, log) - } - } - - return logs -} diff --git a/consensus/polybft/system_state_test.go b/consensus/polybft/system_state_test.go index 46001d1c48..04dc1cd615 100644 --- a/consensus/polybft/system_state_test.go +++ b/consensus/polybft/system_state_test.go @@ -2,7 +2,6 @@ package polybft import ( "encoding/hex" - "encoding/json" "math/big" "testing" @@ -20,71 +19,6 @@ import ( "github.com/umbracle/ethgo/testutil" ) -func TestSystemState_GetValidatorSet(t *testing.T) { - t.Parallel() - - cc := &testutil.Contract{} - cc.AddCallback(func() string { - return ` - - function getCurrentValidatorSet() public returns (address[] memory) { - address[] memory addresses = new address[](1); - addresses[0] = address(1); - return addresses; - } - - function getValidator( - address validator - ) - external - view - returns ( - uint256[4] memory blsKey, - uint256 stake, - uint256 totalStake, - uint256 commission, - uint256 withdrawableRewards, - bool active - ) - { - blsKey = [ - 1708568697487735112380375954529256823287318886168633341382922712646533763844, - 14713639476280042449606484361428781226013866637570951139712205035697871856089, - 16798350082249088544573448433070681576641749462807627179536437108134609634615, - 21427200503135995176566340351867145775962083994845221446131416289459495591422 - ]; - stake = 10; - totalStake = 15; - commission = 20; - withdrawableRewards = 30; - active = true; - } - ` - }) - - solcContract, err := cc.Compile() - assert.NoError(t, err) - - bin, err := hex.DecodeString(solcContract.Bin) - assert.NoError(t, err) - - transition := newTestTransition(t, nil) - - // deploy a contract - result := transition.Create2(types.Address{}, bin, big.NewInt(0), 1000000000) - assert.NoError(t, result.Err) - - provider := &stateProvider{ - transition: transition, - } - - st := NewSystemState(result.Address, contracts.StateReceiverContract, provider) - validators, err := st.GetValidatorSet() - assert.NoError(t, err) - assert.Equal(t, types.Address(ethgo.HexToAddress("1")), validators[0].Address) - assert.Equal(t, new(big.Int).SetUint64(15), validators[0].VotingPower) -} - func TestSystemState_GetNextCommittedIndex(t *testing.T) { t.Parallel() @@ -199,6 +133,9 @@ func newTestTransition(t *testing.T, alloc map[types.Address]*chain.GenesisAccou ex := state.NewExecutor(&chain.Params{ Forks: chain.AllForksEnabled, + BurnContract: map[uint64]types.Address{ + 0: types.ZeroAddress, + }, }, st, hclog.NewNullLogger()) rootHash, err := ex.WriteGenesis(alloc, types.Hash{}) @@ -219,71 +156,3 @@ func newTestTransition(t *testing.T, alloc map[types.Address]*chain.GenesisAccou return transition } - -func Test_buildLogsFromReceipts(t *testing.T) { - t.Parallel() - - defaultHeader := &types.Header{ - Number: 100, - } - - type args struct { - entry []*types.Receipt - header *types.Header - } - - data := map[string]interface{}{ - "Hash": defaultHeader.Hash, - "Number": defaultHeader.Number, - } - - dataArray, err := json.Marshal(&data) - require.NoError(t, err) - - tests := []struct { - name string - args args - want []*types.Log - }{ - { - name: "no entries provided", - }, - { - name: "successfully created logs", - args: args{ - entry: []*types.Receipt{ - { - Logs: []*types.Log{ - { - Address: types.BytesToAddress([]byte{0, 1}), - Topics: nil, - Data: dataArray, - }, - }, - }, - }, - header: defaultHeader, - }, - want: []*types.Log{ - { - Address: types.BytesToAddress([]byte{0, 1}), - Topics: nil, - Data: dataArray, - }, - }, - }, - } - - for _, tt := range tests { - tt := tt - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - assert.EqualValuesf(t, - tt.want, - buildLogsFromReceipts(tt.args.entry, tt.args.header), - "buildLogsFromReceipts(%v, %v)", tt.args.entry, tt.args.header, - ) - }) - } -} diff --git a/consensus/polybft/validator/genesis_validator.go b/consensus/polybft/validator/genesis_validator.go new file mode 100644 index 0000000000..1ffa9a41ed --- /dev/null +++ b/consensus/polybft/validator/genesis_validator.go @@ -0,0 +1,97 @@ +package validator + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + + bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/types" +) + +// GenesisValidator represents public information about validator accounts which are the part of genesis +type GenesisValidator struct { + Address types.Address + BlsPrivateKey *bls.PrivateKey + BlsKey string + Balance *big.Int + Stake *big.Int + MultiAddr string +} + +type genesisValidatorRaw struct { + Address types.Address `json:"address"` + BlsKey string `json:"blsKey"` + Balance *string `json:"balance"` + Stake *string `json:"stake"` + MultiAddr string `json:"multiAddr"` +} + +func (v *GenesisValidator) MarshalJSON() ([]byte, error) { + raw := &genesisValidatorRaw{Address: v.Address, BlsKey: v.BlsKey, MultiAddr: v.MultiAddr} + raw.Balance = types.EncodeBigInt(v.Balance) + raw.Stake = types.EncodeBigInt(v.Stake) + + return json.Marshal(raw) +} + +func (v *GenesisValidator) UnmarshalJSON(data []byte) error { + var ( + raw genesisValidatorRaw + err error + ) + + if err = json.Unmarshal(data, &raw); err != nil { + return err + } + + v.Address = raw.Address + v.BlsKey = raw.BlsKey + v.MultiAddr = raw.MultiAddr + + v.Balance, err = types.ParseUint256orHex(raw.Balance) + if err != nil { + return err + } + + v.Stake, err = types.ParseUint256orHex(raw.Stake) + if err != nil { + return err + } + + return nil +} + +// UnmarshalBLSPublicKey unmarshals the hex encoded BLS public key +func (v *GenesisValidator) UnmarshalBLSPublicKey() (*bls.PublicKey, error) { + decoded, err := hex.DecodeString(v.BlsKey) + if err != nil { + return nil, err + } + + return bls.UnmarshalPublicKey(decoded) +} + +// ToValidatorMetadata creates ValidatorMetadata instance +func (v *GenesisValidator) ToValidatorMetadata() (*ValidatorMetadata, error) { + blsKey, err := v.UnmarshalBLSPublicKey() + if err != nil { + return nil, err + } + + metadata := &ValidatorMetadata{ + Address: v.Address, + BlsKey: blsKey, + VotingPower: new(big.Int).Set(v.Stake), + IsActive: true, + } + + return metadata, nil +} + +// String implements fmt.Stringer interface +func (v *GenesisValidator) String() string { + return fmt.Sprintf("Address=%s; Balance=%d; Stake=%d; P2P Multi addr=%s; BLS Key=%s;", + v.Address, v.Balance, v.Stake, v.MultiAddr, v.BlsKey) +} diff --git a/consensus/polybft/validator/test_helpers.go b/consensus/polybft/validator/test_helpers.go new file mode 100644 index 0000000000..8a6c719d21 --- /dev/null +++ b/consensus/polybft/validator/test_helpers.go @@ -0,0 +1,244 @@ +package validator + +import ( + "encoding/hex" + "fmt" + "math/big" + "sort" + "strconv" + "testing" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" + bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" + "github.com/0xPolygon/polygon-edge/types" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/require" +) + +type TestValidators struct { + Validators map[string]*TestValidator +} + +func NewTestValidators(tb testing.TB, validatorsCount int) *TestValidators { + tb.Helper() + + aliases := make([]string, validatorsCount) + for i := 0; i < validatorsCount; i++ { + aliases[i] = strconv.Itoa(i) + } + + return NewTestValidatorsWithAliases(tb, aliases) +} + +func NewTestValidatorsWithAliases(tb testing.TB, aliases []string, votingPowers ...[]uint64) *TestValidators { + tb.Helper() + + validators := map[string]*TestValidator{} + + for i, alias := range aliases { + votingPower := uint64(1) + if len(votingPowers) == 1 { + votingPower = votingPowers[0][i] + } + + validators[alias] = NewTestValidator(tb, alias, votingPower) + } + + return &TestValidators{Validators: validators} +} + +func (v *TestValidators) Create(t *testing.T, alias string, votingPower uint64) { + t.Helper() + + if _, ok := v.Validators[alias]; !ok { + v.Validators[alias] = NewTestValidator(t, alias, votingPower) + } +} + +func (v *TestValidators) IterAcct(aliases []string, handle func(t *TestValidator)) { + if len(aliases) == 0 { + // loop over the whole set + for k := range v.Validators { + aliases = append(aliases, k) + } + // sort the names since they get queried randomly + sort.Strings(aliases) + } + + for _, alias := range aliases { + handle(v.GetValidator(alias)) + } +} + +func (v *TestValidators) GetParamValidators(aliases ...string) (res []*GenesisValidator) { + v.IterAcct(aliases, func(t *TestValidator) { + res = append(res, t.ParamsValidator()) + }) + + return +} + +func (v *TestValidators) GetValidators(aliases ...string) (res []*TestValidator) { + v.IterAcct(aliases, func(t *TestValidator) { + res = append(res, t) + }) + + return +} + +func (v *TestValidators) GetPublicIdentities(aliases ...string) (res AccountSet) { + v.IterAcct(aliases, func(t *TestValidator) { + res = append(res, t.ValidatorMetadata()) + }) + + return +} + +func (v *TestValidators) GetPrivateIdentities(aliases ...string) (res []*wallet.Account) { + v.IterAcct(aliases, func(t *TestValidator) { + res = append(res, t.Account) + }) + + return +} + +func (v *TestValidators) GetValidator(alias string) *TestValidator { + vv, ok := v.Validators[alias] + if !ok { + panic(fmt.Sprintf("Validator %s does not exist", alias)) //nolint:gocritic + } + + return vv +} + +func (v *TestValidators) ToValidatorSet() ValidatorSet { + return NewValidatorSet(v.GetPublicIdentities(), hclog.NewNullLogger()) +} + +func (v *TestValidators) UpdateVotingPowers(votingPowersMap map[string]uint64) AccountSet { + if len(votingPowersMap) == 0 { + return AccountSet{} + } + + aliases := []string{} + for alias := range votingPowersMap { + aliases = append(aliases, alias) + } + + v.IterAcct(aliases, func(t *TestValidator) { + t.VotingPower = votingPowersMap[t.Alias] + }) + + return v.GetPublicIdentities(aliases...) +} + +type TestValidator struct { + Alias string + Account *wallet.Account + VotingPower uint64 +} + +func NewTestValidator(tb testing.TB, alias string, votingPower uint64) *TestValidator { + tb.Helper() + + return &TestValidator{ + Alias: alias, + VotingPower: votingPower, + Account: generateTestAccount(tb), + } +} + +func (v *TestValidator) Address() types.Address { + return types.Address(v.Account.Ecdsa.Address()) +} + +func (v *TestValidator) Key() *wallet.Key { + return wallet.NewKey(v.Account) +} + +func (v *TestValidator) ParamsValidator() *GenesisValidator { + bls := v.Account.Bls.PublicKey().Marshal() + + return &GenesisValidator{ + Address: v.Address(), + BlsKey: hex.EncodeToString(bls), + Balance: big.NewInt(1000), + Stake: big.NewInt(1000), + } +} + +func (v *TestValidator) ValidatorMetadata() *ValidatorMetadata { + return &ValidatorMetadata{ + Address: types.Address(v.Account.Ecdsa.Address()), + BlsKey: v.Account.Bls.PublicKey(), + VotingPower: new(big.Int).SetUint64(v.VotingPower), + } +} + +func (v *TestValidator) MustSign(hash, domain []byte) *bls.Signature { + signature, err := v.Account.Bls.Sign(hash, domain) + if err != nil { + panic(fmt.Sprintf("BUG: failed to sign: %v", err)) //nolint:gocritic + } + + return signature +} + +func generateTestAccount(tb testing.TB) *wallet.Account { + tb.Helper() + + acc, err := wallet.GenerateAccount() + require.NoError(tb, err) + + return acc +} + +// CreateValidatorSetDelta calculates ValidatorSetDelta based on the provided old and new validator sets +func CreateValidatorSetDelta(oldValidatorSet, newValidatorSet AccountSet) (*ValidatorSetDelta, error) { + var addedValidators, updatedValidators AccountSet + + oldValidatorSetMap := make(map[types.Address]*ValidatorMetadata) + removedValidators := map[types.Address]int{} + + for i, validator := range oldValidatorSet { + if (validator.Address != types.Address{}) { + removedValidators[validator.Address] = i + oldValidatorSetMap[validator.Address] = validator + } + } + + for _, newValidator := range newValidatorSet { + // Check if the validator is among both old and new validator set + oldValidator, validatorExists := oldValidatorSetMap[newValidator.Address] + if validatorExists { + if !oldValidator.EqualAddressAndBlsKey(newValidator) { + return nil, fmt.Errorf("validator '%s' found in both old and new validator set, but its BLS keys differ", + newValidator.Address.String()) + } + + // If it is, then discard it from removed validators... + delete(removedValidators, newValidator.Address) + + if !oldValidator.Equals(newValidator) { + updatedValidators = append(updatedValidators, newValidator) + } + } else { + // ...otherwise it is added + addedValidators = append(addedValidators, newValidator) + } + } + + removedValsBitmap := bitmap.Bitmap{} + for _, i := range removedValidators { + removedValsBitmap.Set(uint64(i)) + } + + delta := &ValidatorSetDelta{ + Added: addedValidators, + Updated: updatedValidators, + Removed: removedValsBitmap, + } + + return delta, nil +} diff --git a/consensus/polybft/validator_metadata.go b/consensus/polybft/validator/validator_metadata.go similarity index 99% rename from consensus/polybft/validator_metadata.go rename to consensus/polybft/validator/validator_metadata.go index 3b207a31cf..8baf12f8f9 100644 --- a/consensus/polybft/validator_metadata.go +++ b/consensus/polybft/validator/validator_metadata.go @@ -1,4 +1,4 @@ -package polybft +package validator import ( "bytes" diff --git a/consensus/polybft/validator_metadata_test.go b/consensus/polybft/validator/validator_metadata_test.go similarity index 87% rename from consensus/polybft/validator_metadata_test.go rename to consensus/polybft/validator/validator_metadata_test.go index 164a60958f..e6999a87f6 100644 --- a/consensus/polybft/validator_metadata_test.go +++ b/consensus/polybft/validator/validator_metadata_test.go @@ -1,6 +1,7 @@ -package polybft +package validator import ( + "crypto/rand" "math/big" "testing" @@ -11,10 +12,21 @@ import ( "github.com/stretchr/testify/require" ) +// generateRandomBytes generates byte array with random data of 32 bytes length +func generateRandomBytes(t *testing.T) (result []byte) { + t.Helper() + + result = make([]byte, types.HashLength) + _, err := rand.Reader.Read(result) + require.NoError(t, err, "Cannot generate random byte array content.") + + return +} + func TestValidatorMetadata_Equals(t *testing.T) { t.Parallel() - v := newTestValidator(t, "A", 10) + v := NewTestValidator(t, "A", 10) validatorAcc := v.ValidatorMetadata() // proper validator metadata instance doesn't equal to nil require.False(t, validatorAcc.Equals(nil)) @@ -29,7 +41,7 @@ func TestValidatorMetadata_Equals(t *testing.T) { func TestValidatorMetadata_EqualAddressAndBlsKey(t *testing.T) { t.Parallel() - v := newTestValidator(t, "A", 10) + v := NewTestValidator(t, "A", 10) validatorAcc := v.ValidatorMetadata() // proper validator metadata instance doesn't equal to nil require.False(t, validatorAcc.EqualAddressAndBlsKey(nil)) @@ -82,7 +94,7 @@ func TestAccountSet_IndexContainsAddressesAndContainsNodeId(t *testing.T) { const count = 10 dummy := types.Address{2, 3, 4} - validators := newTestValidators(t, count).getPublicIdentities() + validators := NewTestValidators(t, count).GetPublicIdentities() addresses := [count]types.Address{} for i, validator := range validators { @@ -195,12 +207,12 @@ func TestAccountSet_ApplyDelta(t *testing.T) { snapshot := AccountSet{} // Add a couple of validators to the snapshot => validators are present in the snapshot after applying such delta - vals := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + vals := NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) for _, step := range cc.steps { addedValidators := AccountSet{} if step.added != nil { - addedValidators = vals.getPublicIdentities(step.added...) + addedValidators = vals.GetPublicIdentities(step.added...) } delta := &ValidatorSetDelta{ Added: addedValidators, @@ -211,7 +223,7 @@ func TestAccountSet_ApplyDelta(t *testing.T) { } // update voting powers - delta.Updated = vals.updateVotingPowers(step.updated) + delta.Updated = vals.UpdateVotingPowers(step.updated) // apply delta var err error @@ -227,7 +239,7 @@ func TestAccountSet_ApplyDelta(t *testing.T) { // validate validator set require.Equal(t, len(step.expected), snapshot.Len()) for validatorAlias, votingPower := range step.expected { - v := vals.getValidator(validatorAlias).ValidatorMetadata() + v := vals.GetValidator(validatorAlias).ValidatorMetadata() require.True(t, snapshot.ContainsAddress(v.Address), "validator '%s' not found in snapshot", validatorAlias) require.Equal(t, new(big.Int).SetUint64(votingPower), v.VotingPower) } @@ -239,8 +251,8 @@ func TestAccountSet_ApplyDelta(t *testing.T) { func TestAccountSet_ApplyEmptyDelta(t *testing.T) { t.Parallel() - v := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) - validatorAccs := v.getPublicIdentities() + v := NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + validatorAccs := v.GetPublicIdentities() validators, err := validatorAccs.ApplyDelta(nil) require.NoError(t, err) require.Equal(t, validatorAccs, validators) @@ -252,8 +264,8 @@ func TestAccountSet_Hash(t *testing.T) { t.Run("Hash non-empty account set", func(t *testing.T) { t.Parallel() - v := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) - hash, err := v.getPublicIdentities().Hash() + v := NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + hash, err := v.GetPublicIdentities().Hash() require.NoError(t, err) require.NotEqual(t, types.ZeroHash, hash) }) diff --git a/consensus/polybft/validator_set.go b/consensus/polybft/validator/validator_set.go similarity index 84% rename from consensus/polybft/validator_set.go rename to consensus/polybft/validator/validator_set.go index ff8d893ab4..f552966729 100644 --- a/consensus/polybft/validator_set.go +++ b/consensus/polybft/validator/validator_set.go @@ -1,4 +1,4 @@ -package polybft +package validator import ( "math/big" @@ -19,8 +19,11 @@ type ValidatorSet interface { // Accounts returns the list of the ValidatorMetadata Accounts() AccountSet - // checks if submitted signers have reached quorum + // HasQuorum checks if submitted signers have reached quorum HasQuorum(signers map[types.Address]struct{}) bool + + // GetVotingPowers retrieves map: string(address) -> vp + GetVotingPowers() map[string]*big.Int } type validatorSet struct { @@ -80,6 +83,16 @@ func (vs validatorSet) HasQuorum(signers map[types.Address]struct{}) bool { return hasQuorum } +func (vs validatorSet) GetVotingPowers() map[string]*big.Int { + result := make(map[string]*big.Int, vs.Len()) + + for address, vp := range vs.votingPowerMap { + result[types.AddressToString(address)] = vp + } + + return result +} + func (vs validatorSet) Accounts() AccountSet { return vs.validators } @@ -92,6 +105,10 @@ func (vs validatorSet) Len() int { return vs.validators.Len() } +func (vs validatorSet) TotalVotingPower() big.Int { + return *vs.totalVotingPower +} + // getQuorumSize calculates quorum size as 2/3 super-majority of provided total voting power func getQuorumSize(totalVotingPower *big.Int) *big.Int { quorum := new(big.Int) diff --git a/consensus/polybft/validator/validator_set_delta.go b/consensus/polybft/validator/validator_set_delta.go new file mode 100644 index 0000000000..23e6f31a12 --- /dev/null +++ b/consensus/polybft/validator/validator_set_delta.go @@ -0,0 +1,144 @@ +package validator + +import ( + "bytes" + "fmt" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/bitmap" + "github.com/umbracle/fastrlp" +) + +// ValidatorSetDelta holds information about added and removed validators compared to the previous epoch +type ValidatorSetDelta struct { + // Added is the slice of added validators + Added AccountSet + // Updated is the slice of updated valiadtors + Updated AccountSet + // Removed is a bitmap of the validators removed from the set + Removed bitmap.Bitmap +} + +// Equals checks validator set delta equality +func (d *ValidatorSetDelta) Equals(other *ValidatorSetDelta) bool { + if other == nil { + return false + } + + return d.Added.Equals(other.Added) && + d.Updated.Equals(other.Updated) && + bytes.Equal(d.Removed, other.Removed) +} + +// MarshalRLPWith marshals ValidatorSetDelta to RLP format +func (d *ValidatorSetDelta) MarshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value { + vv := ar.NewArray() + addedValidatorsRaw := ar.NewArray() + updatedValidatorsRaw := ar.NewArray() + + for _, validatorAccount := range d.Added { + addedValidatorsRaw.Set(validatorAccount.MarshalRLPWith(ar)) + } + + for _, validatorAccount := range d.Updated { + updatedValidatorsRaw.Set(validatorAccount.MarshalRLPWith(ar)) + } + + vv.Set(addedValidatorsRaw) // added + vv.Set(updatedValidatorsRaw) // updated + vv.Set(ar.NewCopyBytes(d.Removed)) // removed + + return vv +} + +// UnmarshalRLPWith unmarshals ValidatorSetDelta from RLP format +func (d *ValidatorSetDelta) UnmarshalRLPWith(v *fastrlp.Value) error { + elems, err := v.GetElems() + if err != nil { + return err + } + + if len(elems) == 0 { + return nil + } else if num := len(elems); num != 3 { + return fmt.Errorf("incorrect elements count to decode validator set delta, expected 3 but found %d", num) + } + + // Validators (added) + { + validatorsRaw, err := elems[0].GetElems() + if err != nil { + return fmt.Errorf("array expected for added validators") + } + + d.Added, err = unmarshalValidators(validatorsRaw) + if err != nil { + return err + } + } + + // Validators (updated) + { + validatorsRaw, err := elems[1].GetElems() + if err != nil { + return fmt.Errorf("array expected for updated validators") + } + + d.Updated, err = unmarshalValidators(validatorsRaw) + if err != nil { + return err + } + } + + // Bitmap (removed) + { + dst, err := elems[2].GetBytes(nil) + if err != nil { + return err + } + + d.Removed = bitmap.Bitmap(dst) + } + + return nil +} + +// unmarshalValidators unmarshals RLP encoded validators and returns AccountSet instance +func unmarshalValidators(validatorsRaw []*fastrlp.Value) (AccountSet, error) { + if len(validatorsRaw) == 0 { + return nil, nil + } + + validators := make(AccountSet, len(validatorsRaw)) + + for i, validatorRaw := range validatorsRaw { + acc := &ValidatorMetadata{} + if err := acc.UnmarshalRLPWith(validatorRaw); err != nil { + return nil, err + } + + validators[i] = acc + } + + return validators, nil +} + +// IsEmpty returns indication whether delta is empty (namely added, updated slices and removed bitmap are empty) +func (d *ValidatorSetDelta) IsEmpty() bool { + return len(d.Added) == 0 && + len(d.Updated) == 0 && + d.Removed.Len() == 0 +} + +// Copy creates deep copy of ValidatorSetDelta +func (d *ValidatorSetDelta) Copy() *ValidatorSetDelta { + added := d.Added.Copy() + removed := make([]byte, len(d.Removed)) + copy(removed, d.Removed) + + return &ValidatorSetDelta{Added: added, Removed: removed} +} + +// fmt.Stringer interface implementation +func (d *ValidatorSetDelta) String() string { + return fmt.Sprintf("Added: \n%v Removed: %v\n Updated: \n%v", d.Added, d.Removed, d.Updated) +} diff --git a/consensus/polybft/validator/validator_set_delta_test.go b/consensus/polybft/validator/validator_set_delta_test.go new file mode 100644 index 0000000000..ca1911dc45 --- /dev/null +++ b/consensus/polybft/validator/validator_set_delta_test.go @@ -0,0 +1,237 @@ +package validator + +import ( + "crypto/rand" + "math/big" + "testing" + + bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" + "github.com/stretchr/testify/require" + "github.com/umbracle/fastrlp" +) + +func TestExtra_CreateValidatorSetDelta_BlsDiffer(t *testing.T) { + t.Parallel() + + vals := NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F"}) + oldValidatorSet := vals.GetPublicIdentities("A", "B", "C", "D") + + // change the public bls key of 'B' + newValidatorSet := vals.GetPublicIdentities("B", "E", "F") + privateKey, err := bls.GenerateBlsKey() + require.NoError(t, err) + + newValidatorSet[0].BlsKey = privateKey.PublicKey() + + _, err = CreateValidatorSetDelta(oldValidatorSet, newValidatorSet) + require.Error(t, err) +} + +func TestValidatorSetDelta_Copy(t *testing.T) { + t.Parallel() + + const ( + originalValidatorsCount = 10 + addedValidatorsCount = 2 + ) + + oldValidatorSet := NewTestValidators(t, originalValidatorsCount).GetPublicIdentities() + newValidatorSet := oldValidatorSet[:len(oldValidatorSet)-2] + originalDelta, err := CreateValidatorSetDelta(oldValidatorSet, newValidatorSet) + require.NoError(t, err) + require.NotNil(t, originalDelta) + require.Empty(t, originalDelta.Added) + + copiedDelta := originalDelta.Copy() + require.NotNil(t, copiedDelta) + require.NotSame(t, originalDelta, copiedDelta) + require.NotEqual(t, originalDelta, copiedDelta) + require.Empty(t, copiedDelta.Added) + require.Equal(t, copiedDelta.Removed.Len(), originalDelta.Removed.Len()) + + newValidators := NewTestValidators(t, addedValidatorsCount).GetPublicIdentities() + copiedDelta.Added = append(copiedDelta.Added, newValidators...) + require.Empty(t, originalDelta.Added) + require.Len(t, copiedDelta.Added, addedValidatorsCount) + require.Equal(t, copiedDelta.Removed.Len(), originalDelta.Removed.Len()) +} + +func TestValidatorSetDelta_UnmarshalRLPWith_NegativeCases(t *testing.T) { + t.Parallel() + + t.Run("Incorrect RLP value type provided", func(t *testing.T) { + t.Parallel() + + ar := &fastrlp.Arena{} + delta := &ValidatorSetDelta{} + require.ErrorContains(t, delta.UnmarshalRLPWith(ar.NewNull()), "value is not of type array") + }) + + t.Run("Empty RLP array provided", func(t *testing.T) { + t.Parallel() + + ar := &fastrlp.Arena{} + delta := &ValidatorSetDelta{} + require.NoError(t, delta.UnmarshalRLPWith(ar.NewArray())) + }) + + t.Run("Incorrect RLP array size", func(t *testing.T) { + t.Parallel() + + ar := &fastrlp.Arena{} + deltaMarshalled := ar.NewArray() + deltaMarshalled.Set(ar.NewBytes([]byte{0x59})) + deltaMarshalled.Set(ar.NewBytes([]byte{0x33})) + deltaMarshalled.Set(ar.NewBytes([]byte{0x26})) + deltaMarshalled.Set(ar.NewBytes([]byte{0x74})) + delta := &ValidatorSetDelta{} + require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "incorrect elements count to decode validator set delta, expected 3 but found 4") + }) + + t.Run("Incorrect RLP value type for Added field", func(t *testing.T) { + t.Parallel() + + ar := &fastrlp.Arena{} + deltaMarshalled := ar.NewArray() + deltaMarshalled.Set(ar.NewBytes([]byte{0x59})) + deltaMarshalled.Set(ar.NewBytes([]byte{0x33})) + deltaMarshalled.Set(ar.NewBytes([]byte{0x27})) + delta := &ValidatorSetDelta{} + require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "array expected for added validators") + }) + + t.Run("Incorrect RLP value type for ValidatorMetadata in Added field", func(t *testing.T) { + t.Parallel() + + ar := &fastrlp.Arena{} + deltaMarshalled := ar.NewArray() + addedArray := ar.NewArray() + addedArray.Set(ar.NewNull()) + deltaMarshalled.Set(addedArray) + deltaMarshalled.Set(ar.NewNullArray()) + deltaMarshalled.Set(ar.NewNull()) + delta := &ValidatorSetDelta{} + require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "value is not of type array") + }) + + t.Run("Incorrect RLP value type for Removed field", func(t *testing.T) { + t.Parallel() + + ar := &fastrlp.Arena{} + deltaMarshalled := ar.NewArray() + addedValidators := NewTestValidators(t, 3).GetPublicIdentities() + addedArray := ar.NewArray() + updatedArray := ar.NewArray() + for _, validator := range addedValidators { + addedArray.Set(validator.MarshalRLPWith(ar)) + } + for _, validator := range addedValidators { + votingPower, err := rand.Int(rand.Reader, big.NewInt(100)) + require.NoError(t, err) + + validator.VotingPower = new(big.Int).Set(votingPower) + updatedArray.Set(validator.MarshalRLPWith(ar)) + } + deltaMarshalled.Set(addedArray) + deltaMarshalled.Set(updatedArray) + deltaMarshalled.Set(ar.NewNull()) + delta := &ValidatorSetDelta{} + require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "value is not of type bytes") + }) + + t.Run("Incorrect RLP value type for Updated field", func(t *testing.T) { + t.Parallel() + + ar := &fastrlp.Arena{} + deltaMarshalled := ar.NewArray() + deltaMarshalled.Set(ar.NewArray()) + deltaMarshalled.Set(ar.NewBytes([]byte{0x33})) + deltaMarshalled.Set(ar.NewNull()) + delta := &ValidatorSetDelta{} + require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "array expected for updated validators") + }) + + t.Run("Incorrect RLP value type for ValidatorMetadata in Updated field", func(t *testing.T) { + t.Parallel() + + ar := &fastrlp.Arena{} + deltaMarshalled := ar.NewArray() + updatedArray := ar.NewArray() + updatedArray.Set(ar.NewNull()) + deltaMarshalled.Set(ar.NewArray()) + deltaMarshalled.Set(updatedArray) + deltaMarshalled.Set(ar.NewNull()) + delta := &ValidatorSetDelta{} + require.ErrorContains(t, delta.UnmarshalRLPWith(deltaMarshalled), "value is not of type array") + }) +} + +func TestExtra_CreateValidatorSetDelta_Cases(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + oldSet []string + newSet []string + added []string + updated []string + removed []uint64 + }{ + { + "Simple", + []string{"A", "B", "C", "E", "F"}, + []string{"B", "E", "H"}, + []string{"H"}, + []string{"B", "E"}, + []uint64{0, 2, 4}, + }, + } + + for _, c := range cases { + c := c + t.Run(c.name, func(t *testing.T) { + t.Parallel() + + vals := NewTestValidatorsWithAliases(t, []string{}) + + for _, name := range c.oldSet { + vals.Create(t, name, 1) + } + for _, name := range c.newSet { + vals.Create(t, name, 1) + } + + oldValidatorSet := vals.GetPublicIdentities(c.oldSet...) + // update voting power to random value + maxVotingPower := big.NewInt(100) + for _, name := range c.updated { + v := vals.GetValidator(name) + vp, err := rand.Int(rand.Reader, maxVotingPower) + require.NoError(t, err) + // make sure generated voting power is different than the original one + v.VotingPower += vp.Uint64() + 1 + } + newValidatorSet := vals.GetPublicIdentities(c.newSet...) + + delta, err := CreateValidatorSetDelta(oldValidatorSet, newValidatorSet) + require.NoError(t, err) + + // added validators + require.Len(t, delta.Added, len(c.added)) + for i, name := range c.added { + require.Equal(t, delta.Added[i].Address, vals.GetValidator(name).Address()) + } + + // removed validators + for _, i := range c.removed { + require.True(t, delta.Removed.IsSet(i)) + } + + // updated validators + require.Len(t, delta.Updated, len(c.updated)) + for i, name := range c.updated { + require.Equal(t, delta.Updated[i].Address, vals.GetValidator(name).Address()) + } + }) + } +} diff --git a/consensus/polybft/validator_set_test.go b/consensus/polybft/validator/validator_set_test.go similarity index 79% rename from consensus/polybft/validator_set_test.go rename to consensus/polybft/validator/validator_set_test.go index f7faa5a678..01778e7e29 100644 --- a/consensus/polybft/validator_set_test.go +++ b/consensus/polybft/validator/validator_set_test.go @@ -1,4 +1,4 @@ -package polybft +package validator import ( "math/big" @@ -12,12 +12,12 @@ func TestValidatorSet_HasQuorum(t *testing.T) { t.Parallel() // enough signers for quorum (2/3 super-majority of validators are signers) - validators := newTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F", "G"}) - vs := validators.toValidatorSet() + validators := NewTestValidatorsWithAliases(t, []string{"A", "B", "C", "D", "E", "F", "G"}) + vs := validators.ToValidatorSet() signers := make(map[types.Address]struct{}) - validators.iterAcct([]string{"A", "B", "C", "D", "E"}, func(v *testValidator) { + validators.IterAcct([]string{"A", "B", "C", "D", "E"}, func(v *TestValidator) { signers[v.Address()] = struct{}{} }) @@ -26,7 +26,7 @@ func TestValidatorSet_HasQuorum(t *testing.T) { // not enough signers for quorum (less than 2/3 super-majority of validators are signers) signers = make(map[types.Address]struct{}) - validators.iterAcct([]string{"A", "B", "C", "D"}, func(v *testValidator) { + validators.IterAcct([]string{"A", "B", "C", "D"}, func(v *TestValidator) { signers[v.Address()] = struct{}{} }) require.False(t, vs.HasQuorum(signers)) diff --git a/consensus/polybft/validators_snapshot.go b/consensus/polybft/validators_snapshot.go index 84295e4ddf..d4ba539920 100644 --- a/consensus/polybft/validators_snapshot.go +++ b/consensus/polybft/validators_snapshot.go @@ -6,14 +6,15 @@ import ( "sync" "github.com/0xPolygon/polygon-edge/blockchain" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" ) type validatorSnapshot struct { - Epoch uint64 `json:"epoch"` - EpochEndingBlock uint64 `json:"epochEndingBlock"` - Snapshot AccountSet `json:"snapshot"` + Epoch uint64 `json:"epoch"` + EpochEndingBlock uint64 `json:"epochEndingBlock"` + Snapshot validator.AccountSet `json:"snapshot"` } func (vs *validatorSnapshot) copy() *validatorSnapshot { @@ -49,7 +50,8 @@ func newValidatorsSnapshotCache( // GetSnapshot tries to retrieve the most recent cached snapshot (if any) and // applies pending validator set deltas to it. // Otherwise, it builds a snapshot from scratch and applies pending validator set deltas. -func (v *validatorsSnapshotCache) GetSnapshot(blockNumber uint64, parents []*types.Header) (AccountSet, error) { +func (v *validatorsSnapshotCache) GetSnapshot( + blockNumber uint64, parents []*types.Header) (validator.AccountSet, error) { v.lock.Lock() defer v.lock.Unlock() @@ -178,12 +180,12 @@ func (v *validatorsSnapshotCache) computeSnapshot( } var ( - snapshot AccountSet + snapshot validator.AccountSet snapshotEpoch uint64 ) if existingSnapshot == nil { - snapshot = AccountSet{} + snapshot = validator.AccountSet{} } else { snapshot = existingSnapshot.Snapshot snapshotEpoch = existingSnapshot.Epoch + 1 diff --git a/consensus/polybft/validators_snapshot_test.go b/consensus/polybft/validators_snapshot_test.go index f22b633d9d..e74d82c6b3 100644 --- a/consensus/polybft/validators_snapshot_test.go +++ b/consensus/polybft/validators_snapshot_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/assert" @@ -21,9 +22,9 @@ func TestValidatorsSnapshotCache_GetSnapshot_Build(t *testing.T) { epochSize = uint64(10) ) - allValidators := newTestValidators(t, totalValidators).getPublicIdentities() + allValidators := validator.NewTestValidators(t, totalValidators).GetPublicIdentities() - var oddValidators, evenValidators AccountSet + var oddValidators, evenValidators validator.AccountSet for i := 0; i < totalValidators; i++ { if i%2 == 0 { @@ -42,7 +43,7 @@ func TestValidatorsSnapshotCache_GetSnapshot_Build(t *testing.T) { var cases = []struct { blockNumber uint64 - expectedSnapshot AccountSet + expectedSnapshot validator.AccountSet validatorsOverlap bool parents []*types.Header }{ @@ -98,8 +99,8 @@ func TestValidatorsSnapshotCache_GetSnapshot_FetchFromCache(t *testing.T) { validatorSetSize = 5 ) - allValidators := newTestValidators(t, totalValidators).getPublicIdentities() - epochOneValidators := AccountSet{allValidators[0], allValidators[len(allValidators)-1]} + allValidators := validator.NewTestValidators(t, totalValidators).GetPublicIdentities() + epochOneValidators := validator.AccountSet{allValidators[0], allValidators[len(allValidators)-1]} epochTwoValidators := allValidators[1 : len(allValidators)-2] headersMap := &testHeadersMap{headersByNumber: make(map[uint64]*types.Header)} @@ -143,7 +144,7 @@ func TestValidatorsSnapshotCache_Cleanup(t *testing.T) { cache := &testValidatorsCache{ validatorsSnapshotCache: newValidatorsSnapshotCache(hclog.NewNullLogger(), newTestState(t), blockchainMock), } - snapshot := newTestValidators(t, 3).getPublicIdentities() + snapshot := validator.NewTestValidators(t, 3).GetPublicIdentities() maxEpoch := uint64(0) for i := uint64(0); i < validatorSnapshotLimit; i++ { @@ -191,7 +192,7 @@ func TestValidatorsSnapshotCache_ComputeSnapshot_UnknownBlock(t *testing.T) { epochSize = uint64(10) ) - allValidators := newTestValidators(t, totalValidators).getPublicIdentities() + allValidators := validator.NewTestValidators(t, totalValidators).GetPublicIdentities() headersMap := &testHeadersMap{} headersMap.addHeader(createValidatorDeltaHeader(t, 0, 0, nil, allValidators[:validatorSetSize])) headersMap.addHeader(createValidatorDeltaHeader(t, 1*epochSize, 1, allValidators[:validatorSetSize], allValidators[validatorSetSize:])) @@ -218,7 +219,7 @@ func TestValidatorsSnapshotCache_ComputeSnapshot_IncorrectExtra(t *testing.T) { epochSize = uint64(10) ) - allValidators := newTestValidators(t, totalValidators).getPublicIdentities() + allValidators := validator.NewTestValidators(t, totalValidators).GetPublicIdentities() headersMap := &testHeadersMap{} invalidHeader := createValidatorDeltaHeader(t, 1*epochSize, 1, allValidators[:validatorSetSize], allValidators[validatorSetSize:]) invalidHeader.ExtraData = []byte{0x2, 0x7} @@ -246,7 +247,7 @@ func TestValidatorsSnapshotCache_ComputeSnapshot_ApplyDeltaFail(t *testing.T) { epochSize = uint64(10) ) - allValidators := newTestValidators(t, totalValidators).getPublicIdentities() + allValidators := validator.NewTestValidators(t, totalValidators).GetPublicIdentities() headersMap := &testHeadersMap{} headersMap.addHeader(createValidatorDeltaHeader(t, 0, 0, nil, allValidators[:validatorSetSize])) headersMap.addHeader(createValidatorDeltaHeader(t, 1*epochSize, 1, nil, allValidators[:validatorSetSize])) @@ -264,7 +265,7 @@ func TestValidatorsSnapshotCache_ComputeSnapshot_ApplyDeltaFail(t *testing.T) { } func createHeaders(t *testing.T, headersMap *testHeadersMap, - fromBlock, toBlock, epoch uint64, oldValidators, newValidators AccountSet) { + fromBlock, toBlock, epoch uint64, oldValidators, newValidators validator.AccountSet) { t.Helper() headersMap.addHeader(createValidatorDeltaHeader(t, fromBlock, epoch-1, oldValidators, newValidators)) @@ -274,15 +275,15 @@ func createHeaders(t *testing.T, headersMap *testHeadersMap, } } -func createValidatorDeltaHeader(t *testing.T, blockNumber, epoch uint64, oldValidatorSet, newValidatorSet AccountSet) *types.Header { +func createValidatorDeltaHeader(t *testing.T, blockNumber, epoch uint64, oldValidatorSet, newValidatorSet validator.AccountSet) *types.Header { t.Helper() - delta, _ := createValidatorSetDelta(oldValidatorSet, newValidatorSet) + delta, _ := validator.CreateValidatorSetDelta(oldValidatorSet, newValidatorSet) extra := &Extra{Validators: delta, Checkpoint: &CheckpointData{EpochNumber: epoch}} return &types.Header{ Number: blockNumber, - ExtraData: append(make([]byte, ExtraVanity), extra.MarshalRLPTo(nil)...), + ExtraData: extra.MarshalRLPTo(nil), } } diff --git a/consensus/polybft/wallet/account.go b/consensus/polybft/wallet/account.go index 751bfb4938..b6c8600221 100644 --- a/consensus/polybft/wallet/account.go +++ b/consensus/polybft/wallet/account.go @@ -7,6 +7,7 @@ import ( bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" "github.com/0xPolygon/polygon-edge/secrets" + "github.com/0xPolygon/polygon-edge/types" "github.com/umbracle/ethgo/wallet" ) @@ -36,37 +37,52 @@ func GenerateAccount() (*Account, error) { // NewAccountFromSecret creates new account by using provided secretsManager func NewAccountFromSecret(secretsManager secrets.SecretsManager) (*Account, error) { - var ( - encodedKey []byte - err error - ) + ecdsaKey, err := GetEcdsaFromSecret(secretsManager) + if err != nil { + return nil, err + } + + blsKey, err := GetBlsFromSecret(secretsManager) + if err != nil { + return nil, err + } + + return &Account{Ecdsa: ecdsaKey, Bls: blsKey}, nil +} - // ECDSA - if encodedKey, err = secretsManager.GetSecret(secrets.ValidatorKey); err != nil { - return nil, fmt.Errorf("failed to read account data: %w", err) +// GetEcdsaFromSecret retrieves validator(ECDSA) key by using provided secretsManager +func GetEcdsaFromSecret(secretsManager secrets.SecretsManager) (*wallet.Key, error) { + encodedKey, err := secretsManager.GetSecret(secrets.ValidatorKey) + if err != nil { + return nil, fmt.Errorf("failed to retrieve ecdsa key: %w", err) } ecdsaRaw, err := hex.DecodeString(string(encodedKey)) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to retrieve ecdsa key: %w", err) } - ecdsaKey, err := wallet.NewWalletFromPrivKey(ecdsaRaw) + key, err := wallet.NewWalletFromPrivKey(ecdsaRaw) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to retrieve ecdsa key: %w", err) } - // BLS - if encodedKey, err = secretsManager.GetSecret(secrets.ValidatorBLSKey); err != nil { - return nil, fmt.Errorf("failed to read account data: %w", err) + return key, nil +} + +// GetBlsFromSecret retrieves BLS key by using provided secretsManager +func GetBlsFromSecret(secretsManager secrets.SecretsManager) (*bls.PrivateKey, error) { + encodedKey, err := secretsManager.GetSecret(secrets.ValidatorBLSKey) + if err != nil { + return nil, fmt.Errorf("failed to retrieve bls key: %w", err) } blsKey, err := bls.UnmarshalPrivateKey(encodedKey) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to retrieve bls key: %w", err) } - return &Account{Ecdsa: ecdsaKey, Bls: blsKey}, nil + return blsKey, nil } // Save persists ECDSA and BLS private keys to the SecretsManager @@ -101,3 +117,7 @@ func (a *Account) GetEcdsaPrivateKey() (*ecdsa.PrivateKey, error) { return wallet.ParsePrivateKey(ecdsaRaw) } + +func (a Account) Address() types.Address { + return types.Address(a.Ecdsa.Address()) +} diff --git a/contracts/system_addresses.go b/contracts/system_addresses.go index abd14886dd..1c6da159cf 100644 --- a/contracts/system_addresses.go +++ b/contracts/system_addresses.go @@ -9,16 +9,36 @@ var ( BLSContract = types.StringToAddress("0x102") // MerkleContract is an address of Merkle contract on the child chain MerkleContract = types.StringToAddress("0x103") + // RewardTokenContract is an address of reward token on child chain + RewardTokenContract = types.StringToAddress("0x104") + // RewardPoolContract is an address of RewardPoolContract contract on the child chain + RewardPoolContract = types.StringToAddress("0x105") // StateReceiverContract is an address of bridge contract on the child chain StateReceiverContract = types.StringToAddress("0x1001") // NativeERC20TokenContract is an address of bridge contract (used for transferring ERC20 native tokens on child chain) NativeERC20TokenContract = types.StringToAddress("0x1010") // L2StateSenderContract is an address of bridge contract to the rootchain L2StateSenderContract = types.StringToAddress("0x1002") + // ChildERC20Contract is an address of bridgable ERC20 token contract on the child chain ChildERC20Contract = types.StringToAddress("0x1003") // ChildERC20PredicateContract is an address of child ERC20 predicate contract on the child chain ChildERC20PredicateContract = types.StringToAddress("0x1004") + // ChildERC721Contract is an address of bridgable ERC721 token contract on the child chain + ChildERC721Contract = types.StringToAddress("0x1005") + // ChildERC721PredicateContract is an address of child ERC721 predicate contract on the child chain + ChildERC721PredicateContract = types.StringToAddress("0x1006") + // ChildERC1155Contract is an address of bridgable ERC1155 token contract on the child chain + ChildERC1155Contract = types.StringToAddress("0x1007") + // ChildERC1155PredicateContract is an address of child ERC1155 predicate contract on the child chain + ChildERC1155PredicateContract = types.StringToAddress("0x1008") + // RootMintableERC20PredicateContract is an address of mintable ERC20 predicate on the child chain + RootMintableERC20PredicateContract = types.StringToAddress("0x1009") + // RootMintableERC721PredicateContract is an address of mintable ERC721 predicate on the child chain + RootMintableERC721PredicateContract = types.StringToAddress("0x100a") + // RootMintableERC1155PredicateContract is an address of mintable ERC1155 predicate on the child chain + RootMintableERC1155PredicateContract = types.StringToAddress("0x100b") + // SystemCaller is address of account, used for system calls to smart contracts SystemCaller = types.StringToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") @@ -30,4 +50,14 @@ var ( ConsolePrecompile = types.StringToAddress("0x000000000000000000636F6e736F6c652e6c6f67") // AllowListContractsAddr is the address of the contract deployer allow list AllowListContractsAddr = types.StringToAddress("0x0200000000000000000000000000000000000000") + // BlockListContractsAddr is the address of the contract deployer block list + BlockListContractsAddr = types.StringToAddress("0x0300000000000000000000000000000000000000") + // AllowListTransactionsAddr is the address of the transactions allow list + AllowListTransactionsAddr = types.StringToAddress("0x0200000000000000000000000000000000000002") + // BlockListTransactionsAddr is the address of the transactions block list + BlockListTransactionsAddr = types.StringToAddress("0x0300000000000000000000000000000000000002") + // AllowListBridgeAddr is the address of the bridge allow list + AllowListBridgeAddr = types.StringToAddress("0x0200000000000000000000000000000000000004") + // BlockListBridgeAddr is the address of the bridge block list + BlockListBridgeAddr = types.StringToAddress("0x0300000000000000000000000000000000000004") ) diff --git a/core-contracts b/core-contracts index 622a936ffb..5a68054893 160000 --- a/core-contracts +++ b/core-contracts @@ -1 +1 @@ -Subproject commit 622a936ffb0539d21cb1519f20a8cea8ab9b28de +Subproject commit 5a68054893e8a9755645b11528221e3c68c2af29 diff --git a/crypto/crypto.go b/crypto/crypto.go index 30ecd13fa5..95421f13bc 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -147,10 +147,6 @@ func RecoverPubkey(signature, hash []byte) (*ecdsa.PublicKey, error) { return nil, errHashOfInvalidLength } - if types.BytesToHash(hash) == types.ZeroHash { - return nil, errZeroHash - } - size := len(signature) term := byte(27) diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go index c9b53d4d80..ab38b04848 100644 --- a/crypto/crypto_test.go +++ b/crypto/crypto_test.go @@ -456,13 +456,6 @@ func TestRecoverPublicKey(t *testing.T) { require.ErrorIs(t, err, errHashOfInvalidLength) }) - t.Run("Zero hash", func(t *testing.T) { - t.Parallel() - - _, err := RecoverPubkey(testSignature, types.ZeroHash[:]) - require.ErrorIs(t, err, errZeroHash) - }) - t.Run("Ok signature and hash", func(t *testing.T) { t.Parallel() diff --git a/crypto/txsigner.go b/crypto/txsigner.go index c35f0b3581..f0c7e203b4 100644 --- a/crypto/txsigner.go +++ b/crypto/txsigner.go @@ -4,12 +4,16 @@ import ( "crypto/ecdsa" "fmt" "math/big" - "math/bits" "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/helper/keccak" "github.com/0xPolygon/polygon-edge/types" - "github.com/umbracle/fastrlp" +) + +// Magic numbers from Ethereum, used in v calculation +var ( + big27 = big.NewInt(27) + big35 = big.NewInt(35) ) // TxSigner is a utility interface used to recover data from a transaction @@ -22,9 +26,6 @@ type TxSigner interface { // SignTx signs a transaction SignTx(tx *types.Transaction, priv *ecdsa.PrivateKey) (*types.Transaction, error) - - // CalculateV calculates the V value based on the type of signer used - CalculateV(parity byte) []byte } // NewSigner creates a new signer object (EIP155 or FrontierSigner) @@ -32,27 +33,54 @@ func NewSigner(forks chain.ForksInTime, chainID uint64) TxSigner { var signer TxSigner if forks.EIP155 { - signer = &EIP155Signer{chainID: chainID, isHomestead: forks.Homestead} + signer = NewEIP155Signer(chainID, forks.Homestead) } else { - signer = &FrontierSigner{forks.Homestead} + signer = NewFrontierSigner(forks.Homestead) + } + + // London signer requires a fallback signer that is defined above. + // This is the reason why the london signer check is separated. + if forks.London { + return NewLondonSigner(chainID, forks.Homestead, signer) } return signer } -type FrontierSigner struct { - isHomestead bool -} +// encodeSignature generates a signature value based on the R, S and V value +func encodeSignature(R, S, V *big.Int, isHomestead bool) ([]byte, error) { + if !ValidateSignatureValues(V, R, S, isHomestead) { + return nil, fmt.Errorf("invalid txn signature") + } -var signerPool fastrlp.ArenaPool + sig := make([]byte, 65) + copy(sig[32-len(R.Bytes()):32], R.Bytes()) + copy(sig[64-len(S.Bytes()):64], S.Bytes()) + sig[64] = byte(V.Int64()) // here is safe to convert it since ValidateSignatureValues will validate the v value + + return sig, nil +} // calcTxHash calculates the transaction hash (keccak256 hash of the RLP value) func calcTxHash(tx *types.Transaction, chainID uint64) types.Hash { a := signerPool.Get() + isDynamicFeeTx := tx.Type == types.DynamicFeeTx v := a.NewArray() + + if isDynamicFeeTx { + v.Set(a.NewUint(chainID)) + } + v.Set(a.NewUint(tx.Nonce)) - v.Set(a.NewBigInt(tx.GasPrice)) + + if isDynamicFeeTx { + v.Set(a.NewBigInt(tx.GasTipCap)) + v.Set(a.NewBigInt(tx.GasFeeCap)) + } else { + v.Set(a.NewBigInt(tx.GasPrice)) + } + v.Set(a.NewUint(tx.Gas)) if tx.To == nil { @@ -62,183 +90,28 @@ func calcTxHash(tx *types.Transaction, chainID uint64) types.Hash { } v.Set(a.NewBigInt(tx.Value)) + v.Set(a.NewCopyBytes(tx.Input)) - // EIP155 - if chainID != 0 { - v.Set(a.NewUint(chainID)) - v.Set(a.NewUint(0)) - v.Set(a.NewUint(0)) + if isDynamicFeeTx { + v.Set(a.NewArray()) + } else { + // EIP155 + if chainID != 0 { + v.Set(a.NewUint(chainID)) + v.Set(a.NewUint(0)) + v.Set(a.NewUint(0)) + } } - hash := keccak.Keccak256Rlp(nil, v) + var hash []byte + if isDynamicFeeTx { + hash = keccak.PrefixedKeccak256Rlp([]byte{byte(tx.Type)}, nil, v) + } else { + hash = keccak.Keccak256Rlp(nil, v) + } signerPool.Put(a) return types.BytesToHash(hash) } - -// Hash is a wrapper function for the calcTxHash, with chainID 0 -func (f *FrontierSigner) Hash(tx *types.Transaction) types.Hash { - return calcTxHash(tx, 0) -} - -// Magic numbers from Ethereum, used in v calculation -var ( - big27 = big.NewInt(27) - big35 = big.NewInt(35) -) - -// Sender decodes the signature and returns the sender of the transaction -func (f *FrontierSigner) Sender(tx *types.Transaction) (types.Address, error) { - refV := big.NewInt(0) - if tx.V != nil { - refV.SetBytes(tx.V.Bytes()) - } - - refV.Sub(refV, big27) - - sig, err := encodeSignature(tx.R, tx.S, refV, f.isHomestead) - if err != nil { - return types.Address{}, err - } - - pub, err := Ecrecover(f.Hash(tx).Bytes(), sig) - if err != nil { - return types.Address{}, err - } - - buf := Keccak256(pub[1:])[12:] - - return types.BytesToAddress(buf), nil -} - -// SignTx signs the transaction using the passed in private key -func (f *FrontierSigner) SignTx( - tx *types.Transaction, - privateKey *ecdsa.PrivateKey, -) (*types.Transaction, error) { - tx = tx.Copy() - - h := f.Hash(tx) - - sig, err := Sign(privateKey, h[:]) - if err != nil { - return nil, err - } - - tx.R = new(big.Int).SetBytes(sig[:32]) - tx.S = new(big.Int).SetBytes(sig[32:64]) - tx.V = new(big.Int).SetBytes(f.CalculateV(sig[64])) - - return tx, nil -} - -// calculateV returns the V value for transactions pre EIP155 -func (f *FrontierSigner) CalculateV(parity byte) []byte { - reference := big.NewInt(int64(parity)) - reference.Add(reference, big27) - - return reference.Bytes() -} - -// NewEIP155Signer returns a new EIP155Signer object -func NewEIP155Signer(forks chain.ForksInTime, chainID uint64) *EIP155Signer { - return &EIP155Signer{chainID: chainID, isHomestead: forks.Homestead} -} - -type EIP155Signer struct { - chainID uint64 - isHomestead bool -} - -// Hash is a wrapper function that calls calcTxHash with the EIP155Signer's chainID -func (e *EIP155Signer) Hash(tx *types.Transaction) types.Hash { - return calcTxHash(tx, e.chainID) -} - -// Sender returns the transaction sender -func (e *EIP155Signer) Sender(tx *types.Transaction) (types.Address, error) { - protected := true - - // Check if v value conforms to an earlier standard (before EIP155) - bigV := big.NewInt(0) - if tx.V != nil { - bigV.SetBytes(tx.V.Bytes()) - } - - if vv := bigV.Uint64(); bits.Len(uint(vv)) <= 8 { - protected = vv != 27 && vv != 28 - } - - if !protected { - return (&FrontierSigner{}).Sender(tx) - } - - // Reverse the V calculation to find the original V in the range [0, 1] - // v = CHAIN_ID * 2 + 35 + {0, 1} - mulOperand := big.NewInt(0).Mul(big.NewInt(int64(e.chainID)), big.NewInt(2)) - bigV.Sub(bigV, mulOperand) - bigV.Sub(bigV, big35) - - sig, err := encodeSignature(tx.R, tx.S, bigV, e.isHomestead) - if err != nil { - return types.Address{}, err - } - - pub, err := Ecrecover(e.Hash(tx).Bytes(), sig) - if err != nil { - return types.Address{}, err - } - - buf := Keccak256(pub[1:])[12:] - - return types.BytesToAddress(buf), nil -} - -// SignTx signs the transaction using the passed in private key -func (e *EIP155Signer) SignTx( - tx *types.Transaction, - privateKey *ecdsa.PrivateKey, -) (*types.Transaction, error) { - tx = tx.Copy() - - h := e.Hash(tx) - - sig, err := Sign(privateKey, h[:]) - if err != nil { - return nil, err - } - - tx.R = new(big.Int).SetBytes(sig[:32]) - tx.S = new(big.Int).SetBytes(sig[32:64]) - tx.V = new(big.Int).SetBytes(e.CalculateV(sig[64])) - - return tx, nil -} - -// calculateV returns the V value for transaction signatures. Based on EIP155 -func (e *EIP155Signer) CalculateV(parity byte) []byte { - reference := big.NewInt(int64(parity)) - reference.Add(reference, big35) - - mulOperand := big.NewInt(0).Mul(big.NewInt(int64(e.chainID)), big.NewInt(2)) - - reference.Add(reference, mulOperand) - - return reference.Bytes() -} - -// encodeSignature generates a signature value based on the R, S and V value -func encodeSignature(R, S, V *big.Int, isHomestead bool) ([]byte, error) { - if !ValidateSignatureValues(V, R, S, isHomestead) { - return nil, fmt.Errorf("invalid txn signature") - } - - sig := make([]byte, 65) - copy(sig[32-len(R.Bytes()):32], R.Bytes()) - copy(sig[64-len(S.Bytes()):64], S.Bytes()) - sig[64] = byte(V.Int64()) // here is safe to convert it since ValidateSignatureValues will validate the v value - - return sig, nil -} diff --git a/crypto/txsigner_eip155.go b/crypto/txsigner_eip155.go new file mode 100644 index 0000000000..faa394347b --- /dev/null +++ b/crypto/txsigner_eip155.go @@ -0,0 +1,99 @@ +package crypto + +import ( + "crypto/ecdsa" + "math/big" + "math/bits" + + "github.com/0xPolygon/polygon-edge/types" +) + +type EIP155Signer struct { + chainID uint64 + isHomestead bool +} + +// NewEIP155Signer returns a new EIP155Signer object +func NewEIP155Signer(chainID uint64, isHomestead bool) *EIP155Signer { + return &EIP155Signer{ + chainID: chainID, + isHomestead: isHomestead, + } +} + +// Hash is a wrapper function that calls calcTxHash with the EIP155Signer's chainID +func (e *EIP155Signer) Hash(tx *types.Transaction) types.Hash { + return calcTxHash(tx, e.chainID) +} + +// Sender returns the transaction sender +func (e *EIP155Signer) Sender(tx *types.Transaction) (types.Address, error) { + protected := true + + // Check if v value conforms to an earlier standard (before EIP155) + bigV := big.NewInt(0) + if tx.V != nil { + bigV.SetBytes(tx.V.Bytes()) + } + + if vv := bigV.Uint64(); bits.Len(uint(vv)) <= 8 { + protected = vv != 27 && vv != 28 + } + + if !protected { + return (&FrontierSigner{}).Sender(tx) + } + + // Reverse the V calculation to find the original V in the range [0, 1] + // v = CHAIN_ID * 2 + 35 + {0, 1} + mulOperand := big.NewInt(0).Mul(big.NewInt(int64(e.chainID)), big.NewInt(2)) + bigV.Sub(bigV, mulOperand) + bigV.Sub(bigV, big35) + + sig, err := encodeSignature(tx.R, tx.S, bigV, e.isHomestead) + if err != nil { + return types.Address{}, err + } + + pub, err := Ecrecover(e.Hash(tx).Bytes(), sig) + if err != nil { + return types.Address{}, err + } + + buf := Keccak256(pub[1:])[12:] + + return types.BytesToAddress(buf), nil +} + +// SignTx signs the transaction using the passed in private key +func (e *EIP155Signer) SignTx( + tx *types.Transaction, + privateKey *ecdsa.PrivateKey, +) (*types.Transaction, error) { + tx = tx.Copy() + + h := e.Hash(tx) + + sig, err := Sign(privateKey, h[:]) + if err != nil { + return nil, err + } + + tx.R = new(big.Int).SetBytes(sig[:32]) + tx.S = new(big.Int).SetBytes(sig[32:64]) + tx.V = new(big.Int).SetBytes(e.calculateV(sig[64])) + + return tx, nil +} + +// calculateV returns the V value for transaction signatures. Based on EIP155 +func (e *EIP155Signer) calculateV(parity byte) []byte { + reference := big.NewInt(int64(parity)) + reference.Add(reference, big35) + + mulOperand := big.NewInt(0).Mul(big.NewInt(int64(e.chainID)), big.NewInt(2)) + + reference.Add(reference, mulOperand) + + return reference.Bytes() +} diff --git a/crypto/txsigner_test.go b/crypto/txsigner_eip155_test.go similarity index 74% rename from crypto/txsigner_test.go rename to crypto/txsigner_eip155_test.go index f53cb5f694..a312b4023f 100644 --- a/crypto/txsigner_test.go +++ b/crypto/txsigner_eip155_test.go @@ -4,71 +4,59 @@ import ( "math/big" "testing" - "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/assert" ) -func TestFrontierSigner(t *testing.T) { - signer := &FrontierSigner{} - - toAddress := types.StringToAddress("1") - key, err := GenerateECDSAKey() - assert.NoError(t, err) - - txn := &types.Transaction{ - To: &toAddress, - Value: big.NewInt(10), - GasPrice: big.NewInt(0), - } - signedTx, err := signer.SignTx(txn, key) - assert.NoError(t, err) - - from, err := signer.Sender(signedTx) - assert.NoError(t, err) - assert.Equal(t, from, PubKeyToAddress(&key.PublicKey)) -} - func TestEIP155Signer_Sender(t *testing.T) { t.Parallel() toAddress := types.StringToAddress("1") testTable := []struct { - name string - chainID *big.Int + name string + chainID *big.Int + isHomestead bool }{ { "mainnet", big.NewInt(1), + true, }, { "expanse mainnet", big.NewInt(2), + true, }, { "ropsten", big.NewInt(3), + true, }, { "rinkeby", big.NewInt(4), + true, }, { "goerli", big.NewInt(5), + true, }, { "kovan", big.NewInt(42), + true, }, { "geth private", big.NewInt(1337), + true, }, { "mega large", big.NewInt(0).Exp(big.NewInt(2), big.NewInt(20), nil), // 2**20 + true, }, } @@ -88,7 +76,10 @@ func TestEIP155Signer_Sender(t *testing.T) { GasPrice: big.NewInt(0), } - signer := NewEIP155Signer(chain.AllForksEnabled.At(0), testCase.chainID.Uint64()) + signer := NewEIP155Signer( + testCase.chainID.Uint64(), + testCase.isHomestead, + ) signedTx, signErr := signer.SignTx(txn, key) if signErr != nil { @@ -121,7 +112,7 @@ func TestEIP155Signer_ChainIDMismatch(t *testing.T) { GasPrice: big.NewInt(0), } - signer := NewEIP155Signer(chain.AllForksEnabled.At(0), chainIDTop) + signer := NewEIP155Signer(chainIDTop, true) signedTx, signErr := signer.SignTx(txn, key) if signErr != nil { @@ -129,7 +120,7 @@ func TestEIP155Signer_ChainIDMismatch(t *testing.T) { } for _, chainIDBottom := range chainIDS { - signerBottom := NewEIP155Signer(chain.AllForksEnabled.At(0), chainIDBottom) + signerBottom := NewEIP155Signer(chainIDBottom, true) recoveredSender, recoverErr := signerBottom.Sender(signedTx) if chainIDTop == chainIDBottom { diff --git a/crypto/txsigner_frontier.go b/crypto/txsigner_frontier.go new file mode 100644 index 0000000000..f2d2297d75 --- /dev/null +++ b/crypto/txsigner_frontier.go @@ -0,0 +1,82 @@ +package crypto + +import ( + "crypto/ecdsa" + "math/big" + + "github.com/umbracle/fastrlp" + + "github.com/0xPolygon/polygon-edge/types" +) + +var signerPool fastrlp.ArenaPool + +// FrontierSigner implements tx signer interface +type FrontierSigner struct { + isHomestead bool +} + +// NewFrontierSigner is the constructor of FrontierSigner +func NewFrontierSigner(isHomestead bool) *FrontierSigner { + return &FrontierSigner{ + isHomestead: isHomestead, + } +} + +// Hash is a wrapper function for the calcTxHash, with chainID 0 +func (f *FrontierSigner) Hash(tx *types.Transaction) types.Hash { + return calcTxHash(tx, 0) +} + +// Sender decodes the signature and returns the sender of the transaction +func (f *FrontierSigner) Sender(tx *types.Transaction) (types.Address, error) { + refV := big.NewInt(0) + if tx.V != nil { + refV.SetBytes(tx.V.Bytes()) + } + + refV.Sub(refV, big27) + + sig, err := encodeSignature(tx.R, tx.S, refV, f.isHomestead) + if err != nil { + return types.Address{}, err + } + + pub, err := Ecrecover(f.Hash(tx).Bytes(), sig) + if err != nil { + return types.Address{}, err + } + + buf := Keccak256(pub[1:])[12:] + + return types.BytesToAddress(buf), nil +} + +// SignTx signs the transaction using the passed in private key +func (f *FrontierSigner) SignTx( + tx *types.Transaction, + privateKey *ecdsa.PrivateKey, +) (*types.Transaction, error) { + tx = tx.Copy() + + h := f.Hash(tx) + + sig, err := Sign(privateKey, h[:]) + if err != nil { + return nil, err + } + + tx.R = new(big.Int).SetBytes(sig[:32]) + tx.S = new(big.Int).SetBytes(sig[32:64]) + tx.V = new(big.Int).SetBytes(f.calculateV(sig[64])) + + return tx, nil +} + +// calculateV returns the V value for transactions pre EIP155 +func (f *FrontierSigner) calculateV(parity byte) []byte { + reference := big.NewInt(int64(parity)) + reference.Add(reference, big27) + + return reference.Bytes() +} diff --git a/crypto/txsigner_frontier_test.go b/crypto/txsigner_frontier_test.go new file mode 100644 index 0000000000..e0d9c3ddfb --- /dev/null +++ b/crypto/txsigner_frontier_test.go @@ -0,0 +1,29 @@ +package crypto + +import ( + "math/big" + "testing" + + "github.com/0xPolygon/polygon-edge/types" + "github.com/stretchr/testify/assert" +) + +func TestFrontierSigner(t *testing.T) { + signer := &FrontierSigner{} + + toAddress := types.StringToAddress("1") + key, err := GenerateECDSAKey() + assert.NoError(t, err) + + txn := &types.Transaction{ + To: &toAddress, + Value: big.NewInt(10), + GasPrice: big.NewInt(0), + } + signedTx, err := signer.SignTx(txn, key) + assert.NoError(t, err) + + from, err := signer.Sender(signedTx) + assert.NoError(t, err) + assert.Equal(t, from, PubKeyToAddress(&key.PublicKey)) +} diff --git a/crypto/txsigner_london.go b/crypto/txsigner_london.go new file mode 100644 index 0000000000..727368b28b --- /dev/null +++ b/crypto/txsigner_london.go @@ -0,0 +1,79 @@ +package crypto + +import ( + "crypto/ecdsa" + "math/big" + + "github.com/0xPolygon/polygon-edge/types" +) + +// LondonSigner implements signer for EIP-1559 +type LondonSigner struct { + chainID uint64 + isHomestead bool + fallbackSigner TxSigner +} + +// NewLondonSigner returns a new LondonSigner object +func NewLondonSigner(chainID uint64, isHomestead bool, fallbackSigner TxSigner) *LondonSigner { + return &LondonSigner{ + chainID: chainID, + isHomestead: isHomestead, + fallbackSigner: fallbackSigner, + } +} + +// Hash is a wrapper function that calls calcTxHash with the LondonSigner's fields +func (e *LondonSigner) Hash(tx *types.Transaction) types.Hash { + return calcTxHash(tx, e.chainID) +} + +// Sender returns the transaction sender +func (e *LondonSigner) Sender(tx *types.Transaction) (types.Address, error) { + // Apply fallback signer for non-dynamic-fee-txs + if tx.Type != types.DynamicFeeTx { + return e.fallbackSigner.Sender(tx) + } + + sig, err := encodeSignature(tx.R, tx.S, tx.V, e.isHomestead) + if err != nil { + return types.Address{}, err + } + + pub, err := Ecrecover(e.Hash(tx).Bytes(), sig) + if err != nil { + return types.Address{}, err + } + + buf := Keccak256(pub[1:])[12:] + + return types.BytesToAddress(buf), nil +} + +// SignTx signs the transaction using the passed in private key +func (e *LondonSigner) SignTx(tx *types.Transaction, pk *ecdsa.PrivateKey) (*types.Transaction, error) { + // Apply fallback signer for non-dynamic-fee-txs + if tx.Type != types.DynamicFeeTx { + return e.fallbackSigner.SignTx(tx, pk) + } + + tx = tx.Copy() + + h := e.Hash(tx) + + sig, err := Sign(pk, h[:]) + if err != nil { + return nil, err + } + + tx.R = new(big.Int).SetBytes(sig[:32]) + tx.S = new(big.Int).SetBytes(sig[32:64]) + tx.V = new(big.Int).SetBytes(e.calculateV(sig[64])) + + return tx, nil +} + +// calculateV returns the V value for transaction signatures. Based on EIP155 +func (e *LondonSigner) calculateV(parity byte) []byte { + return big.NewInt(int64(parity)).Bytes() +} diff --git a/crypto/txsigner_london_test.go b/crypto/txsigner_london_test.go new file mode 100644 index 0000000000..f27997dd43 --- /dev/null +++ b/crypto/txsigner_london_test.go @@ -0,0 +1,145 @@ +package crypto + +import ( + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/0xPolygon/polygon-edge/types" +) + +func TestLondonSignerSender(t *testing.T) { + t.Parallel() + + toAddress := types.StringToAddress("1") + + testTable := []struct { + name string + chainID *big.Int + isGomestead bool + }{ + { + "mainnet", + big.NewInt(1), + true, + }, + { + "expanse mainnet", + big.NewInt(2), + true, + }, + { + "ropsten", + big.NewInt(3), + true, + }, + { + "rinkeby", + big.NewInt(4), + true, + }, + { + "goerli", + big.NewInt(5), + true, + }, + { + "kovan", + big.NewInt(42), + true, + }, + { + "geth private", + big.NewInt(1337), + true, + }, + { + "mega large", + big.NewInt(0).Exp(big.NewInt(2), big.NewInt(20), nil), // 2**20 + true, + }, + } + + for _, testCase := range testTable { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + key, keyGenError := GenerateECDSAKey() + if keyGenError != nil { + t.Fatalf("Unable to generate key") + } + + txn := &types.Transaction{ + To: &toAddress, + Value: big.NewInt(1), + GasPrice: big.NewInt(0), + } + + chainID := testCase.chainID.Uint64() + signer := NewLondonSigner(chainID, true, NewEIP155Signer(chainID, true)) + + signedTx, signErr := signer.SignTx(txn, key) + if signErr != nil { + t.Fatalf("Unable to sign transaction") + } + + recoveredSender, recoverErr := signer.Sender(signedTx) + if recoverErr != nil { + t.Fatalf("Unable to recover sender") + } + + assert.Equal(t, recoveredSender.String(), PubKeyToAddress(&key.PublicKey).String()) + }) + } +} + +func Test_LondonSigner_Sender(t *testing.T) { + t.Parallel() + + signer := NewLondonSigner(100, true, NewEIP155Signer(100, true)) + to := types.StringToAddress("0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF") + + r, ok := big.NewInt(0).SetString("102623819621514684481463796449525884981685455700611671612296611353030973716382", 10) + require.True(t, ok) + + s, ok := big.NewInt(0).SetString("52694559292202008915948760944211702951173212957828665318138448463580296965840", 10) + require.True(t, ok) + + testTable := []struct { + name string + tx *types.Transaction + sender types.Address + }{ + { + name: "sender is 0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6", + tx: &types.Transaction{ + Type: types.DynamicFeeTx, + GasPrice: big.NewInt(1000000402), + GasTipCap: big.NewInt(1000000000), + GasFeeCap: big.NewInt(10000000000), + Gas: 21000, + To: &to, + Value: big.NewInt(100000000000000), + V: big.NewInt(0), + R: r, + S: s, + }, + sender: types.StringToAddress("0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6"), + }, + } + + for _, tt := range testTable { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + sender, err := signer.Sender(tt.tx) + require.NoError(t, err) + require.Equal(t, tt.sender, sender) + }) + } +} diff --git a/docker/README.md b/docker/README.md index f4a5cba036..39a7dc23fe 100644 --- a/docker/README.md +++ b/docker/README.md @@ -7,7 +7,7 @@ ### `polybft` consensus When deploying with `polybft` consensus, there are some additional dependencies: * [npm](https://nodejs.org/en/) -* [go 1.18.x](https://go.dev/dl/) +* [go 1.20.x](https://go.dev/dl/) ## Local development Running `polygon-edge` local cluster with docker can be done very easily by using provided `scripts` folder @@ -50,10 +50,10 @@ Primarily, the `--premine` parameter needs to be edited to include the accounts ### Submodules Before deploying `polybft` environment, `core-contracts` submodule needs to be downloaded. -To do that simply run `make download-submodules`. +To do that, simply run `make download-submodules`. ### Build times -When building containers for the first time (or after purging docker build cache) +When building containers for the first time (or after purging docker build cache), it might take a while to complete, depending on the hardware that the build operation is running on. ### Production diff --git a/docker/local/Dockerfile b/docker/local/Dockerfile index afffcbc864..05c9cf6659 100644 --- a/docker/local/Dockerfile +++ b/docker/local/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.18-alpine AS builder +FROM golang:1.20-alpine AS builder WORKDIR /polygon-edge diff --git a/docker/local/docker-compose.yml b/docker/local/docker-compose.yml index 425b95bd36..00e99800e2 100644 --- a/docker/local/docker-compose.yml +++ b/docker/local/docker-compose.yml @@ -1,14 +1,40 @@ version: '3.9' services: - ## INITIALIZE GENESIS AND SECRETS + ## RUN ROOTCHAIN + rootchain: + image: ghcr.io/0xpolygon/go-ethereum-console:latest + container_name: polygon-edge-rootchain + command: [ + "--dev", + "--dev.period", "2", + "--datadir", "/eth1data", + "--ipcpath", "/eth1data/geth.ipc", + "--http", + "--http.addr", "0.0.0.0", + "--http.vhosts", "*", + "--http.api", "eth,net,web3,debug", + "--ws", + "--ws.addr", "0.0.0.0" + ] + ports: + - '8545:8545' + volumes: + - eth1data:/eth1data + networks: + - polygon-edge-docker + + ## INITIALIZE GENESIS AND SECRETS, ETC. init: build: context: ../../ dockerfile: docker/local/Dockerfile image: local/polygon-edge container_name: polygon-edge-bootstrapper - command: [ "init", "${EDGE_CONSENSUS:-ibft}" ] + command: [ "init", "${EDGE_CONSENSUS:-polybft}" ] + depends_on: + rootchain: + condition: service_started volumes: - data:/data networks: @@ -18,10 +44,21 @@ services: node-1: image: local/polygon-edge container_name: polygon-edge-validator-1 - command: ["server", "--data-dir", "/data/data-1", "--chain", "/data/genesis.json", "--grpc-address", "0.0.0.0:9632", "--libp2p", "0.0.0.0:1478", "--jsonrpc", "0.0.0.0:8545", "--prometheus", "0.0.0.0:5001", "--seal"] + command: [ + "server", + "--data-dir", "/data/data-1", + "--chain", "/data/genesis.json", + "--grpc-address", "0.0.0.0:9632", + "--libp2p", "0.0.0.0:1478", + "--jsonrpc", "0.0.0.0:8545", + "--prometheus", "0.0.0.0:5001", + "--seal" + ] depends_on: init: condition: service_completed_successfully + rootchain: + condition: service_started ports: - '10000:9632' - '10002:8545' @@ -35,10 +72,22 @@ services: node-2: image: local/polygon-edge container_name: polygon-edge-validator-2 - command: ["server", "--data-dir", "/data/data-2", "--chain", "/data/genesis.json", "--grpc-address", "0.0.0.0:9632", "--libp2p", "0.0.0.0:1478", "--jsonrpc", "0.0.0.0:8545", "--prometheus", "0.0.0.0:5001", "--seal"] + command: [ + "server", + "--data-dir", + "/data/data-2", + "--chain", "/data/genesis.json", + "--grpc-address", "0.0.0.0:9632", + "--libp2p", "0.0.0.0:1478", + "--jsonrpc", "0.0.0.0:8545", + "--prometheus", "0.0.0.0:5001", + "--seal" + ] depends_on: init: condition: service_completed_successfully + rootchain: + condition: service_started ports: - '20000:9632' - '20002:8545' @@ -52,10 +101,21 @@ services: node-3: image: local/polygon-edge container_name: polygon-edge-validator-3 - command: ["server", "--data-dir", "/data/data-3", "--chain", "/data/genesis.json", "--grpc-address", "0.0.0.0:9632", "--libp2p", "0.0.0.0:1478", "--jsonrpc", "0.0.0.0:8545", "--prometheus", "0.0.0.0:5001", "--seal"] + command: [ + "server", + "--data-dir", "/data/data-3", + "--chain", "/data/genesis.json", + "--grpc-address", "0.0.0.0:9632", + "--libp2p", "0.0.0.0:1478", + "--jsonrpc", "0.0.0.0:8545", + "--prometheus", "0.0.0.0:5001", + "--seal" + ] depends_on: init: condition: service_completed_successfully + rootchain: + condition: service_started ports: - '30000:9632' - '30002:8545' @@ -69,10 +129,21 @@ services: node-4: image: local/polygon-edge container_name: polygon-edge-validator-4 - command: ["server", "--data-dir", "/data/data-4", "--chain", "/data/genesis.json", "--grpc-address", "0.0.0.0:9632", "--libp2p", "0.0.0.0:1478", "--jsonrpc", "0.0.0.0:8545", "--prometheus", "0.0.0.0:5001", "--seal"] + command: [ + "server", + "--data-dir", "/data/data-4", + "--chain", "/data/genesis.json", + "--grpc-address", "0.0.0.0:9632", + "--libp2p", "0.0.0.0:1478", + "--jsonrpc", "0.0.0.0:8545", + "--prometheus", "0.0.0.0:5001", + "--seal" + ] depends_on: init: condition: service_completed_successfully + rootchain: + condition: service_started ports: - '40000:9632' - '40002:8545' @@ -90,4 +161,5 @@ networks: volumes: data: + eth1data: genesis: diff --git a/docker/local/polygon-edge.sh b/docker/local/polygon-edge.sh index cbb813c501..29db8d7bc3 100755 --- a/docker/local/polygon-edge.sh +++ b/docker/local/polygon-edge.sh @@ -14,49 +14,115 @@ EOL ) case "$1" in - "init") case "$2" in - "ibft") - if [ -f "$GENESIS_PATH" ]; then - echo "Secrets have already been generated." - else - echo "Generating secrets..." - secrets=$("$POLYGON_EDGE_BIN" secrets init --insecure --num 4 --data-dir /data/data- --json) - echo "Secrets have been successfully generated" - echo "Generating IBFT Genesis file..." - cd /data && /polygon-edge/polygon-edge genesis $CHAIN_CUSTOM_OPTIONS \ - --dir genesis.json \ - --consensus ibft \ - --ibft-validators-prefix-path data- \ - --validator-set-size=4 \ - --bootnode "/dns4/node-1/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[0] | .node_id')" \ - --bootnode "/dns4/node-2/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[1] | .node_id')" - fi + "ibft") + if [ -f "$GENESIS_PATH" ]; then + echo "Secrets have already been generated." + else + echo "Generating IBFT secrets..." + secrets=$("$POLYGON_EDGE_BIN" secrets init --insecure --num 4 --data-dir /data/data- --json) + echo "Secrets have been successfully generated" + + rm -f /data/genesis.json + + echo "Generating IBFT Genesis file..." + "$POLYGON_EDGE_BIN" genesis $CHAIN_CUSTOM_OPTIONS \ + --dir /data/genesis.json \ + --consensus ibft \ + --ibft-validators-prefix-path data- \ + --bootnode "/dns4/node-1/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[0] | .node_id')" \ + --bootnode "/dns4/node-2/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[1] | .node_id')" \ + --bootnode "/dns4/node-3/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[2] | .node_id')" \ + --bootnode "/dns4/node-4/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[3] | .node_id')" + fi ;; "polybft") echo "Generating PolyBFT secrets..." secrets=$("$POLYGON_EDGE_BIN" polybft-secrets init --insecure --num 4 --data-dir /data/data- --json) echo "Secrets have been successfully generated" - echo "Generating manifest..." - "$POLYGON_EDGE_BIN" manifest --path /data/manifest.json --validators-path /data --validators-prefix data- + rm -f /data/genesis.json - echo "Generating PolyBFT Genesis file..." + echo "Generating PolyBFT genesis file..." "$POLYGON_EDGE_BIN" genesis $CHAIN_CUSTOM_OPTIONS \ --dir /data/genesis.json \ --consensus polybft \ - --manifest /data/manifest.json \ - --validator-set-size=4 \ + --validators-path /data \ + --validators-prefix data- \ + --reward-wallet 0xDEADBEEF:1000000 \ + --native-token-config "Polygon:MATIC:18:true:$(echo "$secrets" | jq -r '.[0] | .address')" \ --bootnode "/dns4/node-1/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[0] | .node_id')" \ - --bootnode "/dns4/node-2/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[1] | .node_id')" + --bootnode "/dns4/node-2/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[1] | .node_id')" \ + --bootnode "/dns4/node-3/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[2] | .node_id')" \ + --bootnode "/dns4/node-4/tcp/1478/p2p/$(echo "$secrets" | jq -r '.[3] | .node_id')" + + echo "Deploying stake manager..." + "$POLYGON_EDGE_BIN" polybft stake-manager-deploy \ + --jsonrpc http://rootchain:8545 \ + --genesis /data/genesis.json \ + --test + + stakeManagerAddr=$(cat /data/genesis.json | jq -r '.params.engine.polybft.bridge.stakeManagerAddr') + stakeToken=$(cat /data/genesis.json | jq -r '.params.engine.polybft.bridge.stakeTokenAddr') + + "$POLYGON_EDGE_BIN" rootchain deploy \ + --stake-manager ${stakeManagerAddr} \ + --stake-token ${stakeToken} \ + --json-rpc http://rootchain:8545 \ + --genesis /data/genesis.json \ + --test + + customSupernetManagerAddr=$(cat /data/genesis.json | jq -r '.params.engine.polybft.bridge.customSupernetManagerAddr') + supernetID=$(cat /data/genesis.json | jq -r '.params.engine.polybft.supernetID') + addresses="$(echo "$secrets" | jq -r '.[0] | .address'),$(echo "$secrets" | jq -r '.[1] | .address'),$(echo "$secrets" | jq -r '.[2] | .address'),$(echo "$secrets" | jq -r '.[3] | .address')" + + "$POLYGON_EDGE_BIN" rootchain fund \ + --json-rpc http://rootchain:8545 \ + --stake-token ${stakeToken} \ + --mint \ + --addresses ${addresses} \ + --amounts 1000000000000000000000000,1000000000000000000000000,1000000000000000000000000,1000000000000000000000000 + + "$POLYGON_EDGE_BIN" polybft whitelist-validators \ + --addresses ${addresses} \ + --supernet-manager ${customSupernetManagerAddr} \ + --private-key aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d \ + --jsonrpc http://rootchain:8545 + + counter=1 + while [ $counter -le 4 ]; do + echo "Registering validator: ${counter}" + + "$POLYGON_EDGE_BIN" polybft register-validator \ + --supernet-manager ${customSupernetManagerAddr} \ + --data-dir /data/data-${counter} \ + --jsonrpc http://rootchain:8545 + + "$POLYGON_EDGE_BIN" polybft stake \ + --data-dir /data/data-${counter} \ + --amount 1000000000000000000000000 \ + --supernet-id ${supernetID} \ + --stake-manager ${stakeManagerAddr} \ + --stake-token ${stakeToken} \ + --jsonrpc http://rootchain:8545 + + counter=$((counter + 1)) + done + + "$POLYGON_EDGE_BIN" polybft supernet \ + --private-key aa75e9a7d427efc732f8e4f1a5b7646adcc61fd5bae40f80d13c8419c9f43d6d \ + --supernet-manager ${customSupernetManagerAddr} \ + --stake-manager ${stakeManagerAddr} \ + --finalize-genesis-set \ + --enable-staking \ + --genesis /data/genesis.json \ + --jsonrpc http://rootchain:8545 ;; esac ;; - *) echo "Executing polygon-edge..." exec "$POLYGON_EDGE_BIN" "$@" ;; - esac diff --git a/docs/bridge/sequences.md b/docs/bridge/sequences.md new file mode 100644 index 0000000000..7134412653 --- /dev/null +++ b/docs/bridge/sequences.md @@ -0,0 +1,64 @@ +## Deposit + +Bridge ERC 20 tokens from rootchain to childchain via deposit. + +```mermaid +sequenceDiagram + User->>Edge: deposit + Edge->>RootERC20.sol: approve(RootERC20Predicate) + Edge->>RootERC20Predicate.sol: deposit() + RootERC20Predicate.sol->>RootERC20Predicate.sol: mapToken() + RootERC20Predicate.sol->>StateSender.sol: syncState(MAP_TOKEN_SIG), recv=ChildERC20Predicate + RootERC20Predicate.sol-->>Edge: TokenMapped Event + StateSender.sol-->>Edge: StateSynced Event to map tokens on child predicate + RootERC20Predicate.sol->>StateSender.sol: syncState(DEPOSIT_SIG), recv=ChildERC20Predicate + StateSender.sol-->>Edge: StateSynced Event to deposit on child chain + Edge->>User: ok + Edge->>StateReceiver.sol:commit() + StateReceiver.sol-->>Edge: NewCommitment Event + Edge->>StateReceiver.sol:execute() + StateReceiver.sol->>ChildERC20Predicate.sol:onStateReceive() + ChildERC20Predicate.sol->>ChildERC20.sol: mint() + StateReceiver.sol-->>Edge:StateSyncResult Event +``` + +## Withdraw + +Bridge ERC 20 tokens from childchain to rootchain via withdrawal. + +```mermaid +sequenceDiagram + User->>Edge: withdraw + Edge->>ChildERC20Predicate.sol: withdrawTo() + ChildERC20Predicate.sol->>ChildERC20: burn() + ChildERC20Predicate.sol->>L2StateSender.sol: syncState(WITHDRAW_SIG), recv=RootERC20Predicate + Edge->>User: tx hash + User->>Edge: get tx receipt + Edge->>User: exit event id + ChildERC20Predicate.sol-->>Edge: L2ERC20Withdraw Event + L2StateSender.sol-->>Edge: StateSynced Event + Edge->>Edge: Seal block + Edge->>CheckpointManager.sol: submit() +``` +## Exit + +Finalize withdrawal of ERC 20 tokens from childchain to rootchain. + +```mermaid +sequenceDiagram + User->>Edge: exit, event id:X + Edge->>Edge: bridge_generateExitProof() + Edge->>CheckpointManager.sol: getCheckpointBlock() + CheckpointManager.sol->>Edge: blockNum + Edge->>Edge: getExitEventsForProof(epochNum, blockNum) + Edge->>Edge: createExitTree(exitEvents) + Edge->>Edge: generateProof() + Edge->>ExitHelper.sol: exit() + ExitHelper.sol->>CheckpointManager.sol: getEventMembershipByBlockNumber() + ExitHelper.sol->>RootERC20Predicate.sol:onL2StateReceive() + RootERC20Predicate.sol->>RootERC20: transfer() + Edge->>User: ok + RootERC20Predicate.sol-->>Edge: ERC20Withdraw Event + ExitHelper.sol-->>Edge: ExitProcessed Event +``` + diff --git a/e2e-polybft/e2e/acls_test.go b/e2e-polybft/e2e/acls_test.go new file mode 100644 index 0000000000..deb72c2a27 --- /dev/null +++ b/e2e-polybft/e2e/acls_test.go @@ -0,0 +1,415 @@ +package e2e + +import ( + "fmt" + "math/big" + "testing" + + "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" + "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/state/runtime/addresslist" + "github.com/0xPolygon/polygon-edge/types" + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo/wallet" +) + +// Contract used as bytecode + +/* +pragma solidity ^0.8; +pragma experimental ABIEncoderV2; + +contract Sample { + address public constant allowListContractsAddr = 0x0200000000000000000000000000000000000000; + + function readAddressList(address addr) public returns (uint256) { + (bool success, bytes memory returnData) = allowListContractsAddr.call(abi.encodeWithSignature("readAddressList(address)", addr)); + (uint256 val) = abi.decode(returnData, (uint256)); + return val; + } +} +*/ + +func TestE2E_AllowList_ContractDeployment(t *testing.T) { + // create two accounts, one for an admin sender and a second + // one for a non-enabled account that will switch on-off between + // both enabled and non-enabled roles. + admin, _ := wallet.GenerateKey() + target, _ := wallet.GenerateKey() + + adminAddr := types.Address(admin.Address()) + targetAddr := types.Address(target.Address()) + + otherAddr := types.Address{0x1} + + cluster := framework.NewTestCluster(t, 5, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, adminAddr)), + framework.WithPremine(adminAddr, targetAddr), + framework.WithContractDeployerAllowListAdmin(adminAddr), + framework.WithContractDeployerAllowListEnabled(otherAddr), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + // bytecode for an empty smart contract + bytecode, err := hex.DecodeString("608060405234801561001057600080fd5b506103db806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635e9f13f81461003b578063d78bca6914610059575b600080fd5b610043610089565b6040516100509190610217565b60405180910390f35b610073600480360381019061006e9190610263565b6100a1565b60405161008091906102a9565b60405180910390f35b73020000000000000000000000000000000000000081565b600080600073020000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16846040516024016100e29190610217565b6040516020818303038152906040527fd78bca69000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161016c9190610335565b6000604051808303816000865af19150503d80600081146101a9576040519150601f19603f3d011682016040523d82523d6000602084013e6101ae565b606091505b50915091506000818060200190518101906101c99190610378565b9050809350505050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610201826101d6565b9050919050565b610211816101f6565b82525050565b600060208201905061022c6000830184610208565b92915050565b600080fd5b610240816101f6565b811461024b57600080fd5b50565b60008135905061025d81610237565b92915050565b60006020828403121561027957610278610232565b5b60006102878482850161024e565b91505092915050565b6000819050919050565b6102a381610290565b82525050565b60006020820190506102be600083018461029a565b92915050565b600081519050919050565b600081905092915050565b60005b838110156102f85780820151818401526020810190506102dd565b60008484015250505050565b600061030f826102c4565b61031981856102cf565b93506103298185602086016102da565b80840191505092915050565b60006103418284610304565b915081905092915050565b61035581610290565b811461036057600080fd5b50565b6000815190506103728161034c565b92915050565b60006020828403121561038e5761038d610232565b5b600061039c84828501610363565b9150509291505056fea264697066735822122035f391b5c3dbf9a5e31072167a4ada71e9ba762650849f6320bc6150fa45aa9564736f6c63430008110033") + require.NoError(t, err) + + { + // Step 0. Check the role of both accounts + expectRole(t, cluster, contracts.AllowListContractsAddr, adminAddr, addresslist.AdminRole) + expectRole(t, cluster, contracts.AllowListContractsAddr, targetAddr, addresslist.NoRole) + expectRole(t, cluster, contracts.AllowListContractsAddr, otherAddr, addresslist.EnabledRole) + } + + { + // Step 1. 'targetAddr' can send a normal transaction (non-contract creation). + err := cluster.Transfer(t, target, types.ZeroAddress, big.NewInt(1)).Wait() + require.NoError(t, err) + } + + var proxyContract types.Address + + { + // Step 2. 'targetAddr' **cannot** deploy a contract because it is not whitelisted. + // (The transaction does not fail but the contract is not deployed and all gas + // for the transaction is consumed) + deployTxn := cluster.Deploy(t, target, bytecode) + require.NoError(t, deployTxn.Wait()) + require.True(t, deployTxn.Reverted()) + require.False(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) + } + + { + // Step 3. 'adminAddr' can create contracts + deployTxn := cluster.Deploy(t, admin, bytecode) + require.NoError(t, deployTxn.Wait()) + require.True(t, deployTxn.Succeed()) + require.True(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) + + proxyContract = types.Address(deployTxn.Receipt().ContractAddress) + } + + { + // Step 4. 'adminAddr' sends a transaction to enable 'targetAddr'. + input, _ := addresslist.SetEnabledFunc.Encode([]interface{}{targetAddr}) + + adminSetTxn := cluster.MethodTxn(t, admin, contracts.AllowListContractsAddr, input) + require.NoError(t, adminSetTxn.Wait()) + expectRole(t, cluster, contracts.AllowListContractsAddr, targetAddr, addresslist.EnabledRole) + } + + { + // Step 5. 'targetAddr' can create contracts now. + deployTxn := cluster.Deploy(t, target, bytecode) + require.NoError(t, deployTxn.Wait()) + require.True(t, deployTxn.Succeed()) + require.True(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) + } + + { + // Step 6. 'targetAddr' cannot enable other accounts since it is not an admin + // (The transaction fails) + input, _ := addresslist.SetEnabledFunc.Encode([]interface{}{types.ZeroAddress}) + + adminSetFailTxn := cluster.MethodTxn(t, target, contracts.AllowListContractsAddr, input) + require.NoError(t, adminSetFailTxn.Wait()) + require.True(t, adminSetFailTxn.Failed()) + expectRole(t, cluster, contracts.AllowListContractsAddr, types.ZeroAddress, addresslist.NoRole) + } + + { + // Step 7. Call a proxy contract that can call the allow list + resp := cluster.Call(t, proxyContract, addresslist.ReadAddressListFunc, adminAddr) + + role, ok := resp["0"].(*big.Int) + require.True(t, ok) + require.Equal(t, role.Uint64(), addresslist.AdminRole.Uint64()) + } +} + +func TestE2E_BlockList_ContractDeployment(t *testing.T) { + // create two accounts, one for an admin sender and a second + // one for a non-enabled account that will switch on-off between + // both enabled and non-enabled roles. + admin, _ := wallet.GenerateKey() + target, _ := wallet.GenerateKey() + + adminAddr := types.Address(admin.Address()) + targetAddr := types.Address(target.Address()) + + otherAddr := types.Address{0x1} + + cluster := framework.NewTestCluster(t, 5, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, adminAddr)), + framework.WithPremine(adminAddr, targetAddr), + framework.WithContractDeployerBlockListAdmin(adminAddr), + framework.WithContractDeployerBlockListEnabled(otherAddr), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + // bytecode for an empty smart contract + bytecode, err := hex.DecodeString("608060405234801561001057600080fd5b506103db806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635e9f13f81461003b578063d78bca6914610059575b600080fd5b610043610089565b6040516100509190610217565b60405180910390f35b610073600480360381019061006e9190610263565b6100a1565b60405161008091906102a9565b60405180910390f35b73020000000000000000000000000000000000000081565b600080600073020000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16846040516024016100e29190610217565b6040516020818303038152906040527fd78bca69000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161016c9190610335565b6000604051808303816000865af19150503d80600081146101a9576040519150601f19603f3d011682016040523d82523d6000602084013e6101ae565b606091505b50915091506000818060200190518101906101c99190610378565b9050809350505050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610201826101d6565b9050919050565b610211816101f6565b82525050565b600060208201905061022c6000830184610208565b92915050565b600080fd5b610240816101f6565b811461024b57600080fd5b50565b60008135905061025d81610237565b92915050565b60006020828403121561027957610278610232565b5b60006102878482850161024e565b91505092915050565b6000819050919050565b6102a381610290565b82525050565b60006020820190506102be600083018461029a565b92915050565b600081519050919050565b600081905092915050565b60005b838110156102f85780820151818401526020810190506102dd565b60008484015250505050565b600061030f826102c4565b61031981856102cf565b93506103298185602086016102da565b80840191505092915050565b60006103418284610304565b915081905092915050565b61035581610290565b811461036057600080fd5b50565b6000815190506103728161034c565b92915050565b60006020828403121561038e5761038d610232565b5b600061039c84828501610363565b9150509291505056fea264697066735822122035f391b5c3dbf9a5e31072167a4ada71e9ba762650849f6320bc6150fa45aa9564736f6c63430008110033") + require.NoError(t, err) + + { + // Step 0. Check the role of accounts + expectRole(t, cluster, contracts.BlockListContractsAddr, adminAddr, addresslist.AdminRole) + expectRole(t, cluster, contracts.BlockListContractsAddr, targetAddr, addresslist.NoRole) + expectRole(t, cluster, contracts.BlockListContractsAddr, otherAddr, addresslist.EnabledRole) + } + + { + // Step 1. 'targetAddr' can send a normal transaction (non-contract creation). + err := cluster.Transfer(t, target, types.ZeroAddress, big.NewInt(1)).Wait() + require.NoError(t, err) + } + + { + // Step 2. 'targetAddr' **can** deploy a contract because it is not blacklisted. + deployTxn := cluster.Deploy(t, target, bytecode) + require.NoError(t, deployTxn.Wait()) + require.True(t, deployTxn.Succeed()) + require.True(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) + } + + { + // Step 3. 'adminAddr' can create contracts + deployTxn := cluster.Deploy(t, admin, bytecode) + require.NoError(t, deployTxn.Wait()) + require.True(t, deployTxn.Succeed()) + require.True(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) + } + + { + // Step 4. 'adminAddr' sends a transaction to enable 'targetAddr'. + input, _ := addresslist.SetEnabledFunc.Encode([]interface{}{targetAddr}) + + adminSetTxn := cluster.MethodTxn(t, admin, contracts.BlockListContractsAddr, input) + require.NoError(t, adminSetTxn.Wait()) + expectRole(t, cluster, contracts.BlockListContractsAddr, targetAddr, addresslist.EnabledRole) + } + + { + // Step 5. 'targetAddr' **cannot** create contracts now as it's now blacklisted. + deployTxn := cluster.Deploy(t, target, bytecode) + require.NoError(t, deployTxn.Wait()) + require.True(t, deployTxn.Reverted()) + require.False(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) + } + + { + // Step 6. 'targetAddr' cannot enable other accounts since it is not an admin + // (The transaction fails) + input, _ := addresslist.SetEnabledFunc.Encode([]interface{}{types.ZeroAddress}) + + adminSetFailTxn := cluster.MethodTxn(t, target, contracts.BlockListContractsAddr, input) + require.NoError(t, adminSetFailTxn.Wait()) + require.True(t, adminSetFailTxn.Failed()) + expectRole(t, cluster, contracts.BlockListContractsAddr, types.ZeroAddress, addresslist.NoRole) + } +} + +func TestE2E_AllowList_Transactions(t *testing.T) { + // create two accounts, one for an admin sender and a second + // one for a non-enabled account that will switch on-off between + // both enabled and non-enabled roles. + admin, _ := wallet.GenerateKey() + target, _ := wallet.GenerateKey() + other, _ := wallet.GenerateKey() + + adminAddr := types.Address(admin.Address()) + targetAddr := types.Address(target.Address()) + otherAddr := types.Address(other.Address()) + + cluster := framework.NewTestCluster(t, 5, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, adminAddr)), + framework.WithPremine(adminAddr, targetAddr, otherAddr), + framework.WithTransactionsAllowListAdmin(adminAddr), + framework.WithTransactionsAllowListEnabled(otherAddr), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + // bytecode for an empty smart contract + bytecode, _ := hex.DecodeString("608060405234801561001057600080fd5b506103db806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80635e9f13f81461003b578063d78bca6914610059575b600080fd5b610043610089565b6040516100509190610217565b60405180910390f35b610073600480360381019061006e9190610263565b6100a1565b60405161008091906102a9565b60405180910390f35b73020000000000000000000000000000000000000081565b600080600073020000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16846040516024016100e29190610217565b6040516020818303038152906040527fd78bca69000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161016c9190610335565b6000604051808303816000865af19150503d80600081146101a9576040519150601f19603f3d011682016040523d82523d6000602084013e6101ae565b606091505b50915091506000818060200190518101906101c99190610378565b9050809350505050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610201826101d6565b9050919050565b610211816101f6565b82525050565b600060208201905061022c6000830184610208565b92915050565b600080fd5b610240816101f6565b811461024b57600080fd5b50565b60008135905061025d81610237565b92915050565b60006020828403121561027957610278610232565b5b60006102878482850161024e565b91505092915050565b6000819050919050565b6102a381610290565b82525050565b60006020820190506102be600083018461029a565b92915050565b600081519050919050565b600081905092915050565b60005b838110156102f85780820151818401526020810190506102dd565b60008484015250505050565b600061030f826102c4565b61031981856102cf565b93506103298185602086016102da565b80840191505092915050565b60006103418284610304565b915081905092915050565b61035581610290565b811461036057600080fd5b50565b6000815190506103728161034c565b92915050565b60006020828403121561038e5761038d610232565b5b600061039c84828501610363565b9150509291505056fea264697066735822122035f391b5c3dbf9a5e31072167a4ada71e9ba762650849f6320bc6150fa45aa9564736f6c63430008110033") + + { + // Step 0. Check the role of both accounts + expectRole(t, cluster, contracts.AllowListTransactionsAddr, adminAddr, addresslist.AdminRole) + expectRole(t, cluster, contracts.AllowListTransactionsAddr, targetAddr, addresslist.NoRole) + expectRole(t, cluster, contracts.AllowListTransactionsAddr, otherAddr, addresslist.EnabledRole) + } + + { + // Step 1. 'otherAddr' can send a normal transaction (non-contract creation). + otherTxn := cluster.Transfer(t, other, types.ZeroAddress, big.NewInt(1)) + require.NoError(t, otherTxn.Wait()) + require.True(t, otherTxn.Succeed()) + } + + { + // Step 2. 'targetAddr' **cannot** send a normal transaction because it is not whitelisted. + targetTxn := cluster.Transfer(t, target, types.ZeroAddress, big.NewInt(1)) + require.NoError(t, targetTxn.Wait()) + require.True(t, targetTxn.Reverted()) + } + + { + // Step 2.5. 'targetAddr' **cannot** deploy a contract because it is not whitelisted. + // (The transaction does not fail but the contract is not deployed and all gas + // for the transaction is consumed) + deployTxn := cluster.Deploy(t, target, bytecode) + require.NoError(t, deployTxn.Wait()) + require.True(t, deployTxn.Reverted()) + require.False(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) + } + + { + // Step 3. 'adminAddr' sends a transaction to enable 'targetAddr'. + input, _ := addresslist.SetEnabledFunc.Encode([]interface{}{targetAddr}) + + adminSetTxn := cluster.MethodTxn(t, admin, contracts.AllowListTransactionsAddr, input) + require.NoError(t, adminSetTxn.Wait()) + expectRole(t, cluster, contracts.AllowListTransactionsAddr, targetAddr, addresslist.EnabledRole) + } + + { + // Step 4. 'targetAddr' **can** send a normal transaction because it is whitelisted. + targetTxn := cluster.Transfer(t, target, types.ZeroAddress, big.NewInt(1)) + require.NoError(t, targetTxn.Wait()) + require.True(t, targetTxn.Succeed()) + } + + { + // Step 5. 'targetAddr' cannot enable other accounts since it is not an admin + // (The transaction fails) + input, _ := addresslist.SetEnabledFunc.Encode([]interface{}{types.ZeroAddress}) + + adminSetFailTxn := cluster.MethodTxn(t, target, contracts.AllowListTransactionsAddr, input) + require.NoError(t, adminSetFailTxn.Wait()) + require.True(t, adminSetFailTxn.Failed()) + expectRole(t, cluster, contracts.AllowListTransactionsAddr, types.ZeroAddress, addresslist.NoRole) + } + + { + // Step 6. 'adminAddr' sends a transaction to disable himself. + input, _ := addresslist.SetNoneFunc.Encode([]interface{}{adminAddr}) + + noneSetTxn := cluster.MethodTxn(t, admin, contracts.AllowListTransactionsAddr, input) + require.NoError(t, noneSetTxn.Wait()) + require.True(t, noneSetTxn.Failed()) + expectRole(t, cluster, contracts.AllowListTransactionsAddr, adminAddr, addresslist.AdminRole) + } +} + +func TestE2E_BlockList_Transactions(t *testing.T) { + // create two accounts, one for an admin sender and a second + // one for a non-enabled account that will switch on-off between + // both enabled and non-enabled roles. + admin, _ := wallet.GenerateKey() + target, _ := wallet.GenerateKey() + other, _ := wallet.GenerateKey() + + adminAddr := types.Address(admin.Address()) + targetAddr := types.Address(target.Address()) + otherAddr := types.Address(other.Address()) + + cluster := framework.NewTestCluster(t, 5, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, adminAddr)), + framework.WithPremine(adminAddr, targetAddr, otherAddr), + framework.WithTransactionsBlockListAdmin(adminAddr), + framework.WithTransactionsBlockListEnabled(otherAddr), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + { + // Step 0. Check the role of both accounts + expectRole(t, cluster, contracts.BlockListTransactionsAddr, adminAddr, addresslist.AdminRole) + expectRole(t, cluster, contracts.BlockListTransactionsAddr, targetAddr, addresslist.NoRole) + expectRole(t, cluster, contracts.BlockListTransactionsAddr, otherAddr, addresslist.EnabledRole) + } + + { + // Step 1. 'otherAddr' **cannot** send a normal transaction (non-contract creation) because it is blacklisted. + otherTxn := cluster.Transfer(t, other, types.ZeroAddress, big.NewInt(1)) + require.NoError(t, otherTxn.Wait()) + require.True(t, otherTxn.Reverted()) + } + + { + // Step 2. 'targetAddr' **can** send a normal transaction because it is not blacklisted. + targetTxn := cluster.Transfer(t, target, types.ZeroAddress, big.NewInt(1)) + require.NoError(t, targetTxn.Wait()) + require.True(t, targetTxn.Succeed()) + } + + { + // Step 3. 'targetAddr' cannot enable other accounts since it is not an admin + // (The transaction fails) + input, _ := addresslist.SetEnabledFunc.Encode([]interface{}{types.ZeroAddress}) + + adminSetFailTxn := cluster.MethodTxn(t, target, contracts.BlockListTransactionsAddr, input) + require.NoError(t, adminSetFailTxn.Wait()) + require.True(t, adminSetFailTxn.Failed()) + expectRole(t, cluster, contracts.BlockListTransactionsAddr, types.ZeroAddress, addresslist.NoRole) + } + + { + // Step 4. 'adminAddr' sends a transaction to enable 'targetAddr'. + input, _ := addresslist.SetEnabledFunc.Encode([]interface{}{targetAddr}) + + adminSetTxn := cluster.MethodTxn(t, admin, contracts.BlockListTransactionsAddr, input) + require.NoError(t, adminSetTxn.Wait()) + expectRole(t, cluster, contracts.BlockListTransactionsAddr, targetAddr, addresslist.EnabledRole) + } + + { + // Step 5. 'targetAddr' **cannot** send a normal transaction because it is blacklisted. + targetTxn := cluster.Transfer(t, target, types.ZeroAddress, big.NewInt(1)) + require.NoError(t, targetTxn.Wait()) + require.True(t, targetTxn.Reverted()) + } +} + +func TestE2E_AddressLists_Bridge(t *testing.T) { + // create two accounts, one for an admin sender and a second + // one for a non-enabled account that will switch on-off between + // both enabled and non-enabled roles. + admin, _ := wallet.GenerateKey() + target, _ := wallet.GenerateKey() + other, _ := wallet.GenerateKey() + + adminAddr := types.Address(admin.Address()) + targetAddr := types.Address(target.Address()) + otherAddr := types.Address(other.Address()) + + cluster := framework.NewTestCluster(t, 5, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, adminAddr)), + framework.WithPremine(adminAddr, targetAddr, otherAddr), + framework.WithBridgeAllowListAdmin(adminAddr), + framework.WithBridgeAllowListEnabled(otherAddr), + framework.WithBridgeBlockListAdmin(adminAddr), + framework.WithBridgeBlockListEnabled(otherAddr), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + { + // Step 0. Check the role of both accounts + expectRole(t, cluster, contracts.AllowListBridgeAddr, adminAddr, addresslist.AdminRole) + expectRole(t, cluster, contracts.AllowListBridgeAddr, targetAddr, addresslist.NoRole) + expectRole(t, cluster, contracts.AllowListBridgeAddr, otherAddr, addresslist.EnabledRole) + expectRole(t, cluster, contracts.BlockListBridgeAddr, adminAddr, addresslist.AdminRole) + expectRole(t, cluster, contracts.BlockListBridgeAddr, targetAddr, addresslist.NoRole) + expectRole(t, cluster, contracts.BlockListBridgeAddr, otherAddr, addresslist.EnabledRole) + } +} diff --git a/e2e-polybft/e2e/allowlist_test.go b/e2e-polybft/e2e/allowlist_test.go deleted file mode 100644 index 5978612354..0000000000 --- a/e2e-polybft/e2e/allowlist_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package e2e - -import ( - "math/big" - "testing" - - "github.com/0xPolygon/polygon-edge/contracts" - "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" - "github.com/0xPolygon/polygon-edge/helper/hex" - "github.com/0xPolygon/polygon-edge/state/runtime/allowlist" - "github.com/0xPolygon/polygon-edge/types" - "github.com/stretchr/testify/require" - "github.com/umbracle/ethgo/wallet" -) - -func TestAllowList_ContractDeployment(t *testing.T) { - // create two accounts, one for an admin sender and a second - // one for a non-enabled account that will switch on-off between - // both enabled and non-enabled roles. - admin, _ := wallet.GenerateKey() - target, _ := wallet.GenerateKey() - - adminAddr := types.Address(admin.Address()) - targetAddr := types.Address(target.Address()) - - otherAddr := types.Address{0x1} - - cluster := framework.NewTestCluster(t, 3, - framework.WithPremine(adminAddr, targetAddr), - framework.WithContractDeployerAllowListAdmin(adminAddr), - framework.WithContractDeployerAllowListEnabled(otherAddr), - ) - defer cluster.Stop() - - cluster.WaitForReady(t) - - // bytecode for an empty smart contract - bytecode, _ := hex.DecodeString("6080604052348015600f57600080fd5b50603e80601d6000396000f3fe6080604052600080fdfea265627a7a7231582027748e4afe5ee282a786005d286f4427f13dac1b62e03f9aed311c2db7e8245364736f6c63430005110032") - - expectRole := func(addr types.Address, role allowlist.Role) { - out := cluster.Call(t, contracts.AllowListContractsAddr, allowlist.ReadAllowListFunc, addr) - - num, ok := out["0"].(*big.Int) - if !ok { - t.Fatal("unexpected") - } - - require.Equal(t, role.Uint64(), num.Uint64()) - } - - { - // Step 0. Check the role of both accounts - expectRole(adminAddr, allowlist.AdminRole) - expectRole(targetAddr, allowlist.NoRole) - expectRole(otherAddr, allowlist.EnabledRole) - } - - { - // Step 1. 'targetAddr' can send a normal transaction (non-contract creation). - err := cluster.Transfer(t, target, types.ZeroAddress, big.NewInt(1)).Wait() - require.NoError(t, err) - } - - { - // Step 2. 'targetAddr' **cannot** deploy a contract because it is not whitelisted. - // (The transaction does not fail but the contract is not deployed and all gas - // for the transaction is consumed) - deployTxn := cluster.Deploy(t, target, bytecode) - require.NoError(t, deployTxn.Wait()) - require.True(t, deployTxn.Reverted()) - require.False(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) - } - - { - // Step 3. 'adminAddr' can create contracts - deployTxn := cluster.Deploy(t, admin, bytecode) - require.NoError(t, deployTxn.Wait()) - require.True(t, deployTxn.Succeed()) - require.True(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) - } - - { - // Step 4. 'adminAddr' sends a transaction to enable 'targetAddr'. - input, _ := allowlist.SetEnabledSignatureFunc.Encode([]interface{}{targetAddr}) - - adminSetTxn := cluster.MethodTxn(t, admin, contracts.AllowListContractsAddr, input) - require.NoError(t, adminSetTxn.Wait()) - expectRole(targetAddr, allowlist.EnabledRole) - } - - { - // Step 5. 'targetAddr' can create contracts now. - deployTxn := cluster.Deploy(t, target, bytecode) - require.NoError(t, deployTxn.Wait()) - require.True(t, deployTxn.Succeed()) - require.True(t, cluster.ExistsCode(t, deployTxn.Receipt().ContractAddress)) - } - - { - // Step 6. 'targetAddr' cannot enable other accounts since it is not an admin - // (The transaction fails) - input, _ := allowlist.SetEnabledSignatureFunc.Encode([]interface{}{types.ZeroAddress}) - - adminSetFailTxn := cluster.MethodTxn(t, target, contracts.AllowListContractsAddr, input) - require.NoError(t, adminSetFailTxn.Wait()) - require.True(t, adminSetFailTxn.Failed()) - expectRole(types.ZeroAddress, allowlist.NoRole) - } -} diff --git a/e2e-polybft/e2e/bridge_test.go b/e2e-polybft/e2e/bridge_test.go index fffa24d9d6..e6c33cf376 100644 --- a/e2e-polybft/e2e/bridge_test.go +++ b/e2e-polybft/e2e/bridge_test.go @@ -5,7 +5,6 @@ import ( "fmt" "math/big" "path" - "strconv" "strings" "testing" "time" @@ -14,35 +13,38 @@ import ( "github.com/umbracle/ethgo" ethgow "github.com/umbracle/ethgo/wallet" + "github.com/0xPolygon/polygon-edge/command" + "github.com/0xPolygon/polygon-edge/command/bridge/common" "github.com/0xPolygon/polygon-edge/command/genesis" - rootchainHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" "github.com/0xPolygon/polygon-edge/command/sidechain" "github.com/0xPolygon/polygon-edge/consensus/polybft" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" - + "github.com/0xPolygon/polygon-edge/state/runtime/addresslist" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" ) const ( - manifestFileName = "manifest.json" + chainConfigFileName = "genesis.json" ) -func TestE2E_Bridge_DepositAndWithdrawERC20(t *testing.T) { +func TestE2E_Bridge_Transfers(t *testing.T) { const ( - num = 10 + transfersCount = 5 amount = 100 numBlockConfirmations = 2 // make epoch size long enough, so that all exit events are processed within the same epoch - epochSize = 30 + epochSize = 30 + sprintSize = uint64(5) ) - receivers := make([]string, num) - amounts := make([]string, num) + receivers := make([]string, transfersCount) + amounts := make([]string, transfersCount) - for i := 0; i < num; i++ { + for i := 0; i < transfersCount; i++ { key, err := ethgow.GenerateKey() require.NoError(t, err) @@ -53,532 +55,969 @@ func TestE2E_Bridge_DepositAndWithdrawERC20(t *testing.T) { } cluster := framework.NewTestCluster(t, 5, - framework.WithBridge(), framework.WithNumBlockConfirmations(numBlockConfirmations), framework.WithEpochSize(epochSize)) defer cluster.Stop() cluster.WaitForReady(t) - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) - // DEPOSIT ERC20 TOKENS - // send a few transactions to the bridge - require.NoError( - t, - cluster.Bridge.DepositERC20( - manifest.RootchainConfig.RootNativeERC20Address, - manifest.RootchainConfig.RootERC20PredicateAddress, - strings.Join(receivers[:], ","), - strings.Join(amounts[:], ","), - ), - ) + validatorSrv := cluster.Servers[0] + senderAccount, err := sidechain.GetAccountFromDir(validatorSrv.DataDir()) + require.NoError(t, err) - // wait for a few more sprints - require.NoError(t, cluster.WaitForBlock(35, 2*time.Minute)) + childEthEndpoint := validatorSrv.JSONRPC().Eth() - // the transactions are processed and there should be a success events - var stateSyncedResult contractsapi.StateSyncResultEvent + // bridge some tokens for first validator to child chain + tokensToDeposit := ethgo.Ether(10) - id := stateSyncedResult.Sig() - filter := ðgo.LogFilter{ - Topics: [][]*ethgo.Hash{ - {&id}, - }, - } + require.NoError( + t, cluster.Bridge.Deposit( + common.ERC20, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, + rootHelper.TestAccountPrivKey, + senderAccount.Address().String(), + tokensToDeposit.String(), + "", + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), + ) - filter.SetFromUint64(0) - filter.SetToUint64(100) + // wait for a couple of sprints + finalBlockNum := 5 * sprintSize + require.NoError(t, cluster.WaitForBlock(finalBlockNum, 2*time.Minute)) - childEthEndpoint := cluster.Servers[0].JSONRPC().Eth() + // the transaction is processed and there should be a success event + var stateSyncedResult contractsapi.StateSyncResultEvent - logs, err := childEthEndpoint.GetLogs(filter) + logs, err := getFilteredLogs(stateSyncedResult.Sig(), 0, finalBlockNum, childEthEndpoint) require.NoError(t, err) // assert that all deposits are executed successfully - checkStateSyncResultLogs(t, logs, num) - - // check receivers balances got increased by deposited amount - for _, receiver := range receivers { - balance, err := childEthEndpoint.GetBalance(ethgo.Address(types.StringToAddress(receiver)), ethgo.Latest) - require.NoError(t, err) - require.Equal(t, big.NewInt(amount), balance) - } + checkStateSyncResultLogs(t, logs, 1) - t.Log("Deposits were successfully processed") - - // WITHDRAW ERC20 TOKENS - rootchainTxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) + // check validator balance got increased by deposited amount + balance, err := childEthEndpoint.GetBalance(ethgo.Address(senderAccount.Address()), ethgo.Latest) require.NoError(t, err) + require.Equal(t, tokensToDeposit, balance) + + t.Run("bridge ERC 20 tokens", func(t *testing.T) { + // DEPOSIT ERC20 TOKENS + // send a few transactions to the bridge + require.NoError( + t, + cluster.Bridge.Deposit( + common.ERC20, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, + rootHelper.TestAccountPrivKey, + strings.Join(receivers[:], ","), + strings.Join(amounts[:], ","), + "", + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), + ) + + finalBlockNum := 10 * sprintSize + // wait for a couple of sprints + require.NoError(t, cluster.WaitForBlock(finalBlockNum, 2*time.Minute)) + + // the transactions are processed and there should be a success events + var stateSyncedResult contractsapi.StateSyncResultEvent + + logs, err := getFilteredLogs(stateSyncedResult.Sig(), 0, finalBlockNum, childEthEndpoint) + require.NoError(t, err) - senderAccount, err := sidechain.GetAccountFromDir(cluster.Servers[0].DataDir()) - require.NoError(t, err) + // assert that all deposits are executed successfully + checkStateSyncResultLogs(t, logs, transfersCount+1) // because of the first deposit for the first validator - t.Logf("Withdraw sender: %s\n", senderAccount.Ecdsa.Address()) + // check receivers balances got increased by deposited amount + for _, receiver := range receivers { + balance, err := childEthEndpoint.GetBalance(ethgo.Address(types.StringToAddress(receiver)), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, big.NewInt(amount), balance) + } - rawKey, err := senderAccount.Ecdsa.MarshallPrivateKey() - require.NoError(t, err) + t.Log("Deposits were successfully processed") - // send withdraw transaction - err = cluster.Bridge.WithdrawERC20( - hex.EncodeToString(rawKey), - strings.Join(receivers[:], ","), - strings.Join(amounts[:], ","), - cluster.Servers[0].JSONRPCAddr()) - require.NoError(t, err) + // WITHDRAW ERC20 TOKENS + rootchainTxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) + require.NoError(t, err) - currentBlock, err := childEthEndpoint.GetBlockByNumber(ethgo.Latest, false) - require.NoError(t, err) + senderAccount, err := sidechain.GetAccountFromDir(validatorSrv.DataDir()) + require.NoError(t, err) - currentExtra, err := polybft.GetIbftExtra(currentBlock.ExtraData) - require.NoError(t, err) + t.Logf("Withdraw sender: %s\n", senderAccount.Ecdsa.Address()) - t.Logf("Latest block number: %d, epoch number: %d\n", currentBlock.Number, currentExtra.Checkpoint.EpochNumber) + rawKey, err := senderAccount.Ecdsa.MarshallPrivateKey() + require.NoError(t, err) - currentEpoch := currentExtra.Checkpoint.EpochNumber - fail := 0 + // send withdraw transaction + err = cluster.Bridge.Withdraw( + common.ERC20, + hex.EncodeToString(rawKey), + strings.Join(receivers[:], ","), + strings.Join(amounts[:], ","), + "", + validatorSrv.JSONRPCAddr(), + contracts.ChildERC20PredicateContract, + contracts.NativeERC20TokenContract, + false) + require.NoError(t, err) - // make sure we have progressed to the next epoch on the root chain - // before sending exit transaction to the root chain - // (it means that checkpoint was submitted) - for range time.Tick(time.Second) { - currentEpochString, err := ABICall(rootchainTxRelayer, contractsapi.CheckpointManager, - ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress), ethgo.ZeroAddress, "currentEpoch") + currentBlock, err := childEthEndpoint.GetBlockByNumber(ethgo.Latest, false) require.NoError(t, err) - rootchainEpoch, err := types.ParseUint64orHex(¤tEpochString) + currentExtra, err := polybft.GetIbftExtra(currentBlock.ExtraData) require.NoError(t, err) - if rootchainEpoch >= currentEpoch { - break + t.Logf("Latest block number: %d, epoch number: %d\n", currentBlock.Number, currentExtra.Checkpoint.EpochNumber) + + currentEpoch := currentExtra.Checkpoint.EpochNumber + + require.NoError(t, waitForRootchainEpoch(currentEpoch, 3*time.Minute, + rootchainTxRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) + + exitHelper := polybftCfg.Bridge.ExitHelperAddr + childJSONRPC := validatorSrv.JSONRPCAddr() + + for exitEventID := uint64(1); exitEventID <= transfersCount; exitEventID++ { + // send exit transaction to exit helper + err = cluster.Bridge.SendExitTransaction(exitHelper, exitEventID, childJSONRPC) + require.NoError(t, err) } - if fail > 300 { - t.Fatal("root chain hasn't progressed to the next epoch") + // assert that receiver's balances on RootERC20 smart contract are expected + for _, receiver := range receivers { + balance := erc20BalanceOf(t, types.StringToAddress(receiver), + polybftCfg.Bridge.RootNativeERC20Addr, rootchainTxRelayer) + require.Equal(t, big.NewInt(amount), balance) } - fail++ - } + }) - exitHelper := manifest.RootchainConfig.ExitHelperAddress - rootJSONRPC := cluster.Bridge.JSONRPCAddr() - childJSONRPC := cluster.Servers[0].JSONRPCAddr() + t.Run("multiple deposit batches per epoch", func(t *testing.T) { + const ( + depositsSubset = 1 + ) - for i := uint64(0); i < num; i++ { - exitEventID := i + 1 + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(validatorSrv.JSONRPC())) + require.NoError(t, err) - // send exit transaction to exit helper - err = cluster.Bridge.SendExitTransaction(exitHelper, exitEventID, rootJSONRPC, childJSONRPC) + lastCommittedIDMethod := contractsapi.StateReceiver.Abi.GetMethod("lastCommittedId") + lastCommittedIDInput, err := lastCommittedIDMethod.Encode([]interface{}{}) require.NoError(t, err) - // make sure exit event is processed successfully - isProcessed, err := isExitEventProcessed(exitEventID, ethgo.Address(exitHelper), rootchainTxRelayer) + // check that we submitted the minimal commitment to smart contract + commitmentIDRaw, err := txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(contracts.StateReceiverContract), lastCommittedIDInput) require.NoError(t, err) - require.True(t, isProcessed, fmt.Sprintf("exit event with ID %d was not processed", exitEventID)) - } - // assert that receiver's balances on RootERC20 smart contract are expected - for _, receiver := range receivers { - balanceInput, err := contractsapi.RootERC20.Abi.Methods["balanceOf"].Encode([]interface{}{receiver}) + initialCommittedID, err := types.ParseUint64orHex(&commitmentIDRaw) require.NoError(t, err) - balanceRaw, err := rootchainTxRelayer.Call(ethgo.ZeroAddress, - ethgo.Address(manifest.RootchainConfig.RootNativeERC20Address), balanceInput) + initialBlockNum, err := childEthEndpoint.BlockNumber() require.NoError(t, err) - balance, err := types.ParseUint256orHex(&balanceRaw) + // wait for next sprint block as the starting point, + // in order to be able to make assertions against blocks offseted by sprints + initialBlockNum = initialBlockNum + sprintSize - (initialBlockNum % sprintSize) + require.NoError(t, cluster.WaitForBlock(initialBlockNum, 1*time.Minute)) + + // send two transactions to the bridge so that we have a minimal commitment + require.NoError( + t, + cluster.Bridge.Deposit( + common.ERC20, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, + rootHelper.TestAccountPrivKey, + strings.Join(receivers[:depositsSubset], ","), + strings.Join(amounts[:depositsSubset], ","), + "", + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), + ) + + // wait for a few more sprints + midBlockNumber := initialBlockNum + 2*sprintSize + require.NoError(t, cluster.WaitForBlock(midBlockNumber, 2*time.Minute)) + + // check that we submitted the minimal commitment to smart contract + commitmentIDRaw, err = txRelayer.Call(ethgo.ZeroAddress, + ethgo.Address(contracts.StateReceiverContract), lastCommittedIDInput) require.NoError(t, err) - require.Equal(t, big.NewInt(amount), balance) - } + + lastCommittedID, err := types.ParseUint64orHex(&commitmentIDRaw) + require.NoError(t, err) + require.Equal(t, initialCommittedID+depositsSubset, lastCommittedID) + + // send some more transactions to the bridge to build another commitment in epoch + require.NoError( + t, + cluster.Bridge.Deposit( + common.ERC20, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, + rootHelper.TestAccountPrivKey, + strings.Join(receivers[depositsSubset:], ","), + strings.Join(amounts[depositsSubset:], ","), + "", + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), + ) + + finalBlockNum := midBlockNumber + 5*sprintSize + // wait for a few more sprints + require.NoError(t, cluster.WaitForBlock(midBlockNumber+5*sprintSize, 3*time.Minute)) + + // check that we submitted the minimal commitment to smart contract + commitmentIDRaw, err = txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(contracts.StateReceiverContract), lastCommittedIDInput) + require.NoError(t, err) + + // check that the second (larger commitment) was also submitted in epoch + lastCommittedID, err = types.ParseUint64orHex(&commitmentIDRaw) + require.NoError(t, err) + require.Equal(t, initialCommittedID+uint64(transfersCount), lastCommittedID) + + // the transactions are mined and state syncs should be executed by the relayer + // and there should be a success events + var stateSyncedResult contractsapi.StateSyncResultEvent + + logs, err := getFilteredLogs(stateSyncedResult.Sig(), initialBlockNum, finalBlockNum, childEthEndpoint) + require.NoError(t, err) + + // assert that all state syncs are executed successfully + checkStateSyncResultLogs(t, logs, transfersCount) + }) } -func TestE2E_Bridge_MultipleCommitmentsPerEpoch(t *testing.T) { - const depositsCount = 10 +func TestE2E_Bridge_ERC721Transfer(t *testing.T) { + const ( + transfersCount = 4 + epochSize = 5 + ) + + minter, err := ethgow.GenerateKey() + require.NoError(t, err) - receivers := make([]string, depositsCount) - amounts := make([]string, depositsCount) + receiverKeys := make([]string, transfersCount) + receivers := make([]string, transfersCount) + receiversAddrs := make([]types.Address, transfersCount) + tokenIDs := make([]string, transfersCount) - for i := 0; i < depositsCount; i++ { + for i := 0; i < transfersCount; i++ { key, err := ethgow.GenerateKey() require.NoError(t, err) + rawKey, err := key.MarshallPrivateKey() + require.NoError(t, err) + + receiverKeys[i] = hex.EncodeToString(rawKey) receivers[i] = types.Address(key.Address()).String() - amounts[i] = fmt.Sprintf("%d", 100) + receiversAddrs[i] = types.Address(key.Address()) + tokenIDs[i] = fmt.Sprintf("%d", i) + + t.Logf("Receiver#%d=%s\n", i+1, receivers[i]) } cluster := framework.NewTestCluster(t, 5, - framework.WithBridge(), - framework.WithEpochSize(30)) + framework.WithEpochSize(epochSize), + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, minter.Address())), + framework.WithPremine(types.Address(minter.Address())), + framework.WithPremine(receiversAddrs...)) defer cluster.Stop() - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) - require.NoError(t, err) - cluster.WaitForReady(t) - // send two transactions to the bridge so that we have a minimal commitment - require.NoError( - t, - cluster.Bridge.DepositERC20( - manifest.RootchainConfig.RootNativeERC20Address, - manifest.RootchainConfig.RootERC20PredicateAddress, - strings.Join(receivers[:2], ","), - strings.Join(amounts[:2], ","), - ), - ) - - // wait for a few more sprints - require.NoError(t, cluster.WaitForBlock(10, 2*time.Minute)) - - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(cluster.Servers[0].JSONRPC())) + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) - lastCommittedIDMethod := contractsapi.StateReceiver.Abi.GetMethod("lastCommittedId") - encode, err := lastCommittedIDMethod.Encode([]interface{}{}) + rootchainTxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) - // check that we submitted the minimal commitment to smart contract - result, err := txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(contracts.StateReceiverContract), encode) + rootchainDeployer, err := rootHelper.DecodePrivateKey("") require.NoError(t, err) - lastCommittedID, err := strconv.ParseUint(result, 0, 64) + // deploy root ERC 721 token + deployTxn := ðgo.Transaction{To: nil, Input: contractsapi.RootERC721.Bytecode} + receipt, err := rootchainTxRelayer.SendTransaction(deployTxn, rootchainDeployer) require.NoError(t, err) - require.Equal(t, uint64(2), lastCommittedID) - // send some more transactions to the bridge to build another commitment in epoch + rootERC721Addr := receipt.ContractAddress + + // DEPOSIT ERC721 TOKENS + // send a few transactions to the bridge require.NoError( t, - cluster.Bridge.DepositERC20( - manifest.RootchainConfig.RootNativeERC20Address, - manifest.RootchainConfig.RootERC20PredicateAddress, - strings.Join(receivers[2:], ","), - strings.Join(amounts[2:], ","), - ), + cluster.Bridge.Deposit( + common.ERC721, + types.Address(rootERC721Addr), + polybftCfg.Bridge.RootERC721PredicateAddr, + rootHelper.TestAccountPrivKey, + strings.Join(receivers[:], ","), + "", + strings.Join(tokenIDs[:], ","), + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), ) // wait for a few more sprints - require.NoError(t, cluster.WaitForBlock(40, 3*time.Minute)) + require.NoError(t, cluster.WaitForBlock(50, 4*time.Minute)) - // check that we submitted the minimal commitment to smart contract - result, err = txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(contracts.StateReceiverContract), encode) - require.NoError(t, err) + validatorSrv := cluster.Servers[0] + childEthEndpoint := validatorSrv.JSONRPC().Eth() - // check that the second (larger commitment) was also submitted in epoch - lastCommittedID, err = strconv.ParseUint(result, 0, 64) - require.NoError(t, err) - require.Equal(t, uint64(depositsCount), lastCommittedID) - - // the transactions are mined and state syncs should be executed by the relayer - // and there should be a success events + // the transactions are processed and there should be a success events var stateSyncedResult contractsapi.StateSyncResultEvent - id := stateSyncedResult.Sig() - filter := ðgo.LogFilter{ - Topics: [][]*ethgo.Hash{ - {&id}, - }, - } - - filter.SetFromUint64(0) - filter.SetToUint64(100) - - logs, err := cluster.Servers[0].JSONRPC().Eth().GetLogs(filter) + logs, err := getFilteredLogs(stateSyncedResult.Sig(), 0, 50, childEthEndpoint) require.NoError(t, err) - // assert that all state syncs are executed successfully - checkStateSyncResultLogs(t, logs, depositsCount) -} - -func TestE2E_CheckpointSubmission(t *testing.T) { - // spin up a cluster with epoch size set to 5 blocks - cluster := framework.NewTestCluster(t, 5, framework.WithBridge(), framework.WithEpochSize(5)) - defer cluster.Stop() - - // initialize tx relayer used to query CheckpointManager smart contract - l1Relayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(validatorSrv.JSONRPC())) require.NoError(t, err) - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) - require.NoError(t, err) + // assert that all deposits are executed successfully. + // All deposits are sent using a single transaction, so arbitrary message bridge emits two state sync events: + // MAP_TOKEN_SIG and DEPOSIT_BATCH_SIG state sync events + checkStateSyncResultLogs(t, logs, 2) - checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) + // retrieve child token address (from both chains, and assert they are the same) + l1ChildTokenAddr := getChildToken(t, contractsapi.RootERC721Predicate.Abi, polybftCfg.Bridge.RootERC721PredicateAddr, + types.Address(rootERC721Addr), rootchainTxRelayer) + l2ChildTokenAddr := getChildToken(t, contractsapi.ChildERC721Predicate.Abi, contracts.ChildERC721PredicateContract, + types.Address(rootERC721Addr), txRelayer) - testCheckpointBlockNumber := func(expectedCheckpointBlock uint64) (bool, error) { - actualCheckpointBlock, err := getCheckpointBlockNumber(l1Relayer, checkpointManagerAddr) - if err != nil { - return false, err - } - - t.Logf("Checkpoint block: %d\n", actualCheckpointBlock) + t.Log("L1 child token", l1ChildTokenAddr) + t.Log("L2 child token", l2ChildTokenAddr) + require.Equal(t, l1ChildTokenAddr, l2ChildTokenAddr) - return actualCheckpointBlock == expectedCheckpointBlock, nil + for i, receiver := range receiversAddrs { + owner := erc721OwnerOf(t, big.NewInt(int64(i)), l2ChildTokenAddr, txRelayer) + require.Equal(t, receiver, owner) } - // wait for a single epoch to be checkpointed - require.NoError(t, cluster.WaitForBlock(7, 30*time.Second)) + t.Log("Deposits were successfully processed") - // checking last checkpoint block before rootchain server stop - err = cluster.Bridge.WaitUntil(2*time.Second, 30*time.Second, func() (bool, error) { - return testCheckpointBlockNumber(5) - }) + // WITHDRAW ERC721 TOKENS + for i, receiverKey := range receiverKeys { + // send withdraw transactions + err = cluster.Bridge.Withdraw( + common.ERC721, + receiverKey, + receivers[i], + "", + tokenIDs[i], + validatorSrv.JSONRPCAddr(), + contracts.ChildERC721PredicateContract, + l2ChildTokenAddr, + false) + require.NoError(t, err) + } + + currentBlock, err := childEthEndpoint.GetBlockByNumber(ethgo.Latest, false) require.NoError(t, err) - // stop rootchain server - cluster.Bridge.Stop() + currentExtra, err := polybft.GetIbftExtra(currentBlock.ExtraData) + require.NoError(t, err) - // wait for a couple of epochs so that there are pending checkpoint (epoch-ending) blocks - require.NoError(t, cluster.WaitForBlock(21, 2*time.Minute)) + t.Logf("Latest block number: %d, epoch number: %d\n", currentBlock.Number, currentExtra.Checkpoint.EpochNumber) - // restart rootchain server - require.NoError(t, cluster.Bridge.Start()) + currentEpoch := currentExtra.Checkpoint.EpochNumber + require.NoError(t, waitForRootchainEpoch(currentEpoch, 3*time.Minute, rootchainTxRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) - // check if pending checkpoint blocks were submitted (namely the last checkpointed block must be block 20) - err = cluster.Bridge.WaitUntil(2*time.Second, 50*time.Second, func() (bool, error) { - return testCheckpointBlockNumber(20) - }) - require.NoError(t, err) -} + exitHelper := polybftCfg.Bridge.ExitHelperAddr + childJSONRPC := validatorSrv.JSONRPCAddr() -// getCheckpointBlockNumber gets current checkpoint block number from checkpoint manager smart contract -func getCheckpointBlockNumber(l1Relayer txrelayer.TxRelayer, checkpointManagerAddr ethgo.Address) (uint64, error) { - checkpointBlockNumRaw, err := ABICall(l1Relayer, contractsapi.CheckpointManager, - checkpointManagerAddr, ethgo.ZeroAddress, "currentCheckpointBlockNumber") - if err != nil { - return 0, err + for exitEventID := uint64(1); exitEventID <= transfersCount; exitEventID++ { + // send exit transaction to exit helper + err = cluster.Bridge.SendExitTransaction(exitHelper, exitEventID, childJSONRPC) + require.NoError(t, err) } - actualCheckpointBlock, err := types.ParseUint64orHex(&checkpointBlockNumRaw) - if err != nil { - return 0, err + // assert that owners of given token ids are the accounts on the root chain ERC 721 token + for i, receiver := range receiversAddrs { + owner := erc721OwnerOf(t, big.NewInt(int64(i)), types.Address(rootERC721Addr), rootchainTxRelayer) + require.Equal(t, receiver, owner) } - - return actualCheckpointBlock, nil } -func TestE2E_Bridge_L2toL1Exit(t *testing.T) { +func TestE2E_Bridge_ERC1155Transfer(t *testing.T) { const ( - userNumber = 10 - epochSize = 30 - checkpointBlock = uint64(epochSize) - checkpointEpoch = uint64(1) + transfersCount = 5 + amount = 100 + epochSize = 5 ) - sidechainKeys := make([]*ethgow.Key, userNumber) - accountAddress := make([]types.Address, userNumber) + minter, err := ethgow.GenerateKey() + require.NoError(t, err) + + receiverKeys := make([]string, transfersCount) + receivers := make([]string, transfersCount) + receiversAddrs := make([]types.Address, transfersCount) + amounts := make([]string, transfersCount) + tokenIDs := make([]string, transfersCount) - for i := 0; i < userNumber; i++ { + for i := 0; i < transfersCount; i++ { key, err := ethgow.GenerateKey() require.NoError(t, err) - sidechainKeys[i] = key - accountAddress[i] = types.Address(key.Address()) - } + rawKey, err := key.MarshallPrivateKey() + require.NoError(t, err) - // use test account for rootchain - rootchainKey, err := rootchainHelper.GetRootchainPrivateKey("") - require.NoError(t, err) + receiverKeys[i] = hex.EncodeToString(rawKey) + receivers[i] = types.Address(key.Address()).String() + receiversAddrs[i] = types.Address(key.Address()) + amounts[i] = fmt.Sprintf("%d", amount) + tokenIDs[i] = fmt.Sprintf("%d", i+1) + + t.Logf("Receiver#%d=%s\n", i+1, receivers[i]) + } cluster := framework.NewTestCluster(t, 5, - framework.WithBridge(), - framework.WithPremine(accountAddress...), + framework.WithNumBlockConfirmations(0), framework.WithEpochSize(epochSize), - ) - + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, minter.Address())), + framework.WithPremine(types.Address(minter.Address())), + framework.WithPremine(receiversAddrs...)) defer cluster.Stop() - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) + cluster.WaitForReady(t) + + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) - checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) - exitHelperAddr := ethgo.Address(manifest.RootchainConfig.ExitHelperAddress) + rootchainTxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) + require.NoError(t, err) - cluster.WaitForReady(t) + rootchainDeployer, err := rootHelper.DecodePrivateKey("") + require.NoError(t, err) - // init rpc clients - l1TxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(txrelayer.DefaultRPCAddress)) + // deploy root ERC 1155 token + deployTxn := ðgo.Transaction{To: nil, Input: contractsapi.RootERC1155.Bytecode} + receipt, err := rootchainTxRelayer.SendTransaction(deployTxn, rootchainDeployer) require.NoError(t, err) - l2TxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Servers[0].JSONRPCAddr())) + + rootERC1155Addr := receipt.ContractAddress + + // DEPOSIT ERC1155 TOKENS + // send a few transactions to the bridge + require.NoError( + t, + cluster.Bridge.Deposit( + common.ERC1155, + types.Address(rootERC1155Addr), + polybftCfg.Bridge.RootERC1155PredicateAddr, + rootHelper.TestAccountPrivKey, + strings.Join(receivers[:], ","), + strings.Join(amounts[:], ","), + strings.Join(tokenIDs[:], ","), + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), + ) + + // wait for a few more sprints + require.NoError(t, cluster.WaitForBlock(50, 4*time.Minute)) + + validatorSrv := cluster.Servers[0] + childEthEndpoint := validatorSrv.JSONRPC().Eth() + + // the transactions are processed and there should be a success events + var stateSyncedResult contractsapi.StateSyncResultEvent + + logs, err := getFilteredLogs(stateSyncedResult.Sig(), 0, 50, childEthEndpoint) require.NoError(t, err) - // deploy L1ExitTest contract - receipt, err := l1TxRelayer.SendTransaction(ðgo.Transaction{Input: contractsapi.TestL1StateReceiver.Bytecode}, - rootchainKey) + txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(validatorSrv.JSONRPC())) require.NoError(t, err) - require.Equal(t, receipt.Status, uint64(types.ReceiptSuccess)) - l1ExitTestAddr := receipt.ContractAddress - l2StateSenderAddress := ethgo.Address(contracts.L2StateSenderContract) + // assert that all deposits are executed successfully. + // All deposits are sent using a single transaction, so arbitrary message bridge emits two state sync events: + // MAP_TOKEN_SIG and DEPOSIT_BATCH_SIG state sync events + checkStateSyncResultLogs(t, logs, 2) + + // retrieve child token address + l1ChildTokenAddr := getChildToken(t, contractsapi.RootERC1155Predicate.Abi, polybftCfg.Bridge.RootERC1155PredicateAddr, + types.Address(rootERC1155Addr), rootchainTxRelayer) + l2ChildTokenAddr := getChildToken(t, contractsapi.ChildERC1155Predicate.Abi, contracts.ChildERC1155PredicateContract, + types.Address(rootERC1155Addr), txRelayer) + + t.Log("L1 child token", l1ChildTokenAddr) + t.Log("L2 child token", l2ChildTokenAddr) + require.Equal(t, l1ChildTokenAddr, l2ChildTokenAddr) + + // check receivers balances got increased by deposited amount + for i, receiver := range receivers { + balanceOfFn := &contractsapi.BalanceOfChildERC1155Fn{ + Account: types.StringToAddress(receiver), + ID: big.NewInt(int64(i + 1)), + } + + balanceInput, err := balanceOfFn.EncodeAbi() + require.NoError(t, err) - // Start test - // send crosschain transaction on l2 and get exit id - stateSenderData := []byte{123} - for i := 0; i < userNumber; i++ { - receipt, err := ABITransaction(l2TxRelayer, sidechainKeys[i], contractsapi.L2StateSender, l2StateSenderAddress, "syncState", l1ExitTestAddr, stateSenderData) + balanceRaw, err := txRelayer.Call(ethgo.ZeroAddress, ethgo.Address(l2ChildTokenAddr), balanceInput) require.NoError(t, err) - require.Equal(t, receipt.Status, uint64(types.ReceiptSuccess)) + + balance, err := types.ParseUint256orHex(&balanceRaw) + require.NoError(t, err) + require.Equal(t, big.NewInt(int64(amount)), balance) } - require.NoError(t, cluster.WaitForBlock(epochSize, 2*time.Minute)) + t.Log("Deposits were successfully processed") - fail := 0 + // WITHDRAW ERC1155 TOKENS + senderAccount, err := sidechain.GetAccountFromDir(cluster.Servers[0].DataDir()) + require.NoError(t, err) - for range time.Tick(time.Second) { - currentEpochString, err := ABICall(l1TxRelayer, contractsapi.CheckpointManager, checkpointManagerAddr, ethgo.ZeroAddress, "currentEpoch") - require.NoError(t, err) + t.Logf("Withdraw sender: %s\n", senderAccount.Ecdsa.Address()) - currentEpoch, err := types.ParseUint64orHex(¤tEpochString) + for i, receiverKey := range receiverKeys { + // send withdraw transactions + err = cluster.Bridge.Withdraw( + common.ERC1155, + receiverKey, + receivers[i], + amounts[i], + tokenIDs[i], + validatorSrv.JSONRPCAddr(), + contracts.ChildERC1155PredicateContract, + l2ChildTokenAddr, + false) require.NoError(t, err) + } - if currentEpoch >= checkpointEpoch { - break - } + currentBlock, err := childEthEndpoint.GetBlockByNumber(ethgo.Latest, false) + require.NoError(t, err) - if fail > 300 { - t.Fatal("epoch havent achieved") - } - fail++ + currentExtra, err := polybft.GetIbftExtra(currentBlock.ExtraData) + require.NoError(t, err) + + currentEpoch := currentExtra.Checkpoint.EpochNumber + t.Logf("Latest block number: %d, epoch number: %d\n", currentBlock.Number, currentExtra.Checkpoint.EpochNumber) + + require.NoError(t, waitForRootchainEpoch(currentEpoch, 3*time.Minute, + rootchainTxRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) + + exitHelper := polybftCfg.Bridge.ExitHelperAddr + childJSONRPC := validatorSrv.JSONRPCAddr() + + for exitEventID := uint64(1); exitEventID <= transfersCount; exitEventID++ { + // send exit transaction to exit helper + err = cluster.Bridge.SendExitTransaction(exitHelper, exitEventID, childJSONRPC) + require.NoError(t, err) } - var proof types.Proof + // assert that receiver's balances on RootERC1155 smart contract are expected + for i, receiver := range receivers { + balanceOfFn := &contractsapi.BalanceOfRootERC1155Fn{ + Account: types.StringToAddress(receiver), + ID: big.NewInt(int64(i + 1)), + } - for i := 0; i < userNumber; i++ { - exitID := uint64(i + 1) // because exit events start from ID = 1 - proof, err = getExitProof(cluster.Servers[0].JSONRPCAddr(), exitID) + balanceInput, err := balanceOfFn.EncodeAbi() require.NoError(t, err) - isProcessed, err := sendExitTransaction(sidechainKeys[i], rootchainKey, proof, checkpointBlock, stateSenderData, l1ExitTestAddr, exitHelperAddr, l1TxRelayer, exitID) + balanceRaw, err := rootchainTxRelayer.Call(ethgo.ZeroAddress, rootERC1155Addr, balanceInput) require.NoError(t, err) - require.True(t, isProcessed) + + balance, err := types.ParseUint256orHex(&balanceRaw) + require.NoError(t, err) + require.Equal(t, big.NewInt(amount), balance) } } -func TestE2E_Bridge_L2toL1ExitMultiple(t *testing.T) { +func TestE2E_Bridge_ChildChainMintableTokensTransfer(t *testing.T) { const ( - userNumber = 6 - epochSize = 10 - roundNumber = 3 - checkpointBlock = uint64(epochSize) - checkpointEpoch = uint64(1) + transfersCount = uint64(4) + amount = 100 + // make epoch size long enough, so that all exit events are processed within the same epoch + epochSize = 30 + sprintSize = uint64(5) ) - exitEventIds := make([]uint64, userNumber*roundNumber) - sidechainKeys := make([]*ethgow.Key, userNumber) - accountAddress := make([]types.Address, userNumber) + // init private keys and amounts + depositorKeys := make([]string, transfersCount) + depositors := make([]types.Address, transfersCount) + amounts := make([]string, transfersCount) + funds := make([]*big.Int, transfersCount) + singleToken := ethgo.Ether(1) - for i := 0; i < userNumber; i++ { + admin, err := ethgow.GenerateKey() + require.NoError(t, err) + + adminAddr := types.Address(admin.Address()) + + for i := uint64(0); i < transfersCount; i++ { key, err := ethgow.GenerateKey() require.NoError(t, err) - sidechainKeys[i] = key - accountAddress[i] = types.Address(key.Address()) - } + rawKey, err := key.MarshallPrivateKey() + require.NoError(t, err) - // use test account for rootchain - rootchainKey, err := rootchainHelper.GetRootchainPrivateKey("") - require.NoError(t, err) + depositorKeys[i] = hex.EncodeToString(rawKey) + depositors[i] = types.Address(key.Address()) + funds[i] = singleToken + amounts[i] = fmt.Sprintf("%d", amount) + + t.Logf("Depositor#%d=%s\n", i+1, depositors[i]) + } + // setup cluster cluster := framework.NewTestCluster(t, 5, - framework.WithBridge(), - framework.WithPremine(accountAddress...), + framework.WithNumBlockConfirmations(0), framework.WithEpochSize(epochSize), - ) + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, adminAddr)), + framework.WithBridgeAllowListAdmin(adminAddr), + framework.WithBridgeBlockListAdmin(adminAddr), + framework.WithPremine(append(depositors, adminAddr)...)) //nolint:makezero defer cluster.Stop() - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) - checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) - exitHelperAddr := ethgo.Address(manifest.RootchainConfig.ExitHelperAddress) + validatorSrv := cluster.Servers[0] + childEthEndpoint := validatorSrv.JSONRPC().Eth() + + // fund accounts on rootchain + require.NoError(t, validatorSrv.RootchainFundFor(depositors, funds, polybftCfg.Bridge.StakeTokenAddr)) cluster.WaitForReady(t) - // init rpc clients - l1TxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(txrelayer.DefaultRPCAddress)) - require.NoError(t, err) - l2TxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Servers[0].JSONRPCAddr())) + rootchainTxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) - // deploy L1ExitTest contract - receipt, err := l1TxRelayer.SendTransaction( - ðgo.Transaction{Input: contractsapi.TestL1StateReceiver.Bytecode}, - rootchainKey) + childchainTxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(validatorSrv.JSONRPC())) require.NoError(t, err) - require.Equal(t, receipt.Status, uint64(types.ReceiptSuccess)) - l1ExitTestAddr := receipt.ContractAddress - l2StateSenderAddress := ethgo.Address(contracts.L2StateSenderContract) + var mintableTokenMapped contractsapi.MintableTokenMappedEvent + + t.Run("bridge native tokens", func(t *testing.T) { + // rootToken represents deposit token (basically native mintable token from the Supernets) + rootToken := contracts.NativeERC20TokenContract + + // try sending a single native token deposit transaction + // it should fail, because depositors are not allow listed for bridge transactions + err = cluster.Bridge.Deposit( + common.ERC20, + rootToken, + contracts.RootMintableERC20PredicateContract, + depositorKeys[0], + depositors[0].String(), + amounts[0], + "", + validatorSrv.JSONRPCAddr(), + "", + true) + require.Error(t, err) + + // allow list each depositor and make sure deposit is successfully executed + for i, key := range depositorKeys { + // add all depositors to bridge allow list + setAccessListRole(t, cluster, contracts.AllowListBridgeAddr, depositors[i], addresslist.EnabledRole, admin) + + // make sure deposit is successfully executed + err = cluster.Bridge.Deposit( + common.ERC20, + rootToken, + contracts.RootMintableERC20PredicateContract, + key, + depositors[i].String(), + amounts[i], + "", + validatorSrv.JSONRPCAddr(), + "", + true) + require.NoError(t, err) + } - // Start test - // send crosschain transaction on l2 and get exit id - stateSenderData := []byte{123} - addTransaction := func(j, i uint64) { - receipt, err := ABITransaction(l2TxRelayer, sidechainKeys[j], contractsapi.L2StateSender, l2StateSenderAddress, "syncState", l1ExitTestAddr, stateSenderData) + latestBlock, err := childEthEndpoint.GetBlockByNumber(ethgo.Latest, false) require.NoError(t, err) - require.Equal(t, receipt.Status, uint64(types.ReceiptSuccess)) - eventData, err := contractsapi.L2StateSender.Abi.Events["L2StateSynced"].ParseLog(receipt.Logs[0]) + extra, err := polybft.GetIbftExtra(latestBlock.ExtraData) require.NoError(t, err) - exitEventIds[j+(i-1)*userNumber] = eventData["id"].(*big.Int).Uint64() //nolint:forcetypeassert - } + // wait for checkpoint to get submitted before invoking exit transactions + require.NoError(t, + waitForRootchainEpoch(extra.Checkpoint.EpochNumber, 2*time.Minute, rootchainTxRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) - for i := 1; i <= roundNumber; i++ { - for j := 0; j < userNumber; j++ { - go addTransaction(uint64(j), uint64(i)) + // first exit event is mapping child token on a rootchain + // remaining ones are deposits + for exitEventID := uint64(1); exitEventID <= transfersCount+1; exitEventID++ { + require.NoError(t, + cluster.Bridge.SendExitTransaction(polybftCfg.Bridge.ExitHelperAddr, exitEventID, validatorSrv.JSONRPCAddr())) } - require.NoError(t, cluster.WaitForBlock(uint64((i)*epochSize), 2*time.Minute)) - fail := 0 + rootchainLatestBlock, err := rootchainTxRelayer.Client().Eth().BlockNumber() + require.NoError(t, err) + + // retrieve child mintable token address from both chains and make sure they are the same + l1ChildToken := getChildToken(t, contractsapi.ChildMintableERC20Predicate.Abi, polybftCfg.Bridge.ChildMintableERC20PredicateAddr, + rootToken, rootchainTxRelayer) + l2ChildToken := getChildToken(t, contractsapi.RootMintableERC20Predicate.Abi, contracts.RootMintableERC20PredicateContract, + rootToken, childchainTxRelayer) + + t.Log("L1 child token", l1ChildToken) + t.Log("L2 child token", l2ChildToken) + require.Equal(t, l1ChildToken, l2ChildToken) - for range time.Tick(time.Second) { - currentEpochString, err := ABICall(l1TxRelayer, contractsapi.CheckpointManager, checkpointManagerAddr, ethgo.ZeroAddress, "currentEpoch") + logs, err := getFilteredLogs(mintableTokenMapped.Sig(), 0, rootchainLatestBlock, rootchainTxRelayer.Client().Eth()) + require.NoError(t, err) + require.Len(t, logs, 1) + + // check that balances on rootchain have increased by deposited amounts + for _, depositor := range depositors { + balance := erc20BalanceOf(t, depositor, l1ChildToken, rootchainTxRelayer) + require.Equal(t, big.NewInt(amount), balance) + } + + balancesBefore := make([]*big.Int, transfersCount) + for i := uint64(0); i < transfersCount; i++ { + balancesBefore[i], err = childEthEndpoint.GetBalance(ethgo.Address(depositors[i]), ethgo.Latest) require.NoError(t, err) + } - currentEpoch, err := types.ParseUint64orHex(¤tEpochString) + // withdraw child token on the rootchain + for i, depositorKey := range depositorKeys { + err = cluster.Bridge.Withdraw( + common.ERC20, + depositorKey, + depositors[i].String(), + amounts[i], + "", + cluster.Bridge.JSONRPCAddr(), + polybftCfg.Bridge.ChildMintableERC20PredicateAddr, + l1ChildToken, + true) require.NoError(t, err) + } - if currentEpoch >= uint64(i)*checkpointEpoch { - break - } + blockNum, err := childEthEndpoint.BlockNumber() + require.NoError(t, err) - if fail > 300 { - t.Fatal("epoch havent achieved") - } - fail++ + // wait a couple of sprints to finalize state sync events + require.NoError(t, cluster.WaitForBlock(blockNum+3*sprintSize, 2*time.Minute)) + + // check that balances on the child chain are correct + for i, receiver := range depositors { + balance := erc20BalanceOf(t, receiver, contracts.NativeERC20TokenContract, childchainTxRelayer) + t.Log("Balance before", balancesBefore[i], "Balance after", balance) + require.Equal(t, balance, balancesBefore[i].Add(balancesBefore[i], big.NewInt(amount))) } - } + }) - var proof types.Proof + t.Run("bridge ERC 721 tokens", func(t *testing.T) { + rootchainInitialBlock, err := rootchainTxRelayer.Client().Eth().BlockNumber() + require.NoError(t, err) - for i := 0; i < roundNumber; i++ { - for j := 0; j < userNumber; j++ { - proof, err = getExitProof(cluster.Servers[0].JSONRPCAddr(), exitEventIds[j+i*userNumber]) + exitEventsCounterFn := contractsapi.L2StateSender.Abi.Methods["counter"] + input, err := exitEventsCounterFn.Encode([]interface{}{}) + require.NoError(t, err) + initialExitEventIDRaw, err := childchainTxRelayer.Call(ethgo.ZeroAddress, ethgo.Address(contracts.L2StateSenderContract), input) + require.NoError(t, err) + initialExitEventID, err := types.ParseUint64orHex(&initialExitEventIDRaw) + require.NoError(t, err) + + erc721DeployTxn := cluster.Deploy(t, admin, contractsapi.RootERC721.Bytecode) + require.NoError(t, erc721DeployTxn.Wait()) + require.True(t, erc721DeployTxn.Succeed()) + rootERC721Token := erc721DeployTxn.Receipt().ContractAddress + + for _, depositor := range depositors { + // mint all the depositors in advance + mintFn := &contractsapi.MintRootERC721Fn{To: depositor} + mintInput, err := mintFn.EncodeAbi() require.NoError(t, err) - isProcessed, err := sendExitTransaction(sidechainKeys[j], rootchainKey, proof, uint64(i+1)*checkpointBlock, stateSenderData, l1ExitTestAddr, exitHelperAddr, l1TxRelayer, exitEventIds[j+i*userNumber]) + + mintTxn := cluster.MethodTxn(t, admin, types.Address(rootERC721Token), mintInput) + require.NoError(t, mintTxn.Wait()) + require.True(t, mintTxn.Succeed()) + + // add all depositors to bride block list + setAccessListRole(t, cluster, contracts.BlockListBridgeAddr, depositor, addresslist.EnabledRole, admin) + } + + // deposit should fail because depositors are in bridge block list + err = cluster.Bridge.Deposit( + common.ERC721, + types.Address(rootERC721Token), + contracts.RootMintableERC721PredicateContract, + depositorKeys[0], + depositors[0].String(), + "", + fmt.Sprintf("%d", 0), + validatorSrv.JSONRPCAddr(), + "", + true) + require.Error(t, err) + + for i, depositorKey := range depositorKeys { + // add all depositors to the bridge allow list + setAccessListRole(t, cluster, contracts.AllowListBridgeAddr, depositors[i], addresslist.EnabledRole, admin) + + // remove all depositors from the bridge block list + setAccessListRole(t, cluster, contracts.BlockListBridgeAddr, depositors[i], addresslist.NoRole, admin) + + // deposit (without minting, as it was already done beforehand) + err = cluster.Bridge.Deposit( + common.ERC721, + types.Address(rootERC721Token), + contracts.RootMintableERC721PredicateContract, + depositorKey, + depositors[i].String(), + "", + fmt.Sprintf("%d", i), + validatorSrv.JSONRPCAddr(), + "", + true) require.NoError(t, err) - require.True(t, isProcessed) } + + childChainBlock, err := childEthEndpoint.GetBlockByNumber(ethgo.Latest, false) + require.NoError(t, err) + + childChainBlockExtra, err := polybft.GetIbftExtra(childChainBlock.ExtraData) + require.NoError(t, err) + + // wait for checkpoint to be submitted + require.NoError(t, + waitForRootchainEpoch(childChainBlockExtra.Checkpoint.EpochNumber, 2*time.Minute, rootchainTxRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) + + // first exit event is mapping child token on a rootchain + // remaining ones are the deposits + initialExitEventID++ + for i := initialExitEventID; i <= initialExitEventID+transfersCount; i++ { + require.NoError(t, + cluster.Bridge.SendExitTransaction(polybftCfg.Bridge.ExitHelperAddr, i, validatorSrv.JSONRPCAddr())) + } + + latestRootchainBlock, err := rootchainTxRelayer.Client().Eth().BlockNumber() + require.NoError(t, err) + + // retrieve child token addresses on both chains and make sure they are the same + l1ChildToken := getChildToken(t, contractsapi.ChildMintableERC721Predicate.Abi, polybftCfg.Bridge.ChildMintableERC721PredicateAddr, + types.Address(rootERC721Token), rootchainTxRelayer) + l2ChildToken := getChildToken(t, contractsapi.RootMintableERC721Predicate.Abi, contracts.RootMintableERC721PredicateContract, + types.Address(rootERC721Token), childchainTxRelayer) + + t.Log("L1 child token", l1ChildToken) + t.Log("L2 child token", l2ChildToken) + require.Equal(t, l1ChildToken, l2ChildToken) + + logs, err := getFilteredLogs(mintableTokenMapped.Sig(), rootchainInitialBlock, latestRootchainBlock, + rootchainTxRelayer.Client().Eth()) + require.NoError(t, err) + require.Len(t, logs, 1) + + // check owner on the rootchain + for i := uint64(0); i < transfersCount; i++ { + owner := erc721OwnerOf(t, new(big.Int).SetUint64(i), l1ChildToken, rootchainTxRelayer) + t.Log("ChildERC721 owner", owner) + require.Equal(t, depositors[i], owner) + } + + // withdraw tokens + for i, depositorKey := range depositorKeys { + err = cluster.Bridge.Withdraw( + common.ERC721, + depositorKey, + depositors[i].String(), + "", + fmt.Sprintf("%d", i), + cluster.Bridge.JSONRPCAddr(), + polybftCfg.Bridge.ChildMintableERC721PredicateAddr, + l1ChildToken, + true) + require.NoError(t, err) + } + + childChainBlockNum, err := childEthEndpoint.BlockNumber() + require.NoError(t, err) + + // wait for commitment execution + require.NoError(t, cluster.WaitForBlock(childChainBlockNum+3*sprintSize, 2*time.Minute)) + + // check owners on the child chain + for i, receiver := range depositors { + owner := erc721OwnerOf(t, big.NewInt(int64(i)), types.Address(rootERC721Token), childchainTxRelayer) + t.Log("RootERC721 owner", owner) + require.Equal(t, receiver, owner) + } + }) +} + +func TestE2E_CheckpointSubmission(t *testing.T) { + // spin up a cluster with epoch size set to 5 blocks + cluster := framework.NewTestCluster(t, 5, framework.WithEpochSize(5)) + defer cluster.Stop() + + // initialize tx relayer used to query CheckpointManager smart contract + rootChainRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) + require.NoError(t, err) + + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) + require.NoError(t, err) + + checkpointManagerAddr := ethgo.Address(polybftCfg.Bridge.CheckpointManagerAddr) + + testCheckpointBlockNumber := func(expectedCheckpointBlock uint64) (bool, error) { + actualCheckpointBlock, err := getCheckpointBlockNumber(rootChainRelayer, checkpointManagerAddr) + if err != nil { + return false, err + } + + t.Logf("Checkpoint block: %d\n", actualCheckpointBlock) + + return actualCheckpointBlock == expectedCheckpointBlock, nil } + + // wait for a single epoch to be checkpointed + require.NoError(t, cluster.WaitForBlock(7, 30*time.Second)) + + // checking last checkpoint block before rootchain server stop + err = cluster.Bridge.WaitUntil(2*time.Second, 30*time.Second, func() (bool, error) { + return testCheckpointBlockNumber(5) + }) + require.NoError(t, err) + + // stop rootchain server + cluster.Bridge.Stop() + + // wait for a couple of epochs so that there are pending checkpoint (epoch-ending) blocks + require.NoError(t, cluster.WaitForBlock(21, 2*time.Minute)) + + // restart rootchain server + require.NoError(t, cluster.Bridge.Start()) + + // check if pending checkpoint blocks were submitted (namely the last checkpointed block must be block 20) + err = cluster.Bridge.WaitUntil(2*time.Second, 50*time.Second, func() (bool, error) { + return testCheckpointBlockNumber(20) + }) + require.NoError(t, err) } func TestE2E_Bridge_ChangeVotingPower(t *testing.T) { const ( - finalBlockNumber = 20 - votingPowerChanges = 3 + votingPowerChanges = 2 + epochSize = 5 ) cluster := framework.NewTestCluster(t, 5, - framework.WithBridge(), - framework.WithEpochSize(5), - framework.WithEpochReward(1000)) + framework.WithEpochSize(epochSize), + framework.WithEpochReward(1000000)) defer cluster.Stop() - // load manifest file - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) + // load polybft config + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) - checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) - validatorSecretFiles, err := genesis.GetValidatorKeyFiles(cluster.Config.TmpDir, cluster.Config.ValidatorPrefix) require.NoError(t, err) @@ -591,61 +1030,306 @@ func TestE2E_Bridge_ChangeVotingPower(t *testing.T) { votingPowerChangeValidators[i] = validator.Ecdsa.Address() } - // L2 Tx relayer (for sending stake transaction and querying validator) - l2Relayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Servers[0].JSONRPCAddr())) + // child chain tx relayer + childRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Servers[0].JSONRPCAddr())) require.NoError(t, err) - // L1 Tx relayer (for querying checkpoints) - l1Relayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) + // root chain tx relayer + rootRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) // waiting two epochs, so that some rewards get accumulated - require.NoError(t, cluster.WaitForBlock(10, 1*time.Minute)) + require.NoError(t, cluster.WaitForBlock(2*epochSize, 1*time.Minute)) queryValidators := func(handler func(idx int, validatorInfo *polybft.ValidatorInfo)) { for i, validatorAddr := range votingPowerChangeValidators { // query validator info - validatorInfo, err := sidechain.GetValidatorInfo(validatorAddr, l2Relayer) + validatorInfo, err := sidechain.GetValidatorInfo( + validatorAddr, + polybftCfg.Bridge.CustomSupernetManagerAddr, + polybftCfg.Bridge.StakeManagerAddr, + polybftCfg.SupernetID, + rootRelayer, + childRelayer) require.NoError(t, err) handler(i, validatorInfo) } } - originalValidatorStorage := make(map[ethgo.Address]*polybft.ValidatorInfo, votingPowerChanges) + // validatorsMap holds only changed validators + validatorsMap := make(map[ethgo.Address]*polybft.ValidatorInfo, votingPowerChanges) queryValidators(func(idx int, validator *polybft.ValidatorInfo) { t.Logf("[Validator#%d] Voting power (original)=%d, rewards=%d\n", - idx+1, validator.TotalStake, validator.WithdrawableRewards) + idx+1, validator.Stake, validator.WithdrawableRewards) - originalValidatorStorage[validator.Address] = validator + validatorsMap[validator.Address] = validator + validatorSrv := cluster.Servers[idx] - // stake rewards - require.NoError(t, cluster.Servers[idx].Stake(validator.WithdrawableRewards.Uint64())) - }) + // fund validators (send accumulated rewards amount) + require.NoError(t, validatorSrv.RootchainFund(polybftCfg.Bridge.StakeTokenAddr, validator.WithdrawableRewards)) - // wait a two more epochs, so that stake is registered and two more checkpoints are sent. - // Blocks are still produced, although voting power is slightly changed. - require.NoError(t, cluster.WaitForBlock(finalBlockNumber, 1*time.Minute)) + // stake previously funded amount + require.NoError(t, validatorSrv.Stake(polybftCfg, validator.WithdrawableRewards)) + }) queryValidators(func(idx int, validator *polybft.ValidatorInfo) { - t.Logf("[Validator#%d] Voting power (after stake)=%d\n", idx+1, validator.TotalStake) + t.Logf("[Validator#%d] Voting power (after stake)=%d\n", idx+1, validator.Stake) - previousValidatorInfo := originalValidatorStorage[validator.Address] - stakedAmount := new(big.Int).Add(previousValidatorInfo.WithdrawableRewards, previousValidatorInfo.TotalStake) + previousValidatorInfo := validatorsMap[validator.Address] + stakedAmount := new(big.Int).Add(previousValidatorInfo.WithdrawableRewards, previousValidatorInfo.Stake) // assert that total stake has increased by staked amount - require.Equal(t, stakedAmount, validator.TotalStake) + require.Equal(t, stakedAmount, validator.Stake) + + validatorsMap[validator.Address] = validator }) - require.NoError(t, cluster.Bridge.WaitUntil(time.Second, time.Minute, func() (bool, error) { - actualCheckpointBlock, err := getCheckpointBlockNumber(l1Relayer, checkpointManagerAddr) - if err != nil { - return false, err + currentBlockNum, err := childRelayer.Client().Eth().BlockNumber() + require.NoError(t, err) + + // wait for next epoch-ending block as the starting point, + // in order to be able to easier track checkpoints submission + endOfEpochBlockNum := currentBlockNum + epochSize - (currentBlockNum % epochSize) + require.NoError(t, cluster.WaitForBlock(endOfEpochBlockNum, 1*time.Minute)) + + currentBlock, err := childRelayer.Client().Eth().GetBlockByNumber(ethgo.Latest, false) + require.NoError(t, err) + + currentExtra, err := polybft.GetIbftExtra(currentBlock.ExtraData) + require.NoError(t, err) + + targetEpoch := currentExtra.Checkpoint.EpochNumber + 2 + require.NoError(t, waitForRootchainEpoch(targetEpoch, 2*time.Minute, + rootRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) + + // make sure that correct validator set is submitted to the checkpoint manager + checkpointValidators, err := getCheckpointManagerValidators(rootRelayer, ethgo.Address(polybftCfg.Bridge.CheckpointManagerAddr)) + require.NoError(t, err) + + for _, checkpointValidator := range checkpointValidators { + if validator, ok := validatorsMap[checkpointValidator.Address]; ok { + require.Equal(t, validator.Stake, checkpointValidator.Stake) + } else { + require.Equal(t, command.DefaultPremineBalance, checkpointValidator.Stake) } + } +} - t.Logf("Checkpoint block: %d\n", actualCheckpointBlock) +func TestE2E_Bridge_Transfers_AccessLists(t *testing.T) { + var ( + transfersCount = 5 + depositAmount = ethgo.Ether(5) + withdrawAmount = ethgo.Ether(1) + // make epoch size long enough, so that all exit events are processed within the same epoch + epochSize = 30 + sprintSize = uint64(5) + ) + + receivers := make([]string, transfersCount) + depositAmounts := make([]string, transfersCount) + withdrawAmounts := make([]string, transfersCount) + + admin, _ := ethgow.GenerateKey() + adminAddr := types.Address(admin.Address()) + + cluster := framework.NewTestCluster(t, 5, + framework.WithNumBlockConfirmations(0), + framework.WithEpochSize(epochSize), + framework.WithBridgeAllowListAdmin(adminAddr), + framework.WithBridgeBlockListAdmin(adminAddr), + framework.WithSecretsCallback(func(a []types.Address, tcc *framework.TestClusterConfig) { + for i := 0; i < len(a); i++ { + receivers[i] = a[i].String() + depositAmounts[i] = fmt.Sprintf("%d", depositAmount) + withdrawAmounts[i] = fmt.Sprintf("%d", withdrawAmount) + + t.Logf("Receiver#%d=%s\n", i+1, receivers[i]) + } + }), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) + require.NoError(t, err) - return actualCheckpointBlock == finalBlockNumber, nil - })) + validatorSrv := cluster.Servers[0] + childEthEndpoint := validatorSrv.JSONRPC().Eth() + + var stateSyncedResult contractsapi.StateSyncResultEvent + + // fund admin on rootchain + require.NoError(t, cluster.Servers[0].RootchainFundFor([]types.Address{adminAddr}, []*big.Int{ethgo.Ether(10)}, + polybftCfg.Bridge.StakeTokenAddr)) + + adminBalanceOnChild := ethgo.Ether(5) + + // bridge some tokens for admin to child chain + require.NoError( + t, cluster.Bridge.Deposit( + common.ERC20, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, + rootHelper.TestAccountPrivKey, + adminAddr.String(), + adminBalanceOnChild.String(), + "", + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), + ) + + // wait for a couple of sprints + finalBlockNum := 5 * sprintSize + require.NoError(t, cluster.WaitForBlock(finalBlockNum, 2*time.Minute)) + + // the transaction is processed and there should be a success events + logs, err := getFilteredLogs(stateSyncedResult.Sig(), 0, finalBlockNum, childEthEndpoint) + require.NoError(t, err) + + // assert that all deposits are executed successfully + checkStateSyncResultLogs(t, logs, 1) + + // check admin balance got increased by deposited amount + balance, err := childEthEndpoint.GetBalance(ethgo.Address(adminAddr), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, adminBalanceOnChild, balance) + + t.Run("bridge native (ERC 20) tokens", func(t *testing.T) { + // DEPOSIT ERC20 TOKENS + // send a few transactions to the bridge + require.NoError( + t, + cluster.Bridge.Deposit( + common.ERC20, + polybftCfg.Bridge.RootNativeERC20Addr, + polybftCfg.Bridge.RootERC20PredicateAddr, + rootHelper.TestAccountPrivKey, + strings.Join(receivers[:], ","), + strings.Join(depositAmounts[:], ","), + "", + cluster.Bridge.JSONRPCAddr(), + rootHelper.TestAccountPrivKey, + false), + ) + + finalBlockNum := 10 * sprintSize + // wait for a couple of sprints + require.NoError(t, cluster.WaitForBlock(finalBlockNum, 2*time.Minute)) + + // the transactions are processed and there should be a success events + logs, err := getFilteredLogs(stateSyncedResult.Sig(), 0, finalBlockNum, childEthEndpoint) + require.NoError(t, err) + + // because of the admin deposit on child chain at the beginning + totalTransfers := transfersCount + 1 + + // assert that all deposits are executed successfully + checkStateSyncResultLogs(t, logs, totalTransfers) + + // check receivers balances got increased by deposited amount + for _, receiver := range receivers { + balance, err := childEthEndpoint.GetBalance(ethgo.Address(types.StringToAddress(receiver)), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, depositAmount, balance) + } + + t.Log("Deposits were successfully processed") + + // WITHDRAW ERC20 TOKENS + rootchainTxRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) + require.NoError(t, err) + + senderAccount, err := sidechain.GetAccountFromDir(validatorSrv.DataDir()) + require.NoError(t, err) + + t.Logf("Withdraw sender: %s\n", senderAccount.Ecdsa.Address()) + + rawKey, err := senderAccount.Ecdsa.MarshallPrivateKey() + require.NoError(t, err) + + // send withdraw transaction. + // It should fail because sender is not allow-listed. + err = cluster.Bridge.Withdraw( + common.ERC20, + hex.EncodeToString(rawKey), + strings.Join(receivers[:], ","), + strings.Join(withdrawAmounts[:], ","), + "", + validatorSrv.JSONRPCAddr(), + contracts.ChildERC20PredicateContract, + contracts.NativeERC20TokenContract, + false) + require.Error(t, err) + + // add account to bridge allow list + setAccessListRole(t, cluster, contracts.AllowListBridgeAddr, senderAccount.Address(), addresslist.EnabledRole, admin) + + // try to withdraw again + err = cluster.Bridge.Withdraw( + common.ERC20, + hex.EncodeToString(rawKey), + strings.Join(receivers[:], ","), + strings.Join(withdrawAmounts[:], ","), + "", + validatorSrv.JSONRPCAddr(), + contracts.ChildERC20PredicateContract, + contracts.NativeERC20TokenContract, + false) + require.NoError(t, err) + + // add account to bridge block list + setAccessListRole(t, cluster, contracts.BlockListBridgeAddr, senderAccount.Address(), addresslist.EnabledRole, admin) + + // it should fail now because in block list + err = cluster.Bridge.Withdraw( + common.ERC20, + hex.EncodeToString(rawKey), + strings.Join(receivers[:], ","), + strings.Join(withdrawAmounts[:], ","), + "", + validatorSrv.JSONRPCAddr(), + contracts.ChildERC20PredicateContract, + contracts.NativeERC20TokenContract, + false) + require.ErrorContains(t, err, "failed to send withdraw transaction") + + currentBlock, err := childEthEndpoint.GetBlockByNumber(ethgo.Latest, false) + require.NoError(t, err) + + currentExtra, err := polybft.GetIbftExtra(currentBlock.ExtraData) + require.NoError(t, err) + + t.Logf("Latest block number: %d, epoch number: %d\n", currentBlock.Number, currentExtra.Checkpoint.EpochNumber) + + currentEpoch := currentExtra.Checkpoint.EpochNumber + + require.NoError(t, waitForRootchainEpoch(currentEpoch, 3*time.Minute, + rootchainTxRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) + + exitHelper := polybftCfg.Bridge.ExitHelperAddr + childJSONRPC := validatorSrv.JSONRPCAddr() + + oldBalances := map[types.Address]*big.Int{} + for _, receiver := range receivers { + balance := erc20BalanceOf(t, types.StringToAddress(receiver), polybftCfg.Bridge.RootNativeERC20Addr, rootchainTxRelayer) + oldBalances[types.StringToAddress(receiver)] = balance + } + + for exitEventID := uint64(1); exitEventID <= uint64(transfersCount); exitEventID++ { + // send exit transaction to exit helper + err = cluster.Bridge.SendExitTransaction(exitHelper, exitEventID, childJSONRPC) + require.NoError(t, err) + } + + // assert that receiver's balances on RootERC20 smart contract are expected + for _, receiver := range receivers { + balance := erc20BalanceOf(t, types.StringToAddress(receiver), polybftCfg.Bridge.RootNativeERC20Addr, rootchainTxRelayer) + require.Equal(t, oldBalances[types.StringToAddress(receiver)].Add( + oldBalances[types.StringToAddress(receiver)], withdrawAmount), balance) + } + }) } diff --git a/e2e-polybft/e2e/burn_contract_test.go b/e2e-polybft/e2e/burn_contract_test.go new file mode 100644 index 0000000000..9a592397ea --- /dev/null +++ b/e2e-polybft/e2e/burn_contract_test.go @@ -0,0 +1,37 @@ +package e2e + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/wallet" + + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" + "github.com/0xPolygon/polygon-edge/types" +) + +func TestE2E_BurnContract_Deployed(t *testing.T) { + contractKey, _ := wallet.GenerateKey() + destinationKey, _ := wallet.GenerateKey() + + contractAddr := types.Address(contractKey.Address()) + destinationAddr := types.Address(destinationKey.Address()) + + cluster := framework.NewTestCluster(t, 5, + framework.WithBurnContract(&polybft.BurnContractInfo{ + Address: contractAddr, + DestinationAddress: destinationAddr, + }), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + client := cluster.Servers[0].JSONRPC().Eth() + + // Get the code for the default deployed burn contract + code, err := client.GetCode(ethgo.Address(contractAddr), ethgo.Latest) + require.NoError(t, err) + require.NotEqual(t, code, "0x") +} diff --git a/e2e-polybft/e2e/consensus_test.go b/e2e-polybft/e2e/consensus_test.go index 51979d7e30..45355401f2 100644 --- a/e2e-polybft/e2e/consensus_test.go +++ b/e2e-polybft/e2e/consensus_test.go @@ -6,9 +6,16 @@ import ( "fmt" "math/big" "path" + "strconv" "testing" "time" + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/abi" + "github.com/umbracle/ethgo/wallet" + + "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/genesis" "github.com/0xPolygon/polygon-edge/command/sidechain" "github.com/0xPolygon/polygon-edge/consensus/polybft" @@ -18,74 +25,86 @@ import ( "github.com/0xPolygon/polygon-edge/server/proto" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" - "github.com/stretchr/testify/require" - "github.com/umbracle/ethgo" ) +var uint256ABIType = abi.MustNewType("tuple(uint256)") + func TestE2E_Consensus_Basic_WithNonValidators(t *testing.T) { - cluster := framework.NewTestCluster(t, 7, - framework.WithNonValidators(2), framework.WithValidatorSnapshot(5)) + const epochSize = 4 + + cluster := framework.NewTestCluster(t, 5, + framework.WithEpochSize(epochSize), framework.WithNonValidators(2)) defer cluster.Stop() - require.NoError(t, cluster.WaitForBlock(22, 1*time.Minute)) -} + cluster.WaitForReady(t) -func TestE2E_Consensus_Sync_WithNonValidators(t *testing.T) { - // one non-validator node from the ensemble gets disconnected and connected again. - // It should be able to pick up from the synchronization protocol again. - cluster := framework.NewTestCluster(t, 7, - framework.WithNonValidators(2), framework.WithValidatorSnapshot(5)) - defer cluster.Stop() + // initialize tx relayer + relayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(cluster.Servers[0].JSONRPC())) + require.NoError(t, err) - // wait for the start - require.NoError(t, cluster.WaitForBlock(20, 1*time.Minute)) + // because we are using native token as reward wallet, and it has default premine balance + initialTotalSupply := new(big.Int).Set(command.DefaultPremineBalance) - // stop one non-validator node - node := cluster.Servers[6] - node.Stop() + // check if initial total supply of native ERC20 token is the same as expected + totalSupply := queryNativeERC20Metadata(t, "totalSupply", uint256ABIType, relayer) + require.True(t, initialTotalSupply.Cmp(totalSupply.(*big.Int)) == 0) //nolint:forcetypeassert - // wait for at least 15 more blocks before starting again - require.NoError(t, cluster.WaitForBlock(35, 2*time.Minute)) + t.Run("consensus protocol", func(t *testing.T) { + require.NoError(t, cluster.WaitForBlock(2*epochSize+1, 1*time.Minute)) + }) - // start the node again - node.Start() + t.Run("sync protocol, drop single validator node", func(t *testing.T) { + // query the current block number, as it is a starting point for the test + currentBlockNum, err := cluster.Servers[0].JSONRPC().Eth().BlockNumber() + require.NoError(t, err) - // wait for block 55 - require.NoError(t, cluster.WaitForBlock(55, 2*time.Minute)) -} + // stop one node + node := cluster.Servers[0] + node.Stop() -func TestE2E_Consensus_Sync(t *testing.T) { - // one node from the ensemble gets disconnected and connected again. - // It should be able to pick up from the synchronization protocol again. - cluster := framework.NewTestCluster(t, 6, framework.WithValidatorSnapshot(6)) - defer cluster.Stop() + // wait for 2 epochs to elapse, so that rest of the network progresses + require.NoError(t, cluster.WaitForBlock(currentBlockNum+2*epochSize, 2*time.Minute)) + + // start the node again + node.Start() + + // wait 2 more epochs to elapse and make sure that stopped node managed to catch up + require.NoError(t, cluster.WaitForBlock(currentBlockNum+4*epochSize, 2*time.Minute)) + }) - // wait for the start - require.NoError(t, cluster.WaitForBlock(5, 1*time.Minute)) + t.Run("sync protocol, drop single non-validator node", func(t *testing.T) { + // query the current block number, as it is a starting point for the test + currentBlockNum, err := cluster.Servers[0].JSONRPC().Eth().BlockNumber() + require.NoError(t, err) - // stop one node - node := cluster.Servers[0] - node.Stop() + // stop one non-validator node + node := cluster.Servers[6] + node.Stop() - // wait for at least 15 more blocks before starting again - require.NoError(t, cluster.WaitForBlock(20, 2*time.Minute)) + // wait for 2 epochs to elapse, so that rest of the network progresses + require.NoError(t, cluster.WaitForBlock(currentBlockNum+2*epochSize, 2*time.Minute)) - // start the node again - node.Start() + // start the node again + node.Start() - // wait for block 35 - require.NoError(t, cluster.WaitForBlock(35, 2*time.Minute)) + // wait 2 more epochs to elapse and make sure that stopped node managed to catch up + require.NoError(t, cluster.WaitForBlock(currentBlockNum+4*epochSize, 2*time.Minute)) + }) } -func TestE2E_Consensus_Bulk_Drop(t *testing.T) { - clusterSize := 5 - bulkToDrop := 3 +func TestE2E_Consensus_BulkDrop(t *testing.T) { + const ( + clusterSize = 5 + bulkToDrop = 3 + epochSize = 5 + ) - cluster := framework.NewTestCluster(t, clusterSize) + cluster := framework.NewTestCluster(t, clusterSize, + framework.WithEpochSize(epochSize)) defer cluster.Stop() // wait for cluster to start - require.NoError(t, cluster.WaitForBlock(5, 1*time.Minute)) + cluster.WaitForReady(t) // drop bulk of nodes from cluster for i := 0; i < bulkToDrop; i++ { @@ -99,45 +118,53 @@ func TestE2E_Consensus_Bulk_Drop(t *testing.T) { node.Start() } - // wait for block 10 - require.NoError(t, cluster.WaitForBlock(10, 2*time.Minute)) + // wait to proceed to the 2nd epoch + require.NoError(t, cluster.WaitForBlock(epochSize+1, 2*time.Minute)) } func TestE2E_Consensus_RegisterValidator(t *testing.T) { const ( - validatorSize = 5 - epochSize = 5 - epochReward = 1000000000 + validatorSetSize = 5 + epochSize = 5 ) var ( - firstValidatorDataDir = fmt.Sprintf("test-chain-%d", validatorSize+1) // directory where the first validator secrets will be stored - secondValidatorDataDir = fmt.Sprintf("test-chain-%d", validatorSize+2) // directory where the second validator secrets will be stored + firstValidatorDataDir = fmt.Sprintf("test-chain-%d", validatorSetSize+1) // directory where the first validator secrets will be stored + secondValidatorDataDir = fmt.Sprintf("test-chain-%d", validatorSetSize+2) // directory where the second validator secrets will be stored - premineBalance = ethgo.Ether(2e6) // 2M native tokens (so that we have enough balance to fund new validator) + initMinterBalance = ethgo.Ether(4e6) + premineBalance = ethgo.Ether(2e6) // 2M native tokens (so that we have enough balance to fund new validator) ) + minter, err := wallet.GenerateKey() + require.NoError(t, err) + // start cluster with 'validatorSize' validators - cluster := framework.NewTestCluster(t, validatorSize, + cluster := framework.NewTestCluster(t, validatorSetSize, framework.WithEpochSize(epochSize), - framework.WithEpochReward(epochReward), + framework.WithEpochReward(int(ethgo.Ether(1).Uint64())), + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, minter.Address())), framework.WithSecretsCallback(func(addresses []types.Address, config *framework.TestClusterConfig) { + config.Premine = append(config.Premine, fmt.Sprintf("%s:%s", minter.Address(), initMinterBalance)) for _, a := range addresses { - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%s", a, premineBalance)) + config.Premine = append(config.Premine, fmt.Sprintf("%s:%s", a, premineBalance)) } }), ) defer cluster.Stop() + cluster.WaitForReady(t) + // first validator is the owner of ChildValidator set smart contract owner := cluster.Servers[0] - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(owner.JSONRPCAddr())) + childChainRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(owner.JSONRPCAddr())) + require.NoError(t, err) + + rootChainRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) - systemState := polybft.NewSystemState( - contracts.ValidatorSetContract, - contracts.StateReceiverContract, - &e2eStateProvider{txRelayer: txRelayer}) + polybftConfig, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) + require.NoError(t, err) // create the first account and extract the address addrs, err := cluster.InitSecrets(firstValidatorDataDir, 1) @@ -154,371 +181,266 @@ func TestE2E_Consensus_RegisterValidator(t *testing.T) { // assert that accounts are created validatorSecrets, err := genesis.GetValidatorKeyFiles(cluster.Config.TmpDir, cluster.Config.ValidatorPrefix) require.NoError(t, err) - require.Equal(t, validatorSize+2, len(validatorSecrets)) + require.Equal(t, validatorSetSize+2, len(validatorSecrets)) // collect owners validator secrets - ownerSecrets := validatorSecrets[0] - - // wait for consensus to start - require.NoError(t, cluster.WaitForBlock(1, 10*time.Second)) + firstValidatorSecrets := validatorSecrets[validatorSetSize] + secondValidatorSecrets := validatorSecrets[validatorSetSize+1] genesisBlock, err := owner.JSONRPC().Eth().GetBlockByNumber(0, false) require.NoError(t, err) - extra, err := polybft.GetIbftExtra(genesisBlock.ExtraData) + _, err = polybft.GetIbftExtra(genesisBlock.ExtraData) require.NoError(t, err) - // on genesis block all validators are marked as added, which makes initial validator set - initialValidators := extra.Validators.Added - // owner whitelists both new validators - require.NoError(t, owner.WhitelistValidator(firstValidatorAddr.String(), ownerSecrets)) - require.NoError(t, owner.WhitelistValidator(secondValidatorAddr.String(), ownerSecrets)) + require.NoError(t, owner.WhitelistValidators([]string{ + firstValidatorAddr.String(), + secondValidatorAddr.String(), + }, polybftConfig.Bridge.CustomSupernetManagerAddr)) - // start the first and the second validator - cluster.InitTestServer(t, validatorSize+1, true, false) - cluster.InitTestServer(t, validatorSize+2, true, false) + // set the initial balance of the new validators at the rootchain + initialBalance := ethgo.Ether(500) - ownerAcc, err := sidechain.GetAccountFromDir(path.Join(cluster.Config.TmpDir, ownerSecrets)) + // fund first new validator + err = cluster.Bridge.FundValidators(polybftConfig.Bridge.StakeTokenAddr, + []string{path.Join(cluster.Config.TmpDir, firstValidatorSecrets)}, []*big.Int{initialBalance}) require.NoError(t, err) - // get the initial balance of the new validator - initialBalance := ethgo.Ether(500000) - - // send some tokens from the owner to the first validator so that the first validator can register and stake - receipt, err := txRelayer.SendTransaction(ðgo.Transaction{ - From: ownerAcc.Ecdsa.Address(), - To: &firstValidatorAddr, - Value: initialBalance, - }, ownerAcc.Ecdsa) + // fund second new validator + err = cluster.Bridge.FundValidators(polybftConfig.Bridge.StakeTokenAddr, + []string{path.Join(cluster.Config.TmpDir, secondValidatorSecrets)}, []*big.Int{initialBalance}) require.NoError(t, err) - require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) - - // send some tokens from the owner to the second validator so that the second validator can register and stake - receipt, err = txRelayer.SendTransaction(ðgo.Transaction{ - From: ownerAcc.Ecdsa.Address(), - To: &secondValidatorAddr, - Value: initialBalance, - }, ownerAcc.Ecdsa) - require.NoError(t, err) - require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) - // collect the first and the second validator from the cluster - firstValidator := cluster.Servers[validatorSize] - secondValidator := cluster.Servers[validatorSize+1] - - // wait for the first validator's balance to be received - firstBalance, err := firstValidator.WaitForNonZeroBalance(firstValidatorAddr, 5*time.Second) + // first validator's balance to be received + firstBalance, err := rootChainRelayer.Client().Eth().GetBalance(firstValidatorAddr, ethgo.Latest) require.NoError(t, err) t.Logf("First validator balance=%d\n", firstBalance) - // wait for the first validator's balance to be received - secondBalance, err := secondValidator.WaitForNonZeroBalance(secondValidatorAddr, 5*time.Second) + // second validator's balance to be received + secondBalance, err := rootChainRelayer.Client().Eth().GetBalance(secondValidatorAddr, ethgo.Latest) require.NoError(t, err) t.Logf("Second validator balance=%d\n", secondBalance) - newValidatorStake := ethgo.Ether(10) + // start the first and the second validator + cluster.InitTestServer(t, cluster.Config.ValidatorPrefix+strconv.Itoa(validatorSetSize+1), + cluster.Bridge.JSONRPCAddr(), true, false) + + cluster.InitTestServer(t, cluster.Config.ValidatorPrefix+strconv.Itoa(validatorSetSize+2), + cluster.Bridge.JSONRPCAddr(), true, false) + + // collect the first and the second validator from the cluster + firstValidator := cluster.Servers[validatorSetSize] + secondValidator := cluster.Servers[validatorSetSize+1] + + initialStake := ethgo.Ether(499) // register the first validator with stake - require.NoError(t, firstValidator.RegisterValidator(firstValidatorDataDir, newValidatorStake.String())) + require.NoError(t, firstValidator.RegisterValidator(polybftConfig.Bridge.CustomSupernetManagerAddr)) // register the second validator without stake - require.NoError(t, secondValidator.RegisterValidator(secondValidatorDataDir, "")) + require.NoError(t, secondValidator.RegisterValidator(polybftConfig.Bridge.CustomSupernetManagerAddr)) - // stake manually for the second validator - require.NoError(t, secondValidator.Stake(newValidatorStake.Uint64())) + // stake manually for the first validator + require.NoError(t, firstValidator.Stake(polybftConfig, initialStake)) - validators := polybft.AccountSet{} - // assert that new validator is among validator set - require.NoError(t, cluster.WaitUntil(20*time.Second, 1*time.Second, func() bool { - // query validators - validators, err = systemState.GetValidatorSet() - require.NoError(t, err) - - return validators.ContainsAddress((types.Address(firstValidatorAddr))) && - validators.ContainsAddress((types.Address(secondValidatorAddr))) - })) + // stake manually for the second validator + require.NoError(t, secondValidator.Stake(polybftConfig, initialStake)) - // assert that next validators hash is correct - block, err := owner.JSONRPC().Eth().GetBlockByNumber(ethgo.Latest, false) + firstValidatorInfo, err := sidechain.GetValidatorInfo(firstValidatorAddr, + polybftConfig.Bridge.CustomSupernetManagerAddr, polybftConfig.Bridge.StakeManagerAddr, + polybftConfig.SupernetID, rootChainRelayer, childChainRelayer) require.NoError(t, err) - t.Logf("Block Number=%d\n", block.Number) - - // apply all deltas from epoch ending blocks - nextValidators := initialValidators + require.True(t, firstValidatorInfo.IsActive) + require.True(t, firstValidatorInfo.Stake.Cmp(initialStake) == 0) - // apply all the deltas to the initial validator set - latestEpochEndBlock := block.Number - (block.Number % epochSize) - for blockNum := uint64(epochSize); blockNum <= latestEpochEndBlock; blockNum += epochSize { - block, err = owner.JSONRPC().Eth().GetBlockByNumber(ethgo.BlockNumber(blockNum), false) - require.NoError(t, err) + secondValidatorInfo, err := sidechain.GetValidatorInfo(secondValidatorAddr, + polybftConfig.Bridge.CustomSupernetManagerAddr, polybftConfig.Bridge.StakeManagerAddr, + polybftConfig.SupernetID, rootChainRelayer, childChainRelayer) + require.NoError(t, err) + require.True(t, secondValidatorInfo.IsActive) + require.True(t, secondValidatorInfo.Stake.Cmp(initialStake) == 0) - extra, err = polybft.GetIbftExtra(block.ExtraData) - require.NoError(t, err) - require.NotNil(t, extra.Checkpoint) + // wait for the stake to be bridged + require.NoError(t, cluster.WaitForBlock(polybftConfig.EpochSize*4, time.Minute)) - t.Logf("Block Number: %d, Delta: %v\n", blockNum, extra.Validators) + checkpointManagerAddr := ethgo.Address(polybftConfig.Bridge.CheckpointManagerAddr) - nextValidators, err = nextValidators.ApplyDelta(extra.Validators) - require.NoError(t, err) - } + // check if the validators are added to active validator set + rootchainValidators := []*polybft.ValidatorInfo{} + err = cluster.Bridge.WaitUntil(time.Second, time.Minute, func() (bool, error) { + rootchainValidators, err = getCheckpointManagerValidators(rootChainRelayer, checkpointManagerAddr) + if err != nil { + return true, err + } - // assert that correct validators hash gets submitted - nextValidatorsHash, err := nextValidators.Hash() - require.NoError(t, err) - require.Equal(t, extra.Checkpoint.NextValidatorsHash, nextValidatorsHash) + return len(rootchainValidators) == validatorSetSize+2, nil + }) - // query the first validator - firstValidatorInfo, err := sidechain.GetValidatorInfo(firstValidatorAddr, txRelayer) require.NoError(t, err) + require.Equal(t, validatorSetSize+2, len(rootchainValidators)) - // assert the first validator's stake - t.Logf("First validator stake=%d\n", firstValidatorInfo.TotalStake) - require.Equal(t, newValidatorStake, firstValidatorInfo.TotalStake) + var ( + isFirstValidatorFound bool + isSecondValidatorFound bool + ) - // query the second validatorr - secondValidatorInfo, err := sidechain.GetValidatorInfo(secondValidatorAddr, txRelayer) - require.NoError(t, err) + for _, v := range rootchainValidators { + if v.Address == firstValidatorAddr { + isFirstValidatorFound = true + } else if v.Address == secondValidatorAddr { + isSecondValidatorFound = true + } + } - // assert the second validator's stake - t.Logf("Second validator stake=%d\n", secondValidatorInfo.TotalStake) - require.Equal(t, newValidatorStake, secondValidatorInfo.TotalStake) + // new validators should be in the active validator set + require.True(t, isFirstValidatorFound) + require.True(t, isSecondValidatorFound) - // wait 3 more epochs, so that rewards get accumulated to the registered validator account - currentBlock, err := owner.JSONRPC().Eth().BlockNumber() + currentBlock, err := owner.JSONRPC().Eth().GetBlockByNumber(ethgo.Latest, false) require.NoError(t, err) - require.NoError(t, cluster.WaitForBlock(currentBlock+3*epochSize, 2*time.Minute)) - // query the first validator info again - firstValidatorInfo, err = sidechain.GetValidatorInfo(firstValidatorAddr, txRelayer) - require.NoError(t, err) + // wait for couple of epochs to have some rewards accumulated + require.NoError(t, cluster.WaitForBlock(currentBlock.Number+(polybftConfig.EpochSize*2), time.Minute)) - // check if the first validator has signed any prposals - firstSealed, err := firstValidator.HasValidatorSealed(currentBlock, currentBlock+3*epochSize, nextValidators, firstValidatorAddr) - require.NoError(t, err) + bigZero := big.NewInt(0) - if firstSealed { - // assert registered validator's rewards) - t.Logf("First validator rewards (block %d)=%d\n", currentBlock, firstValidatorInfo.WithdrawableRewards) - require.True(t, firstValidatorInfo.WithdrawableRewards.Cmp(big.NewInt(0)) > 0) - } - - // query the second validator info again - secondValidatorInfo, err = sidechain.GetValidatorInfo(secondValidatorAddr, txRelayer) + firstValidatorInfo, err = sidechain.GetValidatorInfo(firstValidatorAddr, + polybftConfig.Bridge.CustomSupernetManagerAddr, polybftConfig.Bridge.StakeManagerAddr, + polybftConfig.SupernetID, rootChainRelayer, childChainRelayer) require.NoError(t, err) + require.True(t, firstValidatorInfo.IsActive) + require.True(t, firstValidatorInfo.WithdrawableRewards.Cmp(bigZero) > 0) - // check if the second validator has signed any prposals - secondSealed, err := secondValidator.HasValidatorSealed(currentBlock, currentBlock+3*epochSize, nextValidators, secondValidatorAddr) + secondValidatorInfo, err = sidechain.GetValidatorInfo(secondValidatorAddr, + polybftConfig.Bridge.CustomSupernetManagerAddr, polybftConfig.Bridge.StakeManagerAddr, + polybftConfig.SupernetID, rootChainRelayer, childChainRelayer) require.NoError(t, err) - - if secondSealed { - // assert registered validator's rewards - t.Logf("Second validator rewards (block %d)=%d\n", currentBlock, secondValidatorInfo.WithdrawableRewards) - require.True(t, secondValidatorInfo.WithdrawableRewards.Cmp(big.NewInt(0)) > 0) - } + require.True(t, secondValidatorInfo.IsActive) + require.True(t, secondValidatorInfo.WithdrawableRewards.Cmp(bigZero) > 0) } -func TestE2E_Consensus_Delegation_Undelegation(t *testing.T) { - const ( - validatorSecrets = "test-chain-1" - delegatorSecrets = "test-chain-6" - epochSize = 5 +func TestE2E_Consensus_Validator_Unstake(t *testing.T) { + var ( + premineAmount = ethgo.Ether(10) + minterBalance = ethgo.Ether(1e6) ) - premineBalance := ethgo.Ether(500) // 500 native tokens (so that we have enough funds to fund delegator) - fundAmount := ethgo.Ether(250) + minter, err := wallet.GenerateKey() + require.NoError(t, err) cluster := framework.NewTestCluster(t, 5, - framework.WithEpochReward(100000), - framework.WithEpochSize(epochSize), + framework.WithEpochReward(int(ethgo.Ether(1).Uint64())), + framework.WithEpochSize(5), + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, minter.Address())), framework.WithSecretsCallback(func(addresses []types.Address, config *framework.TestClusterConfig) { + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", minter.Address(), minterBalance)) for _, a := range addresses { - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%s", a, premineBalance)) - config.StakeAmounts = append(config.StakeAmounts, fmt.Sprintf("%s:%s", a, premineBalance)) + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", a, premineAmount)) + config.StakeAmounts = append(config.StakeAmounts, new(big.Int).Set(premineAmount)) } }), ) - defer cluster.Stop() - // init delegator account - _, err := cluster.InitSecrets(delegatorSecrets, 1) + polybftCfg, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) require.NoError(t, err) srv := cluster.Servers[0] - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(srv.JSONRPCAddr())) + childChainRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(srv.JSONRPCAddr())) require.NoError(t, err) - cluster.WaitForReady(t) - - // extract delegator's secrets - delegatorSecretsPath := path.Join(cluster.Config.TmpDir, delegatorSecrets) - delegatorAcc, err := sidechain.GetAccountFromDir(delegatorSecretsPath) + rootChainRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) - delegatorAddr := delegatorAcc.Ecdsa.Address() - - // extract validator's secrets - validatorSecretsPath := path.Join(cluster.Config.TmpDir, validatorSecrets) - - validatorAcc, err := sidechain.GetAccountFromDir(validatorSecretsPath) + validatorAcc, err := sidechain.GetAccountFromDir(srv.DataDir()) require.NoError(t, err) - validatorAddr := validatorAcc.Ecdsa.Address() - - // fund delegator - receipt, err := txRelayer.SendTransaction(ðgo.Transaction{ - From: validatorAddr, - To: &delegatorAddr, - Value: fundAmount, - }, validatorAcc.Ecdsa) - require.NoError(t, err) - require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) - - // getDelegatorInfo queries delegator's balance and its rewards - getDelegatorInfo := func() (balance *big.Int, reward *big.Int) { - currentBlockNum, err := srv.JSONRPC().Eth().BlockNumber() - require.NoError(t, err) - - balance, err = srv.JSONRPC().Eth().GetBalance(delegatorAddr, ethgo.Latest) - require.NoError(t, err) - t.Logf("Delegator balance (block %d)=%s\n", currentBlockNum, balance) - - reward, err = sidechain.GetDelegatorReward(validatorAddr, delegatorAddr, txRelayer) - require.NoError(t, err) - t.Logf("Delegator reward (block %d)=%s\n", currentBlockNum, reward) - - return - } - - // assert that delegator received fund amount from validator - delegatorBalance, _ := getDelegatorInfo() - require.Equal(t, fundAmount, delegatorBalance) - - // delegate 1 native token - delegationAmount := uint64(1e18) - require.NoError(t, srv.Delegate(delegationAmount, delegatorSecretsPath, validatorAddr)) + cluster.WaitForReady(t) - // wait for 2 epochs to accumulate delegator rewards - currentBlockNum, err := srv.JSONRPC().Eth().BlockNumber() + initialValidatorBalance, err := srv.JSONRPC().Eth().GetBalance(validatorAcc.Ecdsa.Address(), ethgo.Latest) require.NoError(t, err) - require.NoError(t, cluster.WaitForBlock(currentBlockNum+2*epochSize, 1*time.Minute)) + t.Logf("Balance (before unstake)=%d\n", initialValidatorBalance) - // query delegator rewards - _, delegatorReward := getDelegatorInfo() - // if validator signed at leased 1 block per epoch, this will be the minimal reward for the delegator - require.Greater(t, delegatorReward.Uint64(), uint64(16)) + validatorAddr := validatorAcc.Ecdsa.Address() - // undelegate rewards - require.NoError(t, srv.Undelegate(delegationAmount, delegatorSecretsPath, validatorAddr)) - t.Logf("Rewards are undelegated\n") + // wait for some rewards to get accumulated + require.NoError(t, cluster.WaitForBlock(polybftCfg.EpochSize*3, time.Minute)) - // wait for one epoch to be able to withdraw undelegated funds - currentBlockNum, err = srv.JSONRPC().Eth().BlockNumber() + validatorInfo, err := sidechain.GetValidatorInfo(validatorAddr, + polybftCfg.Bridge.CustomSupernetManagerAddr, polybftCfg.Bridge.StakeManagerAddr, + polybftCfg.SupernetID, rootChainRelayer, childChainRelayer) require.NoError(t, err) - require.NoError(t, cluster.WaitForBlock(currentBlockNum+epochSize, time.Minute)) + require.True(t, validatorInfo.IsActive) - balanceBeforeWithdraw, _ := getDelegatorInfo() - - // withdraw available rewards - require.NoError(t, srv.Withdraw(delegatorSecretsPath, delegatorAddr)) - t.Logf("Funds are withdrawn\n") + initialStake := validatorInfo.Stake + t.Logf("Stake (before unstake)=%d\n", initialStake) - // wait for single epoch to process withdrawal - currentBlockNum, err = srv.JSONRPC().Eth().BlockNumber() - require.NoError(t, err) - require.NoError(t, cluster.WaitForBlock(currentBlockNum+epochSize, time.Minute)) + reward := validatorInfo.WithdrawableRewards + t.Logf("Rewards=%d\n", reward) + require.Greater(t, reward.Uint64(), uint64(0)) - // assert that delegator doesn't receive any rewards - delegatorBalance, delegatorReward = getDelegatorInfo() - require.True(t, delegatorReward.Cmp(big.NewInt(0)) == 0) - require.True(t, balanceBeforeWithdraw.Cmp(delegatorBalance) == -1) -} + // unstake entire balance (which should remove validator from the validator set in next epoch) + require.NoError(t, srv.Unstake(initialStake)) -func TestE2E_Consensus_Validator_Unstake(t *testing.T) { - premineAmount := ethgo.Ether(10) + // wait for one epoch to withdraw from child + require.NoError(t, cluster.WaitForBlock(polybftCfg.EpochSize*4, time.Minute)) - cluster := framework.NewTestCluster(t, 5, - framework.WithBridge(), - framework.WithEpochReward(10000), - framework.WithEpochSize(5), - framework.WithSecretsCallback(func(addresses []types.Address, config *framework.TestClusterConfig) { - for _, a := range addresses { - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%d", a, premineAmount)) - config.StakeAmounts = append(config.StakeAmounts, fmt.Sprintf("%s:%d", a, premineAmount)) - } - }), - ) - validatorSecrets := path.Join(cluster.Config.TmpDir, "test-chain-1") - srv := cluster.Servers[0] + // withdraw from child + require.NoError(t, srv.WithdrawChildChain()) - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(srv.JSONRPCAddr())) + currentBlock, err := srv.JSONRPC().Eth().GetBlockByNumber(ethgo.Latest, false) require.NoError(t, err) - systemState := polybft.NewSystemState( - contracts.ValidatorSetContract, - contracts.StateReceiverContract, - &e2eStateProvider{txRelayer: txRelayer}) - - validatorAcc, err := sidechain.GetAccountFromDir(validatorSecrets) + currentExtra, err := polybft.GetIbftExtra(currentBlock.ExtraData) require.NoError(t, err) - validatorAddr := validatorAcc.Ecdsa.Address() - - // wait for one epoch to accumulate validator rewards - require.NoError(t, cluster.WaitForBlock(5, 20*time.Second)) + t.Logf("Latest block number: %d, epoch number: %d\n", currentBlock.Number, currentExtra.Checkpoint.EpochNumber) - validatorInfo, err := sidechain.GetValidatorInfo(validatorAddr, txRelayer) - require.NoError(t, err) + currentEpoch := currentExtra.Checkpoint.EpochNumber - initialStake := validatorInfo.TotalStake - t.Logf("Stake (before unstake)=%d\n", initialStake) + // wait for checkpoint to be submitted + require.NoError(t, waitForRootchainEpoch(currentEpoch, time.Minute, + rootChainRelayer, polybftCfg.Bridge.CheckpointManagerAddr)) - // unstake entire balance (which should remove validator from the validator set in next epoch) - require.NoError(t, srv.Unstake(initialStake.Uint64())) + exitEventID := uint64(1) - // wait end of epoch - require.NoError(t, cluster.WaitForBlock(10, 20*time.Second)) - - validatorSet, err := systemState.GetValidatorSet() + // send exit transaction to exit helper + err = cluster.Bridge.SendExitTransaction(polybftCfg.Bridge.ExitHelperAddr, exitEventID, srv.JSONRPCAddr()) require.NoError(t, err) - // assert that validator isn't present in new validator set - require.Equal(t, 4, validatorSet.Len()) - - validatorInfo, err = sidechain.GetValidatorInfo(validatorAddr, txRelayer) + // check that validator is no longer active (out of validator set) + validatorInfo, err = sidechain.GetValidatorInfo(validatorAddr, + polybftCfg.Bridge.CustomSupernetManagerAddr, polybftCfg.Bridge.StakeManagerAddr, + polybftCfg.SupernetID, rootChainRelayer, childChainRelayer) require.NoError(t, err) + require.False(t, validatorInfo.IsActive) + require.True(t, validatorInfo.Stake.Cmp(big.NewInt(0)) == 0) - reward := validatorInfo.WithdrawableRewards - t.Logf("Rewards=%d\n", reward) - t.Logf("Stake (after unstake)=%d\n", validatorInfo.TotalStake) - require.Greater(t, reward.Uint64(), uint64(0)) + t.Logf("Stake (after unstake)=%d\n", validatorInfo.Stake) - oldValidatorBalance, err := srv.JSONRPC().Eth().GetBalance(validatorAcc.Ecdsa.Address(), ethgo.Latest) + balanceBeforeRewardsWithdraw, err := srv.JSONRPC().Eth().GetBalance(validatorAcc.Ecdsa.Address(), ethgo.Latest) require.NoError(t, err) - t.Logf("Balance (before withdrawal)=%s\n", oldValidatorBalance) + t.Logf("Balance (before withdraw rewards)=%d\n", balanceBeforeRewardsWithdraw) - // withdraw (stake + rewards) - require.NoError(t, srv.Withdraw(validatorSecrets, validatorAddr)) + // withdraw pending rewards + require.NoError(t, srv.WithdrawRewards()) newValidatorBalance, err := srv.JSONRPC().Eth().GetBalance(validatorAcc.Ecdsa.Address(), ethgo.Latest) require.NoError(t, err) - t.Logf("Balance (after withdrawal)=%s\n", newValidatorBalance) - require.True(t, newValidatorBalance.Cmp(oldValidatorBalance) > 0) + t.Logf("Balance (after withdrawal of rewards)=%s\n", newValidatorBalance) + require.True(t, newValidatorBalance.Cmp(balanceBeforeRewardsWithdraw) > 0) l1Relayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) require.NoError(t, err) - manifest, err := polybft.LoadManifest(path.Join(cluster.Config.TmpDir, manifestFileName)) - require.NoError(t, err) - - checkpointManagerAddr := ethgo.Address(manifest.RootchainConfig.CheckpointManagerAddress) + checkpointManagerAddr := ethgo.Address(polybftCfg.Bridge.CheckpointManagerAddr) // query rootchain validator set and make sure that validator which unstaked all the funds isn't present in validator set anymore // (execute it multiple times if needed, because it is unknown in advance how much time it is going to take until checkpoint is submitted) rootchainValidators := []*polybft.ValidatorInfo{} err = cluster.Bridge.WaitUntil(time.Second, 10*time.Second, func() (bool, error) { - rootchainValidators, err = getRootchainValidators(l1Relayer, checkpointManagerAddr) + rootchainValidators, err = getCheckpointManagerValidators(l1Relayer, checkpointManagerAddr) if err != nil { return true, err } @@ -535,132 +457,78 @@ func TestE2E_Consensus_Validator_Unstake(t *testing.T) { } } -func TestE2E_Consensus_CorrectnessOfExtraValidatorsShouldNotDependOnDelegate(t *testing.T) { - const ( - validatorSecrets = "test-chain-1" - delegatorSecrets = "test-chain-delegator" - epochSize = 5 - validatorCount = 4 - blockTime = 2 * time.Second - ) - - cluster := framework.NewTestCluster(t, validatorCount, - framework.WithEpochReward(100000), - framework.WithEpochSize(epochSize)) - defer cluster.Stop() - - txRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Servers[0].JSONRPCAddr())) - require.NoError(t, err) - - // init delegator account - _, err = cluster.InitSecrets(delegatorSecrets, 1) - require.NoError(t, err) - - cluster.WaitForReady(t) - - // extract delegator's secrets - delegatorSecretsPath := path.Join(cluster.Config.TmpDir, delegatorSecrets) - delegatorAcc, err := sidechain.GetAccountFromDir(delegatorSecretsPath) - require.NoError(t, err) - - delegatorAddr := delegatorAcc.Ecdsa.Address() - - // extract validator's secrets - validatorSecretsPath := path.Join(cluster.Config.TmpDir, validatorSecrets) - - validatorAcc, err := sidechain.GetAccountFromDir(validatorSecretsPath) - require.NoError(t, err) - - validatorAddr := validatorAcc.Ecdsa.Address() - - fundAmount := ethgo.Ether(250) - - // fund delegator - receipt, err := txRelayer.SendTransaction(ðgo.Transaction{ - From: validatorAddr, - To: &delegatorAddr, - Value: fundAmount, - }, validatorAcc.Ecdsa) - require.NoError(t, err) - require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) - - endCh, waitCh := make(chan struct{}), make(chan struct{}) - - // delegate tokens to validator in the loop to be sure that the stake of validator will be changed at end of epoch block - go func() { - for { - delegationAmount := uint64(1e18) - - err = cluster.Servers[0].Delegate(delegationAmount, validatorSecretsPath, validatorAddr) - require.NoError(t, err) - - select { - case <-endCh: - close(waitCh) - - return - case <-time.After(blockTime / 2): - } - } - }() - - require.NoError(t, cluster.WaitForBlock(6, 30*time.Second)) - - close(endCh) - <-waitCh -} - func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) { const ( validatorCount = 5 epochSize = 5 - minterPath = "test-chain-1" + + tokenName = "Edge Coin" + tokenSymbol = "EDGE" + decimals = uint8(5) ) validatorsAddrs := make([]types.Address, validatorCount) - initialStake := ethgo.Gwei(1) - initialBalance := int64(0) + initValidatorsBalance := ethgo.Ether(1) + initMinterBalance := ethgo.Ether(100000) + + minter, err := wallet.GenerateKey() + require.NoError(t, err) + + // because we are using native token as reward wallet, and it has default premine balance + initialTotalSupply := new(big.Int).Set(command.DefaultPremineBalance) cluster := framework.NewTestCluster(t, validatorCount, - framework.WithMintableNativeToken(true), + framework.WithNativeTokenConfig( + fmt.Sprintf("%s:%s:%d:true:%s", tokenName, tokenSymbol, decimals, minter.Address())), framework.WithEpochSize(epochSize), framework.WithSecretsCallback(func(addrs []types.Address, config *framework.TestClusterConfig) { + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", minter.Address(), initMinterBalance)) + initialTotalSupply.Add(initialTotalSupply, initMinterBalance) + for i, addr := range addrs { - // first one is the owner of the NativeERC20Mintable SC - // and it should have premine set to default 1M tokens - // (it is going to send mint transactions to all the other validators) - if i > 0 { - // premine other validators with as minimum stake as possible just to ensure liveness of consensus protocol - config.StakeAmounts = append(config.StakeAmounts, fmt.Sprintf("%s:%d", addr, initialStake)) - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%d", addr, initialBalance)) - } + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", addr, initValidatorsBalance)) + config.StakeAmounts = append(config.StakeAmounts, new(big.Int).Set(initValidatorsBalance)) validatorsAddrs[i] = addr + initialTotalSupply.Add(initialTotalSupply, initValidatorsBalance) } })) defer cluster.Stop() - minterSrv := cluster.Servers[0] - targetJSONRPC := minterSrv.JSONRPC() - - minterAcc, err := sidechain.GetAccountFromDir(minterSrv.DataDir()) - require.NoError(t, err) + targetJSONRPC := cluster.Servers[0].JSONRPC() cluster.WaitForReady(t) - // send mint transactions + // initialize tx relayer relayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(targetJSONRPC)) require.NoError(t, err) + // check are native token metadata correctly initialized + stringABIType := abi.MustNewType("tuple(string)") + uint8ABIType := abi.MustNewType("tuple(uint8)") + + totalSupply := queryNativeERC20Metadata(t, "totalSupply", uint256ABIType, relayer) + require.True(t, initialTotalSupply.Cmp(totalSupply.(*big.Int)) == 0) //nolint:forcetypeassert + + // check if initial total supply of native ERC20 token is the same as expected + name := queryNativeERC20Metadata(t, "name", stringABIType, relayer) + require.Equal(t, tokenName, name) + + symbol := queryNativeERC20Metadata(t, "symbol", stringABIType, relayer) + require.Equal(t, tokenSymbol, symbol) + + decimalsCount := queryNativeERC20Metadata(t, "decimals", uint8ABIType, relayer) + require.Equal(t, decimals, decimalsCount) + + // send mint transactions mintFn, exists := contractsapi.NativeERC20Mintable.Abi.Methods["mint"] require.True(t, exists) - nativeTokenAddr := ethgo.Address(contracts.NativeERC20TokenContract) mintAmount := ethgo.Ether(10) + nativeTokenAddr := ethgo.Address(contracts.NativeERC20TokenContract) // make sure minter account can mint tokens - // (first account, which is minter sends mint transactions to all the other validators) - for _, addr := range validatorsAddrs[1:] { + for _, addr := range validatorsAddrs { balance, err := targetJSONRPC.Eth().GetBalance(ethgo.Address(addr), ethgo.Latest) require.NoError(t, err) t.Logf("Pre-mint balance: %v=%d\n", addr, balance) @@ -672,7 +540,7 @@ func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) { ðgo.Transaction{ To: &nativeTokenAddr, Input: mintInput, - }, minterAcc.Ecdsa) + }, minter) require.NoError(t, err) require.Equal(t, uint64(types.ReceiptSuccess), receipt.Status) @@ -680,18 +548,19 @@ func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) { require.NoError(t, err) t.Logf("Post-mint balance: %v=%d\n", addr, balance) - require.Equal(t, new(big.Int).Add(mintAmount, big.NewInt(initialBalance)), balance) + require.Equal(t, new(big.Int).Add(initValidatorsBalance, mintAmount), balance) } - minterBalance, err := targetJSONRPC.Eth().GetBalance(minterAcc.Ecdsa.Address(), ethgo.Latest) + // assert that minter balance remained the same + minterBalance, err := targetJSONRPC.Eth().GetBalance(minter.Address(), ethgo.Latest) require.NoError(t, err) - require.Equal(t, ethgo.Ether(1e6), minterBalance) + require.Equal(t, initMinterBalance, minterBalance) // try sending mint transaction from non minter account and make sure it would fail nonMinterAcc, err := sidechain.GetAccountFromDir(cluster.Servers[1].DataDir()) require.NoError(t, err) - mintInput, err := mintFn.Encode([]interface{}{validatorsAddrs[2], ethgo.Ether(1)}) + mintInput, err := mintFn.Encode([]interface{}{validatorsAddrs[0], ethgo.Ether(1)}) require.NoError(t, err) receipt, err := relayer.SendTransaction( @@ -699,8 +568,58 @@ func TestE2E_Consensus_MintableERC20NativeToken(t *testing.T) { To: &nativeTokenAddr, Input: mintInput, }, nonMinterAcc.Ecdsa) + require.Error(t, err) + require.Nil(t, receipt) +} + +func TestE2E_Consensus_CustomRewardToken(t *testing.T) { + const epochSize = 5 + + cluster := framework.NewTestCluster(t, 5, + framework.WithEpochSize(epochSize), + framework.WithEpochReward(1000000), + framework.WithTestRewardToken(), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + // initialize tx relayer + relayer, err := txrelayer.NewTxRelayer(txrelayer.WithClient(cluster.Servers[0].JSONRPC())) + require.NoError(t, err) + + // because we are not using native token as reward wallet, and have no premine + // initial token supply should be 0 + initialTotalSupply := big.NewInt(0) + + // check if initial total supply of native ERC20 token is the same as expected + totalSupply := queryNativeERC20Metadata(t, "totalSupply", uint256ABIType, relayer) + require.True(t, initialTotalSupply.Cmp(totalSupply.(*big.Int)) == 0) //nolint:forcetypeassert + + // wait for couple of epochs to accumulate some rewards + require.NoError(t, cluster.WaitForBlock(epochSize*3, 3*time.Minute)) + + // first validator is the owner of ChildValidator set smart contract + owner := cluster.Servers[0] + childChainRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(owner.JSONRPCAddr())) + require.NoError(t, err) + + rootChainRelayer, err := txrelayer.NewTxRelayer(txrelayer.WithIPAddress(cluster.Bridge.JSONRPCAddr())) + require.NoError(t, err) + + polybftConfig, err := polybft.LoadPolyBFTConfig(path.Join(cluster.Config.TmpDir, chainConfigFileName)) + require.NoError(t, err) + + validatorAcc, err := sidechain.GetAccountFromDir(owner.DataDir()) + require.NoError(t, err) + + validatorInfo, err := sidechain.GetValidatorInfo(validatorAcc.Ecdsa.Address(), + polybftConfig.Bridge.CustomSupernetManagerAddr, polybftConfig.Bridge.StakeManagerAddr, + polybftConfig.SupernetID, rootChainRelayer, childChainRelayer) + t.Logf("[Validator#%v] Witdhrawable rewards=%d\n", validatorInfo.Address, validatorInfo.WithdrawableRewards) + require.NoError(t, err) - require.Equal(t, uint64(types.ReceiptFailed), receipt.Status) + require.True(t, validatorInfo.WithdrawableRewards.Cmp(big.NewInt(0)) > 0) } func TestE2E_Consensus_Trace(t *testing.T) { @@ -711,13 +630,30 @@ func TestE2E_Consensus_Trace(t *testing.T) { validatorCount = 5 ) - cluster := framework.NewTestCluster(t, validatorCount, - framework.WithEpochReward(100000), - framework.WithEpochSize(epochSize)) + var ( + premineAmount = ethgo.Ether(10) + minterBalance = ethgo.Ether(1e6) + ) + + minter, err := wallet.GenerateKey() + require.NoError(t, err) + + cluster := framework.NewTestCluster(t, 5, + framework.WithEpochReward(int(ethgo.Ether(1).Uint64())), + framework.WithEpochSize(epochSize), + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, minter.Address())), + framework.WithSecretsCallback(func(addresses []types.Address, config *framework.TestClusterConfig) { + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", minter.Address(), minterBalance)) + for _, a := range addresses { + config.Premine = append(config.Premine, fmt.Sprintf("%s:%d", a, premineAmount)) + config.StakeAmounts = append(config.StakeAmounts, new(big.Int).Set(premineAmount)) + } + }), + ) defer cluster.Stop() // init new account - _, err := cluster.InitSecrets(newAccSecrets, 1) + _, err = cluster.InitSecrets(newAccSecrets, 1) require.NoError(t, err) cluster.WaitForReady(t) diff --git a/e2e-polybft/e2e/helpers_test.go b/e2e-polybft/e2e/helpers_test.go index 5065eec593..2db66a2502 100644 --- a/e2e-polybft/e2e/helpers_test.go +++ b/e2e-polybft/e2e/helpers_test.go @@ -9,19 +9,28 @@ import ( "math/big" "net/http" "testing" + "time" + + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/abi" + "github.com/umbracle/ethgo/contract" + "github.com/umbracle/ethgo/jsonrpc" "github.com/0xPolygon/polygon-edge/consensus/polybft" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi/artifact" + "github.com/0xPolygon/polygon-edge/contracts" + "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/state/runtime/addresslist" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" - "github.com/stretchr/testify/require" - "github.com/umbracle/ethgo" - "github.com/umbracle/ethgo/contract" - ethgow "github.com/umbracle/ethgo/wallet" ) +const nativeTokenMintableTestCfg = "Mintable Edge Coin:MEC:18:true:%s" + type e2eStateProvider struct { txRelayer txrelayer.TxRelayer } @@ -39,36 +48,15 @@ func (s *e2eStateProvider) Txn(ethgo.Address, ethgo.Key, []byte) (contract.Txn, return nil, errors.New("send txn is not supported") } -// isExitEventProcessed queries ExitHelper and as a result returns indication whether given exit event id is processed -func isExitEventProcessed(exitEventID uint64, exitHelper ethgo.Address, rootTxRelayer txrelayer.TxRelayer) (bool, error) { - result, err := ABICall( - rootTxRelayer, - contractsapi.ExitHelper, - exitHelper, - ethgo.ZeroAddress, - "processedExits", - new(big.Int).SetUint64(exitEventID)) - if err != nil { - return false, err - } - - isProcessed, err := types.ParseUint64orHex(&result) - if err != nil { - return false, err - } - - return isProcessed == uint64(1), nil -} - -// getRootchainValidators queries rootchain validator set -func getRootchainValidators(relayer txrelayer.TxRelayer, checkpointManagerAddr ethgo.Address) ([]*polybft.ValidatorInfo, error) { +// getCheckpointManagerValidators queries rootchain validator set on CheckpointManager contract +func getCheckpointManagerValidators(relayer txrelayer.TxRelayer, checkpointManagerAddr ethgo.Address) ([]*polybft.ValidatorInfo, error) { validatorsCountRaw, err := ABICall(relayer, contractsapi.CheckpointManager, checkpointManagerAddr, ethgo.ZeroAddress, "currentValidatorSetLength") if err != nil { return nil, err } - validatorsCount, err := types.ParseUint64orHex(&validatorsCountRaw) + validatorsCount, err := common.ParseUint64orHex(&validatorsCountRaw) if err != nil { return nil, err } @@ -100,8 +88,8 @@ func getRootchainValidators(relayer txrelayer.TxRelayer, checkpointManagerAddr e //nolint:forcetypeassert validators[i] = &polybft.ValidatorInfo{ - Address: results["_address"].(ethgo.Address), - TotalStake: results["votingPower"].(*big.Int), + Address: results["_address"].(ethgo.Address), + Stake: results["votingPower"].(*big.Int), } } @@ -129,52 +117,6 @@ func ABITransaction(relayer txrelayer.TxRelayer, key ethgo.Key, artifact *artifa }, key) } -func sendExitTransaction( - sidechainKey *ethgow.Key, - rootchainKey ethgo.Key, - proof types.Proof, - checkpointBlock uint64, - stateSenderData []byte, - l1ExitTestAddr, - exitHelperAddr ethgo.Address, - l1TxRelayer txrelayer.TxRelayer, - exitEventID uint64) (bool, error) { - var exitEventAPI contractsapi.L2StateSyncedEvent - - proofExitEventEncoded, err := exitEventAPI.Encode(&polybft.ExitEvent{ - ID: exitEventID, - Sender: sidechainKey.Address(), - Receiver: l1ExitTestAddr, - Data: stateSenderData, - }) - if err != nil { - return false, err - } - - leafIndex, ok := proof.Metadata["LeafIndex"].(float64) - if !ok { - return false, fmt.Errorf("could not get leaf index from exit event proof. Leaf from proof: %v", proof.Metadata["LeafIndex"]) - } - - receipt, err := ABITransaction(l1TxRelayer, rootchainKey, contractsapi.ExitHelper, exitHelperAddr, - "exit", - big.NewInt(int64(checkpointBlock)), - uint64(leafIndex), - proofExitEventEncoded, - proof.Data, - ) - - if err != nil { - return false, err - } - - if receipt.Status != uint64(types.ReceiptSuccess) { - return false, errors.New("transaction execution failed") - } - - return isExitEventProcessed(exitEventID, exitHelperAddr, l1TxRelayer) -} - func getExitProof(rpcAddress string, exitID uint64) (types.Proof, error) { query := struct { Jsonrpc string `json:"jsonrpc"` @@ -223,16 +165,186 @@ func checkStateSyncResultLogs( expectedCount int, ) { t.Helper() - require.Len(t, logs, expectedCount) + require.Equal(t, expectedCount, len(logs)) var stateSyncResultEvent contractsapi.StateSyncResultEvent for _, log := range logs { doesMatch, err := stateSyncResultEvent.ParseLog(log) - require.True(t, doesMatch) require.NoError(t, err) + require.True(t, doesMatch) t.Logf("Block Number=%d, Decoded Log=%+v\n", log.BlockNumber, stateSyncResultEvent) require.True(t, stateSyncResultEvent.Status) } } + +// getCheckpointBlockNumber gets current checkpoint block number from checkpoint manager smart contract +func getCheckpointBlockNumber(l1Relayer txrelayer.TxRelayer, checkpointManagerAddr ethgo.Address) (uint64, error) { + checkpointBlockNumRaw, err := ABICall(l1Relayer, contractsapi.CheckpointManager, + checkpointManagerAddr, ethgo.ZeroAddress, "currentCheckpointBlockNumber") + if err != nil { + return 0, err + } + + actualCheckpointBlock, err := types.ParseUint64orHex(&checkpointBlockNumRaw) + if err != nil { + return 0, err + } + + return actualCheckpointBlock, nil +} + +// waitForRootchainEpoch blocks for some predefined timeout to reach target epoch +func waitForRootchainEpoch(targetEpoch uint64, timeout time.Duration, + rootchainTxRelayer txrelayer.TxRelayer, checkpointManager types.Address) error { + timer := time.NewTimer(timeout) + defer timer.Stop() + + ticker := time.NewTicker(time.Second) + defer ticker.Stop() + + for { + select { + case <-timer.C: + return errors.New("root chain hasn't progressed to the desired epoch") + case <-ticker.C: + } + + rootchainEpochRaw, err := ABICall(rootchainTxRelayer, contractsapi.CheckpointManager, + ethgo.Address(checkpointManager), ethgo.ZeroAddress, "currentEpoch") + if err != nil { + return err + } + + rootchainEpoch, err := types.ParseUint64orHex(&rootchainEpochRaw) + if err != nil { + return err + } + + if rootchainEpoch >= targetEpoch { + return nil + } + } +} + +// setAccessListRole sets access list role to appropriate access list precompile +func setAccessListRole(t *testing.T, cluster *framework.TestCluster, precompile, account types.Address, + role addresslist.Role, aclAdmin ethgo.Key) { + t.Helper() + + var updateRoleFn *abi.Method + + switch role { + case addresslist.AdminRole: + updateRoleFn = addresslist.SetAdminFunc + + break + case addresslist.EnabledRole: + updateRoleFn = addresslist.SetEnabledFunc + + break + case addresslist.NoRole: + updateRoleFn = addresslist.SetNoneFunc + + break + } + + input, err := updateRoleFn.Encode([]interface{}{account}) + require.NoError(t, err) + + enableSetTxn := cluster.MethodTxn(t, aclAdmin, precompile, input) + require.NoError(t, enableSetTxn.Wait()) + + expectRole(t, cluster, precompile, account, role) +} + +func expectRole(t *testing.T, cluster *framework.TestCluster, contract types.Address, addr types.Address, role addresslist.Role) { + t.Helper() + out := cluster.Call(t, contract, addresslist.ReadAddressListFunc, addr) + + num, ok := out["0"].(*big.Int) + if !ok { + t.Fatal("unexpected") + } + + require.Equal(t, role.Uint64(), num.Uint64()) +} + +// getFilteredLogs retrieves Ethereum logs, described by event signature within the block range +func getFilteredLogs(eventSig ethgo.Hash, startBlock, endBlock uint64, + ethEndpoint *jsonrpc.Eth) ([]*ethgo.Log, error) { + filter := ðgo.LogFilter{Topics: [][]*ethgo.Hash{{&eventSig}}} + + filter.SetFromUint64(startBlock) + filter.SetToUint64(endBlock) + + return ethEndpoint.GetLogs(filter) +} + +// erc20BalanceOf returns balance of given account on ERC 20 token +func erc20BalanceOf(t *testing.T, account types.Address, tokenAddr types.Address, relayer txrelayer.TxRelayer) *big.Int { + t.Helper() + + balanceOfFn := &contractsapi.BalanceOfRootERC20Fn{Account: account} + balanceOfInput, err := balanceOfFn.EncodeAbi() + require.NoError(t, err) + + balanceRaw, err := relayer.Call(ethgo.ZeroAddress, ethgo.Address(tokenAddr), balanceOfInput) + require.NoError(t, err) + balance, err := types.ParseUint256orHex(&balanceRaw) + require.NoError(t, err) + + return balance +} + +// erc721OwnerOf returns owner of given ERC 721 token +func erc721OwnerOf(t *testing.T, tokenID *big.Int, tokenAddr types.Address, relayer txrelayer.TxRelayer) types.Address { + t.Helper() + + ownerOfFn := &contractsapi.OwnerOfChildERC721Fn{TokenID: tokenID} + ownerOfInput, err := ownerOfFn.EncodeAbi() + require.NoError(t, err) + + ownerRaw, err := relayer.Call(ethgo.ZeroAddress, ethgo.Address(tokenAddr), ownerOfInput) + require.NoError(t, err) + + return types.StringToAddress(ownerRaw) +} + +// queryNativeERC20Metadata returns some meta data user requires from native erc20 token +func queryNativeERC20Metadata(t *testing.T, funcName string, abiType *abi.Type, relayer txrelayer.TxRelayer) interface{} { + t.Helper() + + valueHex, err := ABICall(relayer, contractsapi.NativeERC20Mintable, + ethgo.Address(contracts.NativeERC20TokenContract), + ethgo.ZeroAddress, funcName) + require.NoError(t, err) + + valueRaw, err := hex.DecodeHex(valueHex) + require.NoError(t, err) + + var decodedResult map[string]interface{} + + err = abiType.DecodeStruct(valueRaw, &decodedResult) + require.NoError(t, err) + + return decodedResult["0"] +} + +// getChildToken queries child token address for provided root token on the target predicate +func getChildToken(t *testing.T, predicateABI *abi.ABI, predicateAddr types.Address, + rootToken types.Address, relayer txrelayer.TxRelayer) types.Address { + t.Helper() + + rootToChildTokenFn, exists := predicateABI.Methods["rootTokenToChildToken"] + require.True(t, exists, "rootTokenToChildToken function is not found in the provided predicate ABI definition") + + input, err := rootToChildTokenFn.Encode([]interface{}{rootToken}) + require.NoError(t, err) + + childTokenRaw, err := relayer.Call(ethgo.ZeroAddress, ethgo.Address(predicateAddr), input) + require.NoError(t, err) + + return types.StringToAddress(childTokenRaw) +} diff --git a/e2e-polybft/e2e/jsonrpc_test.go b/e2e-polybft/e2e/jsonrpc_test.go new file mode 100644 index 0000000000..03149db753 --- /dev/null +++ b/e2e-polybft/e2e/jsonrpc_test.go @@ -0,0 +1,308 @@ +package e2e + +import ( + "fmt" + "math/big" + "testing" + + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" + "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/types" + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/abi" + "github.com/umbracle/ethgo/wallet" +) + +var ( + one = big.NewInt(1) +) + +func TestE2E_JsonRPC(t *testing.T) { + acct, err := wallet.GenerateKey() + require.NoError(t, err) + + cluster := framework.NewTestCluster(t, 3, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, acct.Address())), + framework.WithPremine(types.Address(acct.Address())), + ) + defer cluster.Stop() + + cluster.WaitForReady(t) + + client := cluster.Servers[0].JSONRPC().Eth() + + // Test eth_call with override in state diff + t.Run("eth_call state override", func(t *testing.T) { + deployTxn := cluster.Deploy(t, acct, contractsapi.TestSimple.Bytecode) + require.NoError(t, deployTxn.Wait()) + require.True(t, deployTxn.Succeed()) + + target := deployTxn.Receipt().ContractAddress + + input := abi.MustNewMethod("function getValue() public returns (uint256)").ID() + + resp, err := client.Call(ðgo.CallMsg{To: &target, Data: input}, ethgo.Latest) + require.NoError(t, err) + require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000000", resp) + + override := ðgo.StateOverride{ + target: ethgo.OverrideAccount{ + StateDiff: &map[ethgo.Hash]ethgo.Hash{ + // storage slot 0 stores the 'val' uint256 value + {0x0}: {0x3}, + }, + }, + } + + resp, err = client.Call(ðgo.CallMsg{To: &target, Data: input}, ethgo.Latest, override) + require.NoError(t, err) + + require.Equal(t, "0x0300000000000000000000000000000000000000000000000000000000000000", resp) + }) + + t.Run("eth_getBalance", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + + // Test. return zero if the account does not exists + balance1, err := client.GetBalance(key1.Address(), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, balance1, big.NewInt(0)) + + // Test. return the balance of an account + newBalance := ethgo.Ether(1) + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), newBalance) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + balance1, err = client.GetBalance(key1.Address(), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, balance1, newBalance) + + // Test. return 0 if the balance of an existing account is empty + gasPrice, err := client.GasPrice() + require.NoError(t, err) + + toAddr := key1.Address() + msg := ðgo.CallMsg{ + From: acct.Address(), + To: &toAddr, + Value: newBalance, + } + + estimatedGas, err := client.EstimateGas(msg) + require.NoError(t, err) + txPrice := gasPrice * estimatedGas + // subtract gasPrice * estimatedGas from the balance and transfer the rest to the other account + // in order to leave no funds on the account + amountToSend := new(big.Int).Sub(newBalance, big.NewInt(int64(txPrice))) + targetAddr := acct.Address() + txn = cluster.SendTxn(t, key1, ðgo.Transaction{ + To: &targetAddr, + Value: amountToSend, + Gas: estimatedGas, + }) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + balance1, err = client.GetBalance(key1.Address(), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, big.NewInt(0), balance1) + }) + + t.Run("eth_getTransactionCount", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + + nonce, err := client.GetNonce(key1.Address(), ethgo.Latest) + require.Equal(t, uint64(0), nonce) + require.NoError(t, err) + + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), big.NewInt(10000000000000000)) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + // Test. increase the nonce with new transactions + txn = cluster.Transfer(t, key1, types.ZeroAddress, big.NewInt(0)) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + nonce1, err := client.GetNonce(key1.Address(), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, nonce1, uint64(1)) + + // Test. you can query the nonce at any block number in time + nonce1, err = client.GetNonce(key1.Address(), ethgo.BlockNumber(txn.Receipt().BlockNumber-1)) + require.NoError(t, err) + require.Equal(t, nonce1, uint64(0)) + + block, err := client.GetBlockByNumber(ethgo.BlockNumber(txn.Receipt().BlockNumber)-1, false) + require.NoError(t, err) + + _, err = client.GetNonce(key1.Address(), ethgo.BlockNumber(block.Number)) + require.NoError(t, err) + }) + + t.Run("eth_getStorageAt", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + txn = cluster.Deploy(t, acct, contractsapi.TestSimple.Bytecode) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + target := txn.Receipt().ContractAddress + + resp, err := client.GetStorageAt(target, ethgo.Hash{}, ethgo.Latest) + require.NoError(t, err) + require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000000", resp.String()) + + setValueFn := abi.MustNewMethod("function setValue(uint256 _val) public") + + newVal := big.NewInt(1) + + input, err := setValueFn.Encode([]interface{}{newVal}) + require.NoError(t, err) + + txn = cluster.SendTxn(t, acct, ðgo.Transaction{Input: input, To: &target}) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + resp, err = client.GetStorageAt(target, ethgo.Hash{}, ethgo.Latest) + require.NoError(t, err) + require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000001", resp.String()) + }) + + t.Run("eth_getCode", func(t *testing.T) { + // we use a predefined private key so that the deployed contract address is deterministic. + // Note that in order to work, this private key should only be used for this test. + priv, err := hex.DecodeString("2c15bd0dc992a47ca660983ae4b611f4ffb6178e14e04e2b34d153f3a74ce741") + require.NoError(t, err) + key1, err := wallet.NewWalletFromPrivKey(priv) + require.NoError(t, err) + + // fund the account so that it can deploy a contract + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), big.NewInt(10000000000000000)) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + codeAddr := ethgo.HexToAddress("0xDBfca0c43cA12759256a7Dd587Dc4c6EEC1D89A5") + + // Test. We get empty code from an empty contract + code, err := client.GetCode(codeAddr, ethgo.Latest) + require.NoError(t, err) + require.Equal(t, code, "0x") + + txn = cluster.Deploy(t, key1, contractsapi.TestSimple.Bytecode) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + receipt := txn.Receipt() + + // Test. The deployed address is the one expected + require.Equal(t, codeAddr, receipt.ContractAddress) + + // Test. We can retrieve the code by address on latest, block number and block hash + cases := []ethgo.BlockNumberOrHash{ + ethgo.Latest, + ethgo.BlockNumber(receipt.BlockNumber), + } + for _, c := range cases { + code, err = client.GetCode(codeAddr, c) + require.NoError(t, err) + require.NotEqual(t, code, "0x") + } + + // Test. We can query in past state (when the code was empty) + code, err = client.GetCode(codeAddr, ethgo.BlockNumber(receipt.BlockNumber-1)) + require.NoError(t, err) + require.Equal(t, code, "0x") + + // Test. Query by pending should default to latest + code, err = client.GetCode(codeAddr, ethgo.Pending) + require.NoError(t, err) + require.NotEqual(t, code, "0x") + }) + + t.Run("eth_getBlockByHash", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + txReceipt := txn.Receipt() + + block, err := client.GetBlockByHash(txReceipt.BlockHash, false) + require.NoError(t, err) + require.Equal(t, txReceipt.BlockNumber, block.Number) + require.Equal(t, txReceipt.BlockHash, block.Hash) + }) + + t.Run("eth_getBlockByNumber", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + txReceipt := txn.Receipt() + + block, err := client.GetBlockByNumber(ethgo.BlockNumber(txReceipt.BlockNumber), false) + require.NoError(t, err) + require.Equal(t, txReceipt.BlockNumber, block.Number) + require.Equal(t, txReceipt.BlockHash, block.Hash) + }) + + t.Run("eth_getTransactionReceipt", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + // Test. We cannot retrieve a receipt of an empty hash + emptyReceipt, err := client.GetTransactionReceipt(ethgo.ZeroHash) + require.NoError(t, err) // Note that ethgo does not return an error when the item does not exists + require.Nil(t, emptyReceipt) + + // Test. We can retrieve the receipt by the hash + receipt, err := client.GetTransactionReceipt(txn.Receipt().TransactionHash) + require.NoError(t, err) + + // Test. The populated fields match with the block + block, err := client.GetBlockByHash(receipt.BlockHash, false) + require.NoError(t, err) + + require.Equal(t, receipt.TransactionHash, txn.Receipt().TransactionHash) + require.Equal(t, receipt.BlockNumber, block.Number) + require.Equal(t, receipt.BlockHash, block.Hash) + + // Test. The receipt of a deployed contract has the 'ContractAddress' field. + txn = cluster.Deploy(t, acct, contractsapi.TestSimple.Bytecode) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + require.NotEqual(t, txn.Receipt().ContractAddress, ethgo.ZeroAddress) + }) + + t.Run("eth_getTransactionByHash", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + + // Test. We should be able to query the transaction by its hash + txn := cluster.Transfer(t, acct, types.Address(key1.Address()), one) + require.NoError(t, txn.Wait()) + require.True(t, txn.Succeed()) + + ethTxn, err := client.GetTransactionByHash(txn.Receipt().TransactionHash) + require.NoError(t, err) + + // Test. The dynamic 'from' field is populated + require.NotEqual(t, ethTxn.From, ethgo.ZeroAddress) + }) +} diff --git a/e2e-polybft/e2e/migration_test.go b/e2e-polybft/e2e/migration_test.go index dd7ba4ce9e..50b91f7d32 100644 --- a/e2e-polybft/e2e/migration_test.go +++ b/e2e-polybft/e2e/migration_test.go @@ -21,7 +21,7 @@ import ( "github.com/umbracle/ethgo/wallet" ) -func TestMigration(t *testing.T) { +func TestE2E_Migration(t *testing.T) { userKey, _ := wallet.GenerateKey() userAddr := userKey.Address() userKey2, _ := wallet.GenerateKey() @@ -60,20 +60,18 @@ func TestMigration(t *testing.T) { //send transaction to user2 sendAmount := ethgo.Gwei(10000) receipt, err := relayer.SendTransaction(ðgo.Transaction{ - From: userAddr, - To: &userAddr2, - GasPrice: 1048576, - Gas: 1000000, - Value: sendAmount, + From: userAddr, + To: &userAddr2, + Gas: 1000000, + Value: sendAmount, }, userKey) assert.NoError(t, err) assert.NotNil(t, receipt) receipt, err = relayer.SendTransaction(ðgo.Transaction{ - From: userAddr, - GasPrice: 1048576, - Gas: 1000000, - Input: contractsapi.TestWriteBlockMetadata.Bytecode, + From: userAddr, + Gas: 1000000, + Input: contractsapi.TestWriteBlockMetadata.Bytecode, }, userKey) require.NoError(t, err) require.NotNil(t, receipt) @@ -204,6 +202,6 @@ func TestMigration(t *testing.T) { _, err = cluster.InitSecrets("test-chain-8", 1) require.NoError(t, err) - cluster.InitTestServer(t, 8, false, false) + cluster.InitTestServer(t, "test-chain-8", cluster.Bridge.JSONRPCAddr(), false, false) require.NoError(t, cluster.WaitForBlock(33, time.Minute)) } diff --git a/e2e-polybft/e2e/network_test.go b/e2e-polybft/e2e/network_test.go index e1f5128ac3..c04a1320c1 100644 --- a/e2e-polybft/e2e/network_test.go +++ b/e2e-polybft/e2e/network_test.go @@ -20,8 +20,7 @@ func TestE2E_NetworkDiscoveryProtocol(t *testing.T) { ) // create cluster - cluster := framework.NewTestCluster(t, 10, - framework.WithValidatorSnapshot(validatorCount), + cluster := framework.NewTestCluster(t, validatorCount, framework.WithNonValidators(nonValidatorCount), framework.WithBootnodeCount(1)) defer cluster.Stop() diff --git a/e2e-polybft/e2e/txpool_test.go b/e2e-polybft/e2e/txpool_test.go index 91cb52384a..d8b5017cd4 100644 --- a/e2e-polybft/e2e/txpool_test.go +++ b/e2e-polybft/e2e/txpool_test.go @@ -1,20 +1,23 @@ package e2e import ( + "fmt" "math/big" "sync" "testing" "time" - "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" - "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" - "github.com/0xPolygon/polygon-edge/txrelayer" - "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/umbracle/ethgo" "github.com/umbracle/ethgo/jsonrpc" "github.com/umbracle/ethgo/wallet" + + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" + "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" + "github.com/0xPolygon/polygon-edge/txrelayer" + "github.com/0xPolygon/polygon-edge/types" ) func TestE2E_TxPool_Transfer(t *testing.T) { @@ -22,7 +25,10 @@ func TestE2E_TxPool_Transfer(t *testing.T) { sender, err := wallet.GenerateKey() require.NoError(t, err) - cluster := framework.NewTestCluster(t, 5, framework.WithPremine(types.Address(sender.Address()))) + cluster := framework.NewTestCluster(t, 5, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, sender.Address())), + framework.WithPremine(types.Address(sender.Address())), + framework.WithBurnContract(&polybft.BurnContractInfo{BlockNumber: 0, Address: types.ZeroAddress})) defer cluster.Stop() cluster.WaitForReady(t) @@ -48,17 +54,27 @@ func TestE2E_TxPool_Transfer(t *testing.T) { go func(i int, to ethgo.Address) { defer wg.Done() - gasPrice, err := client.GasPrice() - require.NoError(t, err) - txn := ðgo.Transaction{ - From: sender.Address(), - To: &to, - GasPrice: gasPrice, - Gas: 30000, // enough to send a transfer - Value: big.NewInt(int64(sendAmount)), - Nonce: uint64(i), + From: sender.Address(), + To: &to, + Gas: 30000, // enough to send a transfer + Value: big.NewInt(int64(sendAmount)), + Nonce: uint64(i), + } + + // Send every second transaction as a dynamic fees one + if i%2 == 0 { + txn.Type = ethgo.TransactionDynamicFee + txn.MaxFeePerGas = big.NewInt(1000000000) + txn.MaxPriorityFeePerGas = big.NewInt(100000000) + } else { + gasPrice, err := client.GasPrice() + require.NoError(t, err) + + txn.Type = ethgo.TransactionLegacy + txn.GasPrice = gasPrice } + sendTransaction(t, client, sender, txn) }(i, receivers[i]) } @@ -88,7 +104,11 @@ func TestE2E_TxPool_Transfer_Linear(t *testing.T) { require.NoError(t, err) // first account should have some matics premined - cluster := framework.NewTestCluster(t, 5, framework.WithPremine(types.Address(premine.Address()))) + cluster := framework.NewTestCluster(t, 5, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, premine.Address())), + framework.WithPremine(types.Address(premine.Address())), + framework.WithBurnContract(&polybft.BurnContractInfo{BlockNumber: 0, Address: types.ZeroAddress}), + ) defer cluster.Stop() cluster.WaitForReady(t) @@ -112,6 +132,17 @@ func TestE2E_TxPool_Transfer_Linear(t *testing.T) { return err } + populateTxFees := func(txn *ethgo.Transaction, i int) { + if i%2 == 0 { + txn.Type = ethgo.TransactionDynamicFee + txn.MaxFeePerGas = big.NewInt(1000000000) + txn.MaxPriorityFeePerGas = big.NewInt(100000000) + } else { + txn.Type = ethgo.TransactionLegacy + txn.GasPrice = gasPrice + } + } + num := 4 receivers := []*wallet.Key{ premine, @@ -124,11 +155,7 @@ func TestE2E_TxPool_Transfer_Linear(t *testing.T) { receivers = append(receivers, key) } - // Gas cost is always the same since value transfers are deterministic (21k gas). - // Then, the total gas cost required to make a transfer is 21k multiplied by - // the selected gas price. - gasCost := int(21000 * gasPrice) - sendAmount := 3000000 + const sendAmount = 3000000 // We are going to fund the accounts in linear fashion: // A (premined account) -> B -> C -> D -> E @@ -139,15 +166,23 @@ func TestE2E_TxPool_Transfer_Linear(t *testing.T) { // its child i+1 (cover costs + send amounts). // This means that since gasCost and sendAmount are fixed, account C must receive gasCost * 2 // (to cover two more transfers C->D and D->E) + sendAmount * 3 (one bundle for each C,D and E). - amount := gasCost*(num-i-1) + sendAmount*(num-i) recipient := receivers[i].Address() txn := ðgo.Transaction{ - Value: big.NewInt(int64(amount)), - To: &recipient, - GasPrice: gasPrice, - Gas: 21000, - Nonce: 0, + Value: big.NewInt(int64(sendAmount * (num - i))), + To: &recipient, + Gas: 21000, + } + + // Populate fees fields for the current transaction + populateTxFees(txn, i-1) + + // Add remaining fees to finish the cycle + for j := i; j < num; j++ { + copyTxn := txn.Copy() + populateTxFees(copyTxn, j) + txn.Value = txn.Value.Add(txn.Value, txCost(copyTxn)) } + sendTransaction(t, client, receivers[i-1], txn) err := waitUntilBalancesChanged(receivers[i].Address()) @@ -161,11 +196,12 @@ func TestE2E_TxPool_Transfer_Linear(t *testing.T) { } } -func TestE2E_TxPool_TransactionWithHeaderInstuctions(t *testing.T) { +func TestE2E_TxPool_TransactionWithHeaderInstructions(t *testing.T) { sidechainKey, err := wallet.GenerateKey() require.NoError(t, err) cluster := framework.NewTestCluster(t, 4, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, sidechainKey.Address())), framework.WithPremine(types.Address(sidechainKey.Address())), ) defer cluster.Stop() @@ -186,6 +222,87 @@ func TestE2E_TxPool_TransactionWithHeaderInstuctions(t *testing.T) { require.NoError(t, cluster.WaitForBlock(10, 1*time.Minute)) } +// TestE2E_TxPool_BroadcastTransactions sends several transactions (legacy and dynamic fees) to the cluster +// with the 1 amount of eth and checks that all cluster nodes have the recipient balance updated. +func TestE2E_TxPool_BroadcastTransactions(t *testing.T) { + var ( + sendAmount = ethgo.Ether(1) + ) + + const ( + txNum = 10 + ) + + // Create recipient key + key, err := wallet.GenerateKey() + assert.NoError(t, err) + + recipient := key.Address() + + t.Logf("Recipient %s\n", recipient) + + // Create pre-mined balance for sender + sender, err := wallet.GenerateKey() + require.NoError(t, err) + + // First account should have some matics premined + cluster := framework.NewTestCluster(t, 5, + framework.WithNativeTokenConfig(fmt.Sprintf(nativeTokenMintableTestCfg, sender.Address())), + framework.WithPremine(types.Address(sender.Address())), + framework.WithBurnContract(&polybft.BurnContractInfo{BlockNumber: 0, Address: types.ZeroAddress}), + ) + defer cluster.Stop() + + // Wait until the cluster is up and running + cluster.WaitForReady(t) + + client := cluster.Servers[0].JSONRPC().Eth() + + sentAmount := new(big.Int) + nonce := uint64(0) + + for i := 0; i < txNum; i++ { + txn := ðgo.Transaction{ + Value: sendAmount, + To: &recipient, + Gas: 21000, + Nonce: nonce, + } + + if i%2 == 0 { + txn.Type = ethgo.TransactionDynamicFee + txn.MaxFeePerGas = big.NewInt(1000000000) + txn.MaxPriorityFeePerGas = big.NewInt(100000000) + } else { + gasPrice, err := client.GasPrice() + require.NoError(t, err) + + txn.Type = ethgo.TransactionLegacy + txn.GasPrice = gasPrice + } + + sendTransaction(t, client, sender, txn) + sentAmount = sentAmount.Add(sentAmount, txn.Value) + nonce++ + } + + // Wait until the balance has changed on all nodes in the cluster + err = cluster.WaitUntil(time.Minute, time.Second*3, func() bool { + for _, srv := range cluster.Servers { + balance, err := srv.WaitForNonZeroBalance(recipient, time.Second*10) + assert.NoError(t, err) + if balance != nil && balance.BitLen() > 0 { + assert.Equal(t, sentAmount, balance) + } else { + return false + } + } + + return true + }) + assert.NoError(t, err) +} + // sendTransaction is a helper function which signs transaction with provided private key and sends it func sendTransaction(t *testing.T, client *jsonrpc.Eth, sender *wallet.Key, txn *ethgo.Transaction) { t.Helper() @@ -193,6 +310,10 @@ func sendTransaction(t *testing.T, client *jsonrpc.Eth, sender *wallet.Key, txn chainID, err := client.ChainID() require.NoError(t, err) + if txn.Type == ethgo.TransactionDynamicFee { + txn.ChainID = chainID + } + signer := wallet.NewEIP155Signer(chainID.Uint64()) signedTxn, err := signer.SignTx(txn, sender) require.NoError(t, err) @@ -203,3 +324,15 @@ func sendTransaction(t *testing.T, client *jsonrpc.Eth, sender *wallet.Key, txn _, err = client.SendRawTransaction(txnRaw) require.NoError(t, err) } + +func txCost(t *ethgo.Transaction) *big.Int { + var factor *big.Int + + if t.Type == ethgo.TransactionDynamicFee { + factor = new(big.Int).Set(t.MaxFeePerGas) + } else { + factor = new(big.Int).SetUint64(t.GasPrice) + } + + return new(big.Int).Mul(factor, new(big.Int).SetUint64(t.Gas)) +} diff --git a/e2e-polybft/framework/node.go b/e2e-polybft/framework/node.go index 8cac0d299b..37241dfebb 100644 --- a/e2e-polybft/framework/node.go +++ b/e2e-polybft/framework/node.go @@ -8,7 +8,7 @@ import ( ) type node struct { - shuttingDown uint64 + shuttingDown atomic.Bool cmd *exec.Cmd doneCh chan struct{} exitResult *exitResult @@ -52,7 +52,7 @@ func (n *node) run() { } func (n *node) IsShuttingDown() bool { - return atomic.LoadUint64(&n.shuttingDown) == 1 + return n.shuttingDown.Load() } func (n *node) Stop() error { @@ -65,7 +65,7 @@ func (n *node) Stop() error { return err } - atomic.StoreUint64(&n.shuttingDown, 1) + n.shuttingDown.Store(true) <-n.Wait() return nil diff --git a/e2e-polybft/framework/test-bridge.go b/e2e-polybft/framework/test-bridge.go index 162b704dc3..927ba1ec35 100644 --- a/e2e-polybft/framework/test-bridge.go +++ b/e2e-polybft/framework/test-bridge.go @@ -1,14 +1,26 @@ package framework import ( + "context" "errors" "fmt" + "math/big" "path" "strconv" + "strings" "testing" "time" + "golang.org/x/sync/errgroup" + + "github.com/0xPolygon/polygon-edge/command" + bridgeCommon "github.com/0xPolygon/polygon-edge/command/bridge/common" + "github.com/0xPolygon/polygon-edge/command/genesis" + "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" "github.com/0xPolygon/polygon-edge/command/rootchain/server" + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/types" ) @@ -92,65 +104,188 @@ func (t *TestBridge) WaitUntil(pollFrequency, timeout time.Duration, handler fun } } -// DepositERC20 function invokes bridge deposit ERC20 tokens (from the root to the child chain) -// with given receivers and amounts -func (t *TestBridge) DepositERC20(rootTokenAddr, rootPredicateAddr types.Address, receivers, amounts string) error { +// Deposit function invokes bridge deposit of ERC tokens (from the root to the child chain) +// with given receivers, amounts and/or token ids +func (t *TestBridge) Deposit(token bridgeCommon.TokenType, rootTokenAddr, rootPredicateAddr types.Address, + senderKey, receivers, amounts, tokenIDs, jsonRPCAddr, minterKey string, childChainMintable bool) error { + args := []string{} + if receivers == "" { return errors.New("provide at least one receiver address value") } - if amounts == "" { - return errors.New("provide at least one amount value") + if jsonRPCAddr == "" { + return errors.New("provide a JSON RPC endpoint URL") } - return t.cmdRun( - "bridge", - "deposit-erc20", - "--test", - "--root-token", rootTokenAddr.String(), - "--root-predicate", rootPredicateAddr.String(), - "--receivers", receivers, - "--amounts", amounts) + switch token { + case bridgeCommon.ERC20: + if amounts == "" { + return errors.New("provide at least one amount value") + } + + if tokenIDs != "" { + return errors.New("not expected to provide token ids for ERC 20 deposits") + } + + args = append(args, + "bridge", + "deposit-erc20", + "--root-token", rootTokenAddr.String(), + "--root-predicate", rootPredicateAddr.String(), + "--receivers", receivers, + "--amounts", amounts, + "--sender-key", senderKey, + "--minter-key", minterKey, + "--json-rpc", jsonRPCAddr) + + if childChainMintable { + args = append(args, "--child-chain-mintable") + } + + case bridgeCommon.ERC721: + if tokenIDs == "" { + return errors.New("provide at least one token id value") + } + + args = append(args, + "bridge", + "deposit-erc721", + "--root-token", rootTokenAddr.String(), + "--root-predicate", rootPredicateAddr.String(), + "--receivers", receivers, + "--token-ids", tokenIDs, + "--sender-key", senderKey, + "--minter-key", minterKey, + "--json-rpc", jsonRPCAddr) + + if childChainMintable { + args = append(args, "--child-chain-mintable") + } + + case bridgeCommon.ERC1155: + if amounts == "" { + return errors.New("provide at least one amount value") + } + + if tokenIDs == "" { + return errors.New("provide at least one token id value") + } + + args = append(args, + "bridge", + "deposit-erc1155", + "--root-token", rootTokenAddr.String(), + "--root-predicate", rootPredicateAddr.String(), + "--receivers", receivers, + "--amounts", amounts, + "--token-ids", tokenIDs, + "--sender-key", senderKey, + "--minter-key", minterKey, + "--json-rpc", jsonRPCAddr) + + if childChainMintable { + args = append(args, "--child-chain-mintable") + } + } + + return t.cmdRun(args...) } -// WithdrawERC20 function is used to invoke bridge withdraw ERC20 tokens (from the child to the root chain) -// with given receivers and amounts -func (t *TestBridge) WithdrawERC20(senderKey, receivers, amounts, jsonRPCEndpoint string) error { +// Withdraw function is used to invoke bridge withdrawals for any kind of ERC tokens (from the child to the root chain) +// with given receivers, amounts and/or token ids +func (t *TestBridge) Withdraw(token bridgeCommon.TokenType, + senderKey, receivers, amounts, tokenIDs, jsonRPCAddr string, + childPredicate, childToken types.Address, childChainMintable bool) error { if senderKey == "" { - return errors.New("provide hex encoded sender private key") + return errors.New("provide hex-encoded sender private key") } if receivers == "" { return errors.New("provide at least one receiver address value") } - if amounts == "" { - return errors.New("provide at least one amount value") + if jsonRPCAddr == "" { + return errors.New("provide a JSON RPC endpoint URL") } - if jsonRPCEndpoint == "" { - return errors.New("provide a JSON RPC endpoint URL") + args := []string{} + + switch token { + case bridgeCommon.ERC20: + if amounts == "" { + return errors.New("provide at least one amount value") + } + + if tokenIDs != "" { + return errors.New("not expected to provide token ids for ERC 20 withdrawals") + } + + args = append(args, + "bridge", + "withdraw-erc20", + "--child-predicate", childPredicate.String(), + "--child-token", childToken.String(), + "--sender-key", senderKey, + "--receivers", receivers, + "--amounts", amounts, + "--json-rpc", jsonRPCAddr) + + if childChainMintable { + args = append(args, "--child-chain-mintable") + } + + case bridgeCommon.ERC721: + if tokenIDs == "" { + return errors.New("provide at least one token id value") + } + + args = append(args, + "bridge", + "withdraw-erc721", + "--child-predicate", childPredicate.String(), + "--child-token", childToken.String(), + "--sender-key", senderKey, + "--receivers", receivers, + "--token-ids", tokenIDs, + "--json-rpc", jsonRPCAddr) + + if childChainMintable { + args = append(args, "--child-chain-mintable") + } + + case bridgeCommon.ERC1155: + if amounts == "" { + return errors.New("provide at least one amount value") + } + + if tokenIDs == "" { + return errors.New("provide at least one token id value") + } + + args = append(args, + "bridge", + "withdraw-erc1155", + "--child-predicate", childPredicate.String(), + "--child-token", childToken.String(), + "--sender-key", senderKey, + "--receivers", receivers, + "--amounts", amounts, + "--token-ids", tokenIDs, + "--json-rpc", jsonRPCAddr) + + if childChainMintable { + args = append(args, "--child-chain-mintable") + } } - return t.cmdRun( - "bridge", - "withdraw-erc20", - "--sender-key", senderKey, - "--receivers", receivers, - "--amounts", amounts, - "--json-rpc", jsonRPCEndpoint, - ) + return t.cmdRun(args...) } // SendExitTransaction sends exit transaction to the root chain -func (t *TestBridge) SendExitTransaction(exitHelper types.Address, exitID uint64, - rootJSONRPCAddr, childJSONRPCAddr string) error { - if rootJSONRPCAddr == "" { - return errors.New("provide a root JSON RPC endpoint URL") - } - +func (t *TestBridge) SendExitTransaction(exitHelper types.Address, exitID uint64, childJSONRPCAddr string) error { if childJSONRPCAddr == "" { - return errors.New("provide a child JSON RPC endpoint URL") + return errors.New("provide a child chain JSON RPC endpoint URL") } return t.cmdRun( @@ -158,7 +293,7 @@ func (t *TestBridge) SendExitTransaction(exitHelper types.Address, exitID uint64 "exit", "--exit-helper", exitHelper.String(), "--exit-id", strconv.FormatUint(exitID, 10), - "--root-json-rpc", rootJSONRPCAddr, + "--root-json-rpc", t.JSONRPCAddr(), "--child-json-rpc", childJSONRPCAddr, "--test", ) @@ -170,11 +305,18 @@ func (t *TestBridge) cmdRun(args ...string) error { } // deployRootchainContracts deploys and initializes rootchain contracts -func (t *TestBridge) deployRootchainContracts(manifestPath string) error { +func (t *TestBridge) deployRootchainContracts(genesisPath string) error { + polybftConfig, err := polybft.LoadPolyBFTConfig(genesisPath) + if err != nil { + return err + } + args := []string{ "rootchain", - "init-contracts", - "--manifest", manifestPath, + "deploy", + "--stake-manager", polybftConfig.Bridge.StakeManagerAddr.String(), + "--stake-token", polybftConfig.Bridge.StakeTokenAddr.String(), + "--genesis", genesisPath, "--test", } @@ -186,16 +328,202 @@ func (t *TestBridge) deployRootchainContracts(manifestPath string) error { } // fundRootchainValidators sends predefined amount of tokens to rootchain validators -func (t *TestBridge) fundRootchainValidators() error { +func (t *TestBridge) fundRootchainValidators(polybftConfig polybft.PolyBFTConfig) error { + validatorSecrets, err := genesis.GetValidatorKeyFiles(t.clusterConfig.TmpDir, t.clusterConfig.ValidatorPrefix) + if err != nil { + return fmt.Errorf("could not get validator secrets on initial rootchain funding of genesis validators: %w", err) + } + + balances := make([]*big.Int, len(polybftConfig.InitialValidatorSet)) + secrets := make([]string, len(validatorSecrets)) + + for i, secret := range validatorSecrets { + secrets[i] = path.Join(t.clusterConfig.TmpDir, secret) + balances[i] = command.DefaultPremineBalance + } + + if err := t.FundValidators(polybftConfig.Bridge.StakeTokenAddr, + secrets, balances); err != nil { + return fmt.Errorf("failed to fund validators on the rootchain: %w", err) + } + + return nil +} + +func (t *TestBridge) whitelistValidators(validatorAddresses []types.Address, + polybftConfig polybft.PolyBFTConfig) error { + addressesAsString := make([]string, len(validatorAddresses)) + for i := 0; i < len(validatorAddresses); i++ { + addressesAsString[i] = validatorAddresses[i].String() + } + + args := []string{ + "polybft", + "whitelist-validators", + "--addresses", strings.Join(addressesAsString, ","), + "--jsonrpc", t.JSONRPCAddr(), + "--supernet-manager", polybftConfig.Bridge.CustomSupernetManagerAddr.String(), + "--private-key", rootHelper.TestAccountPrivKey, + } + + if err := t.cmdRun(args...); err != nil { + return fmt.Errorf("failed to whitelist genesis validators on supernet manager: %w", err) + } + + return nil +} + +func (t *TestBridge) registerGenesisValidators(polybftConfig polybft.PolyBFTConfig) error { + validatorSecrets, err := genesis.GetValidatorKeyFiles(t.clusterConfig.TmpDir, t.clusterConfig.ValidatorPrefix) + if err != nil { + return fmt.Errorf("could not get validator secrets on whitelist of genesis validators: %w", err) + } + + g, ctx := errgroup.WithContext(context.Background()) + + for _, secret := range validatorSecrets { + secret := secret + + g.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + args := []string{ + "polybft", + "register-validator", + "--jsonrpc", t.JSONRPCAddr(), + "--supernet-manager", polybftConfig.Bridge.CustomSupernetManagerAddr.String(), + "--" + polybftsecrets.AccountDirFlag, path.Join(t.clusterConfig.TmpDir, secret), + } + + if err := t.cmdRun(args...); err != nil { + return fmt.Errorf("failed to register genesis validator on supernet manager: %w", err) + } + + return nil + } + }) + } + + return g.Wait() +} + +func (t *TestBridge) initialStakingOfGenesisValidators(polybftConfig polybft.PolyBFTConfig) error { + validatorSecrets, err := genesis.GetValidatorKeyFiles(t.clusterConfig.TmpDir, t.clusterConfig.ValidatorPrefix) + if err != nil { + return fmt.Errorf("could not get validator secrets on initial staking of genesis validators: %w", err) + } + + g, ctx := errgroup.WithContext(context.Background()) + + for i, secret := range validatorSecrets { + secret := secret + i := i + + g.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + args := []string{ + "polybft", + "stake", + "--jsonrpc", t.JSONRPCAddr(), + "--stake-manager", polybftConfig.Bridge.StakeManagerAddr.String(), + "--" + polybftsecrets.AccountDirFlag, path.Join(t.clusterConfig.TmpDir, secret), + "--amount", t.getStakeAmount(i).String(), + "--supernet-id", strconv.FormatInt(polybftConfig.SupernetID, 10), + "--stake-token", polybftConfig.Bridge.StakeTokenAddr.String(), + } + + if err := t.cmdRun(args...); err != nil { + return fmt.Errorf("failed to do initial staking for genesis validator on stake manager: %w", err) + } + + return nil + } + }) + } + + return g.Wait() +} + +func (t *TestBridge) getStakeAmount(validatorIndex int) *big.Int { + l := len(t.clusterConfig.StakeAmounts) + if l == 0 || l <= validatorIndex { + return command.DefaultStake + } + + return t.clusterConfig.StakeAmounts[validatorIndex] +} + +func (t *TestBridge) finalizeGenesis(genesisPath string, polybftConfig polybft.PolyBFTConfig) error { + args := []string{ + "polybft", + "supernet", + "--jsonrpc", t.JSONRPCAddr(), + "--private-key", rootHelper.TestAccountPrivKey, + "--genesis", genesisPath, + "--supernet-manager", polybftConfig.Bridge.CustomSupernetManagerAddr.String(), + "--stake-manager", polybftConfig.Bridge.StakeManagerAddr.String(), + "--finalize-genesis-set", + "--enable-staking", + } + + if err := t.cmdRun(args...); err != nil { + return fmt.Errorf("failed to finalize genesis validators on supernet manager: %w", err) + } + + return nil +} + +// FundValidators sends tokens to a rootchain validators +func (t *TestBridge) FundValidators(tokenAddress types.Address, secretsPaths []string, amounts []*big.Int) error { + if len(secretsPaths) != len(amounts) { + return errors.New("expected the same length of secrets paths and amounts") + } + args := []string{ "rootchain", "fund", - "--data-dir", path.Join(t.clusterConfig.TmpDir, t.clusterConfig.ValidatorPrefix), - "--num", strconv.Itoa(int(t.clusterConfig.ValidatorSetSize) + t.clusterConfig.NonValidatorCount), + "--stake-token", tokenAddress.String(), + "--mint", + } + + for i := 0; i < len(secretsPaths); i++ { + secretsManager, err := polybftsecrets.GetSecretsManager(secretsPaths[i], "", true) + if err != nil { + return err + } + + key, err := wallet.GetEcdsaFromSecret(secretsManager) + if err != nil { + return err + } + + args = append(args, "--addresses", key.Address().String()) + args = append(args, "--amounts", amounts[i].String()) + } + + if err := t.cmdRun(args...); err != nil { + return err + } + + return nil +} + +func (t *TestBridge) deployStakeManager(genesisPath string) error { + args := []string{ + "polybft", + "stake-manager-deploy", + "--jsonrpc", t.JSONRPCAddr(), + "--genesis", genesisPath, + "--test", } if err := t.cmdRun(args...); err != nil { - return fmt.Errorf("failed to deploy fund validators: %w", err) + return fmt.Errorf("failed to deploy stake manager contract: %w", err) } return nil diff --git a/e2e-polybft/framework/test-cluster.go b/e2e-polybft/framework/test-cluster.go index bd83e3e351..eb57b9c321 100644 --- a/e2e-polybft/framework/test-cluster.go +++ b/e2e-polybft/framework/test-cluster.go @@ -19,7 +19,8 @@ import ( "time" "github.com/0xPolygon/polygon-edge/command/genesis" - "github.com/0xPolygon/polygon-edge/command/rootchain/helper" + "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/contractsapi" "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/txrelayer" "github.com/0xPolygon/polygon-edge/types" @@ -43,16 +44,17 @@ const ( // envStdoutEnabled signal whether the output of the nodes get piped to stdout envStdoutEnabled = "E2E_STDOUT" - // envE2ETestsType used just to display type of test if skipped - envE2ETestsType = "E2E_TESTS_TYPE" -) - -const ( // prefix for validator directory defaultValidatorPrefix = "test-chain-" + + // prefix for non validators directory + nonValidatorPrefix = "test-non-validator-" ) -var startTime int64 +var ( + startTime int64 + testRewardWalletAddr = types.StringToAddress("0xFFFFFFFF") +) func init() { startTime = time.Now().UTC().UnixMilli() @@ -70,34 +72,48 @@ func resolveBinary() string { type TestClusterConfig struct { t *testing.T - Name string - Premine []string // address[:amount] - PremineValidators []string // address:[amount] - StakeAmounts []string // address[:amount] - MintableNativeToken bool - HasBridge bool - BootnodeCount int - NonValidatorCount int - WithLogs bool - WithStdout bool - LogsDir string - TmpDir string - BlockGasLimit uint64 - ValidatorPrefix string - Binary string - ValidatorSetSize uint64 - EpochSize int - EpochReward int - SecretsCallback func([]types.Address, *TestClusterConfig) + Name string + Premine []string // address[:amount] + PremineValidators []string // address[:amount] + StakeAmounts []*big.Int + WithoutBridge bool + BootnodeCount int + NonValidatorCount int + WithLogs bool + WithStdout bool + LogsDir string + TmpDir string + BlockGasLimit uint64 + BurnContract *polybft.BurnContractInfo + ValidatorPrefix string + Binary string + ValidatorSetSize uint64 + EpochSize int + EpochReward int + NativeTokenConfigRaw string + SecretsCallback func([]types.Address, *TestClusterConfig) ContractDeployerAllowListAdmin []types.Address ContractDeployerAllowListEnabled []types.Address + ContractDeployerBlockListAdmin []types.Address + ContractDeployerBlockListEnabled []types.Address + TransactionsAllowListAdmin []types.Address + TransactionsAllowListEnabled []types.Address + TransactionsBlockListAdmin []types.Address + TransactionsBlockListEnabled []types.Address + BridgeAllowListAdmin []types.Address + BridgeAllowListEnabled []types.Address + BridgeBlockListAdmin []types.Address + BridgeBlockListEnabled []types.Address NumBlockConfirmations uint64 InitialTrieDB string InitialStateRoot types.Hash + IsPropertyTest bool + TestRewardToken string + logsDirOnce sync.Once } @@ -145,6 +161,12 @@ func (c *TestClusterConfig) GetStdout(name string, custom ...io.Writer) io.Write func (c *TestClusterConfig) initLogsDir() { logsDir := path.Join("../..", fmt.Sprintf("e2e-logs-%d", startTime), c.t.Name()) + if c.IsPropertyTest { + // property tests run cluster multiple times, so each cluster run will be in the main folder + // e2e-logs-{someNumber}/NameOfPropertyTest/NameOfPropertyTest-{someNumber} + // to have a separation between logs of each cluster run + logsDir = path.Join(logsDir, fmt.Sprintf("%v-%d", c.t.Name(), time.Now().UTC().Unix())) + } if err := common.CreateDirSafe(logsDir, 0750); err != nil { c.t.Fatal(err) @@ -177,21 +199,15 @@ func WithPremine(addresses ...types.Address) ClusterOption { } } -func WithMintableNativeToken(mintableToken bool) ClusterOption { - return func(h *TestClusterConfig) { - h.MintableNativeToken = mintableToken - } -} - func WithSecretsCallback(fn func([]types.Address, *TestClusterConfig)) ClusterOption { return func(h *TestClusterConfig) { h.SecretsCallback = fn } } -func WithBridge() ClusterOption { +func WithoutBridge() ClusterOption { return func(h *TestClusterConfig) { - h.HasBridge = true + h.WithoutBridge = true } } @@ -238,6 +254,12 @@ func WithBlockGasLimit(blockGasLimit uint64) ClusterOption { } } +func WithBurnContract(burnContract *polybft.BurnContractInfo) ClusterOption { + return func(h *TestClusterConfig) { + h.BurnContract = burnContract + } +} + func WithNumBlockConfirmations(numBlockConfirmations uint64) ClusterOption { return func(h *TestClusterConfig) { h.NumBlockConfirmations = numBlockConfirmations @@ -256,25 +278,110 @@ func WithContractDeployerAllowListEnabled(addr types.Address) ClusterOption { } } +func WithContractDeployerBlockListAdmin(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.ContractDeployerBlockListAdmin = append(h.ContractDeployerBlockListAdmin, addr) + } +} + +func WithContractDeployerBlockListEnabled(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.ContractDeployerBlockListEnabled = append(h.ContractDeployerBlockListEnabled, addr) + } +} + +func WithTransactionsAllowListAdmin(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.TransactionsAllowListAdmin = append(h.TransactionsAllowListAdmin, addr) + } +} + +func WithTransactionsAllowListEnabled(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.TransactionsAllowListEnabled = append(h.TransactionsAllowListEnabled, addr) + } +} + +func WithTransactionsBlockListAdmin(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.TransactionsBlockListAdmin = append(h.TransactionsBlockListAdmin, addr) + } +} + +func WithTransactionsBlockListEnabled(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.TransactionsBlockListEnabled = append(h.TransactionsBlockListEnabled, addr) + } +} + +func WithBridgeAllowListAdmin(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.BridgeAllowListAdmin = append(h.BridgeAllowListAdmin, addr) + } +} + +func WithBridgeAllowListEnabled(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.BridgeAllowListEnabled = append(h.BridgeAllowListEnabled, addr) + } +} + +func WithBridgeBlockListAdmin(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.BridgeBlockListAdmin = append(h.BridgeBlockListAdmin, addr) + } +} + +func WithBridgeBlockListEnabled(addr types.Address) ClusterOption { + return func(h *TestClusterConfig) { + h.BridgeBlockListEnabled = append(h.BridgeBlockListEnabled, addr) + } +} + +func WithPropertyTestLogging() ClusterOption { + return func(h *TestClusterConfig) { + h.IsPropertyTest = true + } +} + +func WithNativeTokenConfig(tokenConfigRaw string) ClusterOption { + return func(h *TestClusterConfig) { + h.NativeTokenConfigRaw = tokenConfigRaw + } +} + +func WithTestRewardToken() ClusterOption { + return func(h *TestClusterConfig) { + h.TestRewardToken = hex.EncodeToString(contractsapi.TestRewardToken.DeployedBytecode) + } +} + func isTrueEnv(e string) bool { return strings.ToLower(os.Getenv(e)) == "true" } +func NewPropertyTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *TestCluster { + t.Helper() + + opts = append(opts, WithPropertyTestLogging()) + + return NewTestCluster(t, validatorsCount, opts...) +} + func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *TestCluster { t.Helper() var err error config := &TestClusterConfig{ - t: t, - WithLogs: isTrueEnv(envLogsEnabled), - WithStdout: isTrueEnv(envStdoutEnabled), - Binary: resolveBinary(), - EpochSize: 10, - EpochReward: 1, - BlockGasLimit: 1e7, // 10M - PremineValidators: []string{}, - StakeAmounts: []string{}, + t: t, + WithLogs: isTrueEnv(envLogsEnabled), + WithStdout: isTrueEnv(envStdoutEnabled), + Binary: resolveBinary(), + EpochSize: 10, + EpochReward: 1, + BlockGasLimit: 1e7, // 10M + StakeAmounts: []*big.Int{}, } if config.ValidatorPrefix == "" { @@ -286,8 +393,10 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T } if !isTrueEnv(envE2ETestsEnabled) { - testType := os.Getenv(envE2ETestsType) - if testType == "" { + var testType string + if config.IsPropertyTest { + testType = "property" + } else { testType = "integration" } @@ -305,83 +414,64 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T once: sync.Once{}, } - { - // run init accounts - addresses, err := cluster.InitSecrets(cluster.Config.ValidatorPrefix, validatorsCount) - require.NoError(t, err) - - if cluster.Config.SecretsCallback != nil { - cluster.Config.SecretsCallback(addresses, cluster.Config) - } - } - - manifestPath := path.Join(config.TmpDir, "manifest.json") - args := []string{ - "manifest", - "--path", manifestPath, - "--validators-path", config.TmpDir, - "--validators-prefix", cluster.Config.ValidatorPrefix, - } - - // premine validators - for _, premineValidator := range cluster.Config.PremineValidators { - args = append(args, "--premine-validators", premineValidator) - } - - for _, validatorStake := range cluster.Config.StakeAmounts { - args = append(args, "--stake", validatorStake) - } - - // run manifest file creation - require.NoError(t, cluster.cmdRun(args...)) - - if cluster.Config.HasBridge { - // start bridge - cluster.Bridge, err = NewTestBridge(t, cluster.Config) - require.NoError(t, err) - } - // in case no validators are specified in opts, all nodes will be validators if cluster.Config.ValidatorSetSize == 0 { cluster.Config.ValidatorSetSize = uint64(validatorsCount) } - if cluster.Config.HasBridge { - err := cluster.Bridge.deployRootchainContracts(manifestPath) - require.NoError(t, err) + // run init accounts for validators + addresses, err := cluster.InitSecrets(cluster.Config.ValidatorPrefix, int(cluster.Config.ValidatorSetSize)) + require.NoError(t, err) + + if cluster.Config.SecretsCallback != nil { + cluster.Config.SecretsCallback(addresses, cluster.Config) + } - err = cluster.Bridge.fundRootchainValidators() + if config.NonValidatorCount > 0 { + // run init accounts for non-validators + // we don't call secrets callback on non-validators, + // since we have nothing to premine nor stake for non validators + _, err = cluster.InitSecrets(nonValidatorPrefix, config.NonValidatorCount) require.NoError(t, err) } + genesisPath := path.Join(config.TmpDir, "genesis.json") + { // run genesis configuration population args := []string{ "genesis", - "--manifest", manifestPath, - "--consensus", "polybft", - "--dir", path.Join(config.TmpDir, "genesis.json"), + "--validators-path", config.TmpDir, + "--validators-prefix", cluster.Config.ValidatorPrefix, + "--dir", genesisPath, "--block-gas-limit", strconv.FormatUint(cluster.Config.BlockGasLimit, 10), "--epoch-size", strconv.Itoa(cluster.Config.EpochSize), "--epoch-reward", strconv.Itoa(cluster.Config.EpochReward), "--premine", "0x0000000000000000000000000000000000000000", + "--reward-wallet", testRewardWalletAddr.String(), "--trieroot", cluster.Config.InitialStateRoot.String(), } + if cluster.Config.TestRewardToken != "" { + args = append(args, "--reward-token-code", cluster.Config.TestRewardToken) + } + + // add optional genesis flags + if cluster.Config.NativeTokenConfigRaw != "" { + args = append(args, "--native-token-config", cluster.Config.NativeTokenConfigRaw) + } + if len(cluster.Config.Premine) != 0 { for _, premine := range cluster.Config.Premine { args = append(args, "--premine", premine) } } - if cluster.Config.MintableNativeToken { - args = append(args, "--mintable-native-token") - } - - if cluster.Config.HasBridge { - rootchainIP, err := helper.ReadRootchainIP() - require.NoError(t, err) - args = append(args, "--bridge-json-rpc", rootchainIP) + burnContract := cluster.Config.BurnContract + if burnContract != nil { + args = append(args, "--burn-contract", + fmt.Sprintf("%d:%s:%s", + burnContract.BlockNumber, burnContract.Address, burnContract.DestinationAddress)) } validators, err := genesis.ReadValidatorsByPrefix( @@ -399,10 +489,6 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T } } - if cluster.Config.ValidatorSetSize > 0 { - args = append(args, "--validator-set-size", fmt.Sprint(cluster.Config.ValidatorSetSize)) - } - if len(cluster.Config.ContractDeployerAllowListAdmin) != 0 { args = append(args, "--contract-deployer-allow-list-admin", strings.Join(sliceAddressToSliceString(cluster.Config.ContractDeployerAllowListAdmin), ",")) @@ -413,29 +499,120 @@ func NewTestCluster(t *testing.T, validatorsCount int, opts ...ClusterOption) *T strings.Join(sliceAddressToSliceString(cluster.Config.ContractDeployerAllowListEnabled), ",")) } - // run cmd init-genesis with all the arguments + if len(cluster.Config.ContractDeployerBlockListAdmin) != 0 { + args = append(args, "--contract-deployer-block-list-admin", + strings.Join(sliceAddressToSliceString(cluster.Config.ContractDeployerBlockListAdmin), ",")) + } + + if len(cluster.Config.ContractDeployerBlockListEnabled) != 0 { + args = append(args, "--contract-deployer-block-list-enabled", + strings.Join(sliceAddressToSliceString(cluster.Config.ContractDeployerBlockListEnabled), ",")) + } + + if len(cluster.Config.TransactionsAllowListAdmin) != 0 { + args = append(args, "--transactions-allow-list-admin", + strings.Join(sliceAddressToSliceString(cluster.Config.TransactionsAllowListAdmin), ",")) + } + + if len(cluster.Config.TransactionsAllowListEnabled) != 0 { + args = append(args, "--transactions-allow-list-enabled", + strings.Join(sliceAddressToSliceString(cluster.Config.TransactionsAllowListEnabled), ",")) + } + + if len(cluster.Config.TransactionsBlockListAdmin) != 0 { + args = append(args, "--transactions-block-list-admin", + strings.Join(sliceAddressToSliceString(cluster.Config.TransactionsBlockListAdmin), ",")) + } + + if len(cluster.Config.TransactionsBlockListEnabled) != 0 { + args = append(args, "--transactions-block-list-enabled", + strings.Join(sliceAddressToSliceString(cluster.Config.TransactionsBlockListEnabled), ",")) + } + + if len(cluster.Config.BridgeAllowListAdmin) != 0 { + args = append(args, "--bridge-allow-list-admin", + strings.Join(sliceAddressToSliceString(cluster.Config.BridgeAllowListAdmin), ",")) + } + + if len(cluster.Config.BridgeAllowListEnabled) != 0 { + args = append(args, "--bridge-allow-list-enabled", + strings.Join(sliceAddressToSliceString(cluster.Config.BridgeAllowListEnabled), ",")) + } + + if len(cluster.Config.BridgeBlockListAdmin) != 0 { + args = append(args, "--bridge-block-list-admin", + strings.Join(sliceAddressToSliceString(cluster.Config.BridgeBlockListAdmin), ",")) + } + + if len(cluster.Config.BridgeBlockListEnabled) != 0 { + args = append(args, "--bridge-block-list-enabled", + strings.Join(sliceAddressToSliceString(cluster.Config.BridgeBlockListEnabled), ",")) + } + + // run genesis command with all the arguments err = cluster.cmdRun(args...) require.NoError(t, err) } + if !cluster.Config.WithoutBridge { + // start bridge + cluster.Bridge, err = NewTestBridge(t, cluster.Config) + require.NoError(t, err) + + // deploy stake manager contract + err := cluster.Bridge.deployStakeManager(genesisPath) + require.NoError(t, err) + + // deploy rootchain contracts + err = cluster.Bridge.deployRootchainContracts(genesisPath) + require.NoError(t, err) + + polybftConfig, err := polybft.LoadPolyBFTConfig(genesisPath) + require.NoError(t, err) + + // fund validators on the rootchain + err = cluster.Bridge.fundRootchainValidators(polybftConfig) + require.NoError(t, err) + + // whitelist genesis validators on the rootchain + err = cluster.Bridge.whitelistValidators(addresses, polybftConfig) + require.NoError(t, err) + + // register genesis validators on the rootchain + err = cluster.Bridge.registerGenesisValidators(polybftConfig) + require.NoError(t, err) + + // do initial staking for genesis validators on the rootchain + err = cluster.Bridge.initialStakingOfGenesisValidators(polybftConfig) + require.NoError(t, err) + + // finalize genesis validators on the rootchain + err = cluster.Bridge.finalizeGenesis(genesisPath, polybftConfig) + require.NoError(t, err) + } + for i := 1; i <= int(cluster.Config.ValidatorSetSize); i++ { - cluster.InitTestServer(t, i, true, cluster.Config.HasBridge && i == 1 /* relayer */) + dir := cluster.Config.ValidatorPrefix + strconv.Itoa(i) + cluster.InitTestServer(t, dir, cluster.Bridge.JSONRPCAddr(), + true, !cluster.Config.WithoutBridge && i == 1 /* relayer */) } for i := 1; i <= cluster.Config.NonValidatorCount; i++ { - offsetIndex := i + int(cluster.Config.ValidatorSetSize) - cluster.InitTestServer(t, offsetIndex, false, false /* relayer */) + dir := nonValidatorPrefix + strconv.Itoa(i) + cluster.InitTestServer(t, dir, cluster.Bridge.JSONRPCAddr(), + false, false /* relayer */) } return cluster } -func (c *TestCluster) InitTestServer(t *testing.T, i int, isValidator bool, relayer bool) { +func (c *TestCluster) InitTestServer(t *testing.T, + dataDir string, bridgeJSONRPC string, isValidator bool, relayer bool) { t.Helper() logLevel := os.Getenv(envLogLevel) - dataDir := c.Config.Dir(c.Config.ValidatorPrefix + strconv.Itoa(i)) + dataDir = c.Config.Dir(dataDir) if c.Config.InitialTrieDB != "" { err := CopyDir(c.Config.InitialTrieDB, filepath.Join(dataDir, "trie")) if err != nil { @@ -443,7 +620,7 @@ func (c *TestCluster) InitTestServer(t *testing.T, i int, isValidator bool, rela } } - srv := NewTestServer(t, c.Config, func(config *TestServerConfig) { + srv := NewTestServer(t, c.Config, bridgeJSONRPC, func(config *TestServerConfig) { config.DataDir = dataDir config.Seal = isValidator config.Chain = c.Config.Dir("genesis.json") @@ -451,6 +628,7 @@ func (c *TestCluster) InitTestServer(t *testing.T, i int, isValidator bool, rela config.LogLevel = logLevel config.Relayer = relayer config.NumBlockConfirmations = c.Config.NumBlockConfirmations + config.BridgeJSONRPC = bridgeJSONRPC }) // watch the server for stop signals. It is important to fix the specific @@ -524,7 +702,7 @@ func (c *TestCluster) WaitUntil(timeout, pollFrequency time.Duration, handler fu func (c *TestCluster) WaitForReady(t *testing.T) { t.Helper() - require.NoError(t, c.WaitForBlock(1, 30*time.Second)) + require.NoError(t, c.WaitForBlock(1, time.Minute)) } func (c *TestCluster) WaitForBlock(n uint64, timeout time.Duration) error { @@ -679,7 +857,7 @@ func (c *TestCluster) Call(t *testing.T, to types.Address, method *abi.Method, func (c *TestCluster) Deploy(t *testing.T, sender ethgo.Key, bytecode []byte) *TestTxn { t.Helper() - return c.SendTxn(t, sender, ðgo.Transaction{Input: bytecode}) + return c.SendTxn(t, sender, ðgo.Transaction{From: sender.Address(), Input: bytecode}) } func (c *TestCluster) Transfer(t *testing.T, sender ethgo.Key, target types.Address, value *big.Int) *TestTxn { @@ -687,7 +865,7 @@ func (c *TestCluster) Transfer(t *testing.T, sender ethgo.Key, target types.Addr targetAddr := ethgo.Address(target) - return c.SendTxn(t, sender, ðgo.Transaction{To: &targetAddr, Value: value}) + return c.SendTxn(t, sender, ðgo.Transaction{From: sender.Address(), To: &targetAddr, Value: value}) } func (c *TestCluster) MethodTxn(t *testing.T, sender ethgo.Key, target types.Address, input []byte) *TestTxn { @@ -695,7 +873,7 @@ func (c *TestCluster) MethodTxn(t *testing.T, sender ethgo.Key, target types.Add targetAddr := ethgo.Address(target) - return c.SendTxn(t, sender, ðgo.Transaction{To: &targetAddr, Input: input}) + return c.SendTxn(t, sender, ðgo.Transaction{From: sender.Address(), To: &targetAddr, Input: input}) } // SendTxn sends a transaction @@ -721,11 +899,23 @@ func (c *TestCluster) SendTxn(t *testing.T, sender ethgo.Key, txn *ethgo.Transac } if txn.GasPrice == 0 { - txn.GasPrice = txrelayer.DefaultGasPrice + gasPrice, err := client.Eth().GasPrice() + require.NoError(t, err) + + txn.GasPrice = gasPrice } if txn.Gas == 0 { - txn.Gas = txrelayer.DefaultGasLimit + callMsg := txrelayer.ConvertTxnToCallMsg(txn) + + gasLimit, err := client.Eth().EstimateGas(callMsg) + if err != nil { + // gas estimation can fail in case an account is not allow-listed + // (fallback it to default gas limit in that case) + txn.Gas = txrelayer.DefaultGasLimit + } else { + txn.Gas = gasLimit + } } chainID, err := client.Eth().ChainID() @@ -741,13 +931,11 @@ func (c *TestCluster) SendTxn(t *testing.T, sender ethgo.Key, txn *ethgo.Transac hash, err := client.Eth().SendRawTransaction(txnRaw) require.NoError(t, err) - tTxn := &TestTxn{ + return &TestTxn{ client: client.Eth(), txn: txn, hash: hash, } - - return tTxn } type TestTxn struct { diff --git a/e2e-polybft/framework/test-server.go b/e2e-polybft/framework/test-server.go index b71f4cfc38..1c49b5adba 100644 --- a/e2e-polybft/framework/test-server.go +++ b/e2e-polybft/framework/test-server.go @@ -1,22 +1,26 @@ package framework import ( + "errors" "fmt" "io/ioutil" "math/big" - "path" "strconv" + "strings" "sync/atomic" "testing" "time" "github.com/0xPolygon/polygon-edge/command/polybftsecrets" + rootHelper "github.com/0xPolygon/polygon-edge/command/rootchain/helper" "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/consensus/polybft/validator" + "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/server/proto" txpoolProto "github.com/0xPolygon/polygon-edge/txpool/proto" "github.com/0xPolygon/polygon-edge/types" "github.com/google/uuid" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/umbracle/ethgo" "github.com/umbracle/ethgo/jsonrpc" "google.golang.org/grpc" @@ -33,6 +37,7 @@ type TestServerConfig struct { LogLevel string Relayer bool NumBlockConfirmations uint64 + BridgeJSONRPC string } type TestServerConfigCallback func(*TestServerConfig) @@ -48,6 +53,7 @@ func getOpenPortForServer() int64 { type TestServer struct { t *testing.T + address types.Address clusterConfig *TestClusterConfig config *TestServerConfig node *node @@ -61,6 +67,10 @@ func (t *TestServer) JSONRPCAddr() string { return fmt.Sprintf("http://%s:%d", hostIP, t.config.JSONRPCPort) } +func (t *TestServer) BridgeJSONRPCAddr() string { + return t.config.BridgeJSONRPC +} + func (t *TestServer) JSONRPC() *jsonrpc.Client { clt, err := jsonrpc.NewClient(t.JSONRPCAddr()) if err != nil { @@ -92,14 +102,16 @@ func (t *TestServer) TxnPoolOperator() txpoolProto.TxnPoolOperatorClient { return txpoolProto.NewTxnPoolOperatorClient(conn) } -func NewTestServer(t *testing.T, clusterConfig *TestClusterConfig, callback TestServerConfigCallback) *TestServer { +func NewTestServer(t *testing.T, clusterConfig *TestClusterConfig, + bridgeJSONRPC string, callback TestServerConfigCallback) *TestServer { t.Helper() config := &TestServerConfig{ - Name: uuid.New().String(), - JSONRPCPort: getOpenPortForServer(), - GRPCPort: getOpenPortForServer(), - P2PPort: getOpenPortForServer(), + Name: uuid.New().String(), + JSONRPCPort: getOpenPortForServer(), + GRPCPort: getOpenPortForServer(), + P2PPort: getOpenPortForServer(), + BridgeJSONRPC: bridgeJSONRPC, } if callback != nil { @@ -108,14 +120,21 @@ func NewTestServer(t *testing.T, clusterConfig *TestClusterConfig, callback Test if config.DataDir == "" { dataDir, err := ioutil.TempDir("/tmp", "edge-e2e-") - assert.NoError(t, err) + require.NoError(t, err) config.DataDir = dataDir } + secretsManager, err := polybftsecrets.GetSecretsManager(config.DataDir, "", true) + require.NoError(t, err) + + key, err := wallet.GetEcdsaFromSecret(secretsManager) + require.NoError(t, err) + srv := &TestServer{ t: t, clusterConfig: clusterConfig, + address: types.Address(key.Address()), config: config, } srv.Start() @@ -180,107 +199,143 @@ func (t *TestServer) Stop() { t.node = nil } +// RootchainFund funds given validator account on the rootchain +func (t *TestServer) RootchainFund(stakeToken types.Address, amount *big.Int) error { + return t.RootchainFundFor([]types.Address{t.address}, []*big.Int{amount}, stakeToken) +} + +// RootchainFundFor funds given account on the rootchain +func (t *TestServer) RootchainFundFor(accounts []types.Address, amounts []*big.Int, stakeToken types.Address) error { + if len(accounts) != len(amounts) { + return errors.New("same size for accounts and amounts must be provided to the rootchain funding") + } + + args := []string{ + "rootchain", + "fund", + "--json-rpc", t.BridgeJSONRPCAddr(), + "--stake-token", stakeToken.String(), + "--mint", + } + + for i := 0; i < len(accounts); i++ { + args = append(args, "--addresses", accounts[i].String()) + args = append(args, "--amounts", amounts[i].String()) + } + + if err := runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("bridge")); err != nil { + acctAddrs := make([]string, len(accounts)) + for i, acc := range accounts { + acctAddrs[i] = acc.String() + } + + return fmt.Errorf("failed to fund accounts (%s) on the rootchain: %w", strings.Join(acctAddrs, ","), err) + } + + return nil +} + // Stake stakes given amount to validator account encapsulated by given server instance -func (t *TestServer) Stake(amount uint64) error { +func (t *TestServer) Stake(polybftConfig polybft.PolyBFTConfig, amount *big.Int) error { args := []string{ "polybft", "stake", + "--jsonrpc", t.BridgeJSONRPCAddr(), + "--stake-manager", polybftConfig.Bridge.StakeManagerAddr.String(), "--" + polybftsecrets.AccountDirFlag, t.config.DataDir, - "--jsonrpc", t.JSONRPCAddr(), - "--amount", strconv.FormatUint(amount, 10), - "--self", + "--amount", amount.String(), + "--supernet-id", strconv.FormatInt(polybftConfig.SupernetID, 10), + "--stake-token", polybftConfig.Bridge.StakeTokenAddr.String(), } return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("stake")) } // Unstake unstakes given amount from validator account encapsulated by given server instance -func (t *TestServer) Unstake(amount uint64) error { +func (t *TestServer) Unstake(amount *big.Int) error { args := []string{ "polybft", "unstake", "--" + polybftsecrets.AccountDirFlag, t.config.DataDir, "--jsonrpc", t.JSONRPCAddr(), - "--amount", strconv.FormatUint(amount, 10), - "--self", + "--amount", amount.String(), } - return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("stake")) + return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("unstake")) } -// RegisterValidator is a wrapper function which registers new validator with given balance and stake -func (t *TestServer) RegisterValidator(secrets string, stake string) error { +// RegisterValidator is a wrapper function which registers new validator on a root chain +func (t *TestServer) RegisterValidator(supernetManagerAddr types.Address) error { args := []string{ "polybft", "register-validator", - "--" + polybftsecrets.AccountDirFlag, path.Join(t.clusterConfig.TmpDir, secrets), - "--jsonrpc", t.JSONRPCAddr(), - } - - if stake != "" { - args = append(args, "--stake", stake) + "--jsonrpc", t.BridgeJSONRPCAddr(), + "--supernet-manager", supernetManagerAddr.String(), + "--" + polybftsecrets.AccountDirFlag, t.DataDir(), } - return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("register-validator")) + return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("bridge")) } -// WhitelistValidator invokes whitelist-validator helper CLI command, -// which sends whitelist transaction to ChildValidatorSet -func (t *TestServer) WhitelistValidator(address, secrets string) error { +// WhitelistValidators invokes whitelist-validators helper CLI command, +// that whitelists validators on the root chain +func (t *TestServer) WhitelistValidators(addresses []string, supernetManager types.Address) error { args := []string{ "polybft", - "whitelist-validator", - "--" + polybftsecrets.AccountDirFlag, path.Join(t.clusterConfig.TmpDir, secrets), - "--address", address, - "--jsonrpc", t.JSONRPCAddr(), + "whitelist-validators", + "--private-key", rootHelper.TestAccountPrivKey, + "--jsonrpc", t.BridgeJSONRPCAddr(), + "--supernet-manager", supernetManager.String(), + } + for _, addr := range addresses { + args = append(args, "--addresses", addr) } - return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("whitelist-validator")) + return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("bridge")) } -// Delegate delegates given amount by the account in secrets to validatorAddr validator -func (t *TestServer) Delegate(amount uint64, secrets string, validatorAddr ethgo.Address) error { +// WithdrawChildChain withdraws available balance from child chain +func (t *TestServer) WithdrawChildChain() error { args := []string{ "polybft", - "stake", - "--" + polybftsecrets.AccountDirFlag, secrets, + "withdraw-child", + "--" + polybftsecrets.AccountDirFlag, t.config.DataDir, "--jsonrpc", t.JSONRPCAddr(), - "--delegate", validatorAddr.String(), - "--amount", strconv.FormatUint(amount, 10), } - return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("delegation")) + return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("withdraw-child")) } -// Undelegate undelegates given amount by the account in secrets from validatorAddr validator -func (t *TestServer) Undelegate(amount uint64, secrets string, validatorAddr ethgo.Address) error { +// WithdrawRootChain withdraws available balance from root chain +func (t *TestServer) WithdrawRootChain(recipient string, amount *big.Int, + stakeManager ethgo.Address, bridgeJSONRPC string) error { args := []string{ "polybft", - "unstake", - "--" + polybftsecrets.AccountDirFlag, secrets, - "--undelegate", validatorAddr.String(), - "--amount", strconv.FormatUint(amount, 10), - "--jsonrpc", t.JSONRPCAddr(), + "withdraw-root", + "--" + polybftsecrets.AccountDirFlag, t.config.DataDir, + "--to", recipient, + "--amount", amount.String(), + "--stake-manager", stakeManager.String(), + "--jsonrpc", bridgeJSONRPC, } - return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("delegation")) + return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("withdraw-root")) } -// Withdraw withdraws available balance to provided recipient address -func (t *TestServer) Withdraw(secrets string, recipient ethgo.Address) error { +// WithdrawRewards withdraws pending rewards for given validator on RewardPool contract +func (t *TestServer) WithdrawRewards() error { args := []string{ "polybft", - "withdraw", - "--" + polybftsecrets.AccountDirFlag, secrets, - "--to", recipient.String(), + "withdraw-rewards", + "--" + polybftsecrets.AccountDirFlag, t.config.DataDir, "--jsonrpc", t.JSONRPCAddr(), } - return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("withdrawal")) + return runCommand(t.clusterConfig.Binary, args, t.clusterConfig.GetStdout("withdraw-rewards")) } // HasValidatorSealed checks whether given validator has signed at least single block for the given range of blocks -func (t *TestServer) HasValidatorSealed(firstBlock, lastBlock uint64, validators polybft.AccountSet, +func (t *TestServer) HasValidatorSealed(firstBlock, lastBlock uint64, validators validator.AccountSet, validatorAddr ethgo.Address) (bool, error) { rpcClient := t.JSONRPC() for i := firstBlock + 1; i <= lastBlock; i++ { diff --git a/e2e-polybft/property/property_test.go b/e2e-polybft/property/property_test.go index 9231cb829a..d43a179993 100644 --- a/e2e-polybft/property/property_test.go +++ b/e2e-polybft/property/property_test.go @@ -3,46 +3,54 @@ package property import ( "fmt" "math" + "math/big" + "path/filepath" "testing" "time" - "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" - "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/require" "pgregory.net/rapid" + + "github.com/0xPolygon/polygon-edge/e2e-polybft/framework" + "github.com/0xPolygon/polygon-edge/types" ) func TestProperty_DifferentVotingPower(t *testing.T) { t.Parallel() const ( - blockTime = time.Second * 6 - maxPremine = math.MaxUint64 + blockTime = time.Second * 6 + maxStake = math.MaxUint64 ) rapid.Check(t, func(tt *rapid.T) { var ( - numNodes = rapid.Uint64Range(4, 8).Draw(tt, "number of cluster nodes") + numNodes = rapid.Uint64Range(5, 8).Draw(tt, "number of cluster nodes") epochSize = rapid.OneOf(rapid.Just(4), rapid.Just(10)).Draw(tt, "epoch size") numBlocks = rapid.Uint64Range(2, 5).Draw(tt, "number of blocks the cluster should mine") ) - premine := make([]uint64, numNodes) + stakes := make([]*big.Int, numNodes) - // premined amount will determine validator's stake and therefore voting power - for i := range premine { - premine[i] = rapid.Uint64Range(1, maxPremine).Draw(tt, fmt.Sprintf("stake for node %d", i+1)) + // stake amount will determine validator's stake and therefore voting power + for i := range stakes { + stakes[i] = new(big.Int). + SetUint64(rapid.Uint64Range(1, maxStake). + Draw(tt, fmt.Sprintf("stake for node %d", i+1))) } - cluster := framework.NewTestCluster(t, int(numNodes), + cluster := framework.NewPropertyTestCluster(t, int(numNodes), framework.WithEpochSize(epochSize), framework.WithSecretsCallback(func(adresses []types.Address, config *framework.TestClusterConfig) { - for i, a := range adresses { - config.PremineValidators = append(config.PremineValidators, fmt.Sprintf("%s:%d", a, premine[i])) + for i := range adresses { + config.StakeAmounts = append(config.StakeAmounts, stakes[i]) } })) defer cluster.Stop() + t.Logf("Test %v, run with %d nodes, epoch size: %d. Number of blocks to mine: %d", + filepath.Base(cluster.Config.LogsDir), numNodes, epochSize, numBlocks) + // wait for single epoch to process withdrawal require.NoError(t, cluster.WaitForBlock(numBlocks, blockTime*time.Duration(numBlocks))) }) diff --git a/e2e/framework/config.go b/e2e/framework/config.go index 85ee0eb060..aed0eab16c 100644 --- a/e2e/framework/config.go +++ b/e2e/framework/config.go @@ -50,17 +50,19 @@ type TestServerConfig struct { EpochSize uint64 // The epoch size in blocks for the IBFT layer BlockGasLimit uint64 // Block gas limit BlockGasTarget uint64 // Gas target for new blocks + BaseFee uint64 // Initial base fee ShowsLog bool // Flag specifying if logs are shown Name string // Name of the server SaveLogs bool // Flag specifying if logs are saved LogsDir string // Directory where logs are saved IsPos bool // Specifies the mechanism used for IBFT (PoA / PoS) - Signer *crypto.EIP155Signer // Signer used for transactions + Signer crypto.TxSigner // Signer used for transactions MinValidatorCount uint64 // Min validator count MaxValidatorCount uint64 // Max validator count BlockTime uint64 // Minimum block generation time (in s) IBFTBaseTimeout uint64 // Base Timeout in seconds for IBFT PredeployParams *PredeployParams + BurnContracts map[uint64]types.Address } func (t *TestServerConfig) SetPredeployParams(params *PredeployParams) { @@ -77,7 +79,7 @@ func (t *TestServerConfig) DataDir() string { } } -func (t *TestServerConfig) SetSigner(signer *crypto.EIP155Signer) { +func (t *TestServerConfig) SetSigner(signer crypto.TxSigner) { t.Signer = signer } @@ -118,6 +120,15 @@ func (t *TestServerConfig) SetBlockGasTarget(target uint64) { t.BlockGasTarget = target } +// SetBurnContract sets the given burn contract for the test server +func (t *TestServerConfig) SetBurnContract(block uint64, address types.Address) { + if t.BurnContracts == nil { + t.BurnContracts = map[uint64]types.Address{} + } + + t.BurnContracts[block] = address +} + // SetConsensus callback sets consensus func (t *TestServerConfig) SetConsensus(c ConsensusType) { t.Consensus = c diff --git a/e2e/framework/testserver.go b/e2e/framework/testserver.go index 8fd54c7c5c..442cc41bf9 100644 --- a/e2e/framework/testserver.go +++ b/e2e/framework/testserver.go @@ -21,11 +21,19 @@ import ( "testing" "time" - "github.com/0xPolygon/polygon-edge/chain" - "github.com/0xPolygon/polygon-edge/command/genesis/predeploy" + "github.com/hashicorp/go-hclog" + "github.com/libp2p/go-libp2p/core/peer" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/jsonrpc" + "github.com/umbracle/ethgo/wallet" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + empty "google.golang.org/protobuf/types/known/emptypb" + "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/command" "github.com/0xPolygon/polygon-edge/command/genesis" + "github.com/0xPolygon/polygon-edge/command/genesis/predeploy" ibftSwitch "github.com/0xPolygon/polygon-edge/command/ibft/switch" initCmd "github.com/0xPolygon/polygon-edge/command/secrets/init" "github.com/0xPolygon/polygon-edge/command/server" @@ -41,14 +49,6 @@ import ( txpoolProto "github.com/0xPolygon/polygon-edge/txpool/proto" "github.com/0xPolygon/polygon-edge/types" "github.com/0xPolygon/polygon-edge/validators" - "github.com/hashicorp/go-hclog" - "github.com/libp2p/go-libp2p/core/peer" - "github.com/umbracle/ethgo" - "github.com/umbracle/ethgo/jsonrpc" - "github.com/umbracle/ethgo/wallet" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - empty "google.golang.org/protobuf/types/known/emptypb" ) type TestServerConfigCallback func(*TestServerConfig) @@ -83,7 +83,7 @@ func NewTestServer(t *testing.T, rootDir string, callback TestServerConfigCallba LibP2PPort: ports[1].Port(), JSONRPCPort: ports[2].Port(), RootDir: rootDir, - Signer: crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100), + Signer: crypto.NewSigner(chain.AllForksEnabled.At(0), 100), ValidatorType: validators.ECDSAValidatorType, } @@ -277,6 +277,13 @@ func (t *TestServer) GenerateGenesis() error { args = append(args, "--premine", acct.Addr.String()+":0x"+acct.Balance.Text(16)) } + // provide block time flag + // (e2e framework expects BlockTime parameter to be provided in seconds) + if t.Config.BlockTime != 0 { + args = append(args, "--block-time", + (time.Duration(t.Config.BlockTime) * time.Second).String()) + } + // add consensus flags switch t.Config.Consensus { case ConsensusIBFT: @@ -339,6 +346,21 @@ func (t *TestServer) GenerateGenesis() error { blockGasLimit := strconv.FormatUint(t.Config.BlockGasLimit, 10) args = append(args, "--block-gas-limit", blockGasLimit) + // add base fee + if t.Config.BaseFee != 0 { + args = append(args, "--base-fee", *types.EncodeUint64(t.Config.BaseFee)) + } + + // add burn contracts + if len(t.Config.BurnContracts) != 0 { + for block, addr := range t.Config.BurnContracts { + args = append(args, "--burn-contract", fmt.Sprintf("%d:%s", block, addr)) + } + } else { + // london hardfork is enabled by default so there must be a default burn contract + args = append(args, "--burn-contract", "0:0x0000000000000000000000000000000000000000") + } + cmd := exec.Command(resolveBinary(), args...) //nolint:gosec cmd.Dir = t.Config.RootDir @@ -429,10 +451,6 @@ func (t *TestServer) Start(ctx context.Context) error { args = append(args, "--block-gas-target", *types.EncodeUint64(t.Config.BlockGasTarget)) } - if t.Config.BlockTime != 0 { - args = append(args, "--block-time", strconv.FormatUint(t.Config.BlockTime, 10)) - } - if t.Config.IBFTBaseTimeout != 0 { args = append(args, "--ibft-base-timeout", strconv.FormatUint(t.Config.IBFTBaseTimeout, 10)) } @@ -608,12 +626,6 @@ func (t *Txn) GasLimit(gas uint64) *Txn { return t } -func (t *Txn) GasPrice(price uint64) *Txn { - t.raw.GasPrice = price - - return t -} - func (t *Txn) Nonce(nonce uint64) *Txn { t.raw.Nonce = nonce @@ -622,8 +634,18 @@ func (t *Txn) Nonce(nonce uint64) *Txn { func (t *Txn) sendImpl() error { // populate default values - t.raw.Gas = 1048576 - t.raw.GasPrice = 1048576 + if t.raw.Gas == 0 { + t.raw.Gas = 1048576 + } + + if t.raw.GasPrice == 0 { + gasPrice, err := t.client.GasPrice() + if err != nil { + return fmt.Errorf("failed to get gas price: %w", err) + } + + t.raw.GasPrice = gasPrice + } if t.raw.Nonce == 0 { nextNonce, err := t.client.GetNonce(t.key.Address(), ethgo.Latest) diff --git a/e2e/ibft_test.go b/e2e/ibft_test.go index 95a3dc94cc..b15d57dca9 100644 --- a/e2e/ibft_test.go +++ b/e2e/ibft_test.go @@ -6,7 +6,6 @@ import ( "testing" "time" - "github.com/0xPolygon/polygon-edge/command/server/config" ibftSigner "github.com/0xPolygon/polygon-edge/consensus/ibft/signer" "github.com/0xPolygon/polygon-edge/e2e/framework" "github.com/0xPolygon/polygon-edge/helper/tests" @@ -19,6 +18,8 @@ import ( // TestIbft_Transfer sends a transfer transaction (EOA -> EOA) // and verifies it was mined func TestIbft_Transfer(t *testing.T) { + const defaultBlockTime uint64 = 2 + testCases := []struct { name string blockTime uint64 @@ -27,7 +28,7 @@ func TestIbft_Transfer(t *testing.T) { }{ { name: "default block time", - blockTime: config.DefaultBlockTime, + blockTime: defaultBlockTime, ibftBaseTimeout: 0, // use default value validatorType: validators.ECDSAValidatorType, }, @@ -39,7 +40,7 @@ func TestIbft_Transfer(t *testing.T) { }, { name: "with BLS", - blockTime: config.DefaultBlockTime, + blockTime: defaultBlockTime, ibftBaseTimeout: 0, // use default value validatorType: validators.BLSValidatorType, }, diff --git a/e2e/jsonrpc_test.go b/e2e/jsonrpc_test.go index 64150ade25..f74eddd52a 100644 --- a/e2e/jsonrpc_test.go +++ b/e2e/jsonrpc_test.go @@ -3,6 +3,7 @@ package e2e import ( "context" "encoding/hex" + "math/big" "testing" @@ -18,19 +19,18 @@ var ( ) func TestJsonRPC(t *testing.T) { - //nolint:godox - // TODO: Reuse the same tests for websockets and IPC. (to be fixed in EVM-521) fund, err := wallet.GenerateKey() require.NoError(t, err) - bytecode, _ := hex.DecodeString(sampleByteCode) + bytecode, err := hex.DecodeString(sampleByteCode) + require.NoError(t, err) ibftManager := framework.NewIBFTServersManager( t, 1, IBFTDirPrefix, func(i int, config *framework.TestServerConfig) { - config.Premine(types.Address(fund.Address()), framework.EthToWei(10)) + config.Premine(types.Address(fund.Address()), ethgo.Ether(10)) config.SetBlockTime(1) }, ) @@ -39,10 +39,12 @@ func TestJsonRPC(t *testing.T) { defer ibftManager.StopServers() srv := ibftManager.GetServer(0) + client := srv.JSONRPC().Eth() t.Run("eth_getBalance", func(t *testing.T) { - key1, _ := wallet.GenerateKey() + key1, err := wallet.GenerateKey() + require.NoError(t, err) // Test. return zero if the account does not exists balance1, err := client.GetBalance(key1.Address(), ethgo.Latest) @@ -50,7 +52,7 @@ func TestJsonRPC(t *testing.T) { require.Equal(t, balance1, big.NewInt(0)) // Test. return the balance of an account - newBalance := big.NewInt(22000) + newBalance := ethgo.Ether(1) txn, err := srv.Txn(fund).Transfer(key1.Address(), newBalance).Send() require.NoError(t, err) txn.NoFail(t) @@ -59,17 +61,41 @@ func TestJsonRPC(t *testing.T) { require.NoError(t, err) require.Equal(t, balance1, newBalance) - //nolint:godox // Test. return 0 if the balance of an existing account is empty - // TODO (to be fixed in EVM-521) + gasPrice, err := client.GasPrice() + require.NoError(t, err) + + toAddr := key1.Address() + msg := ðgo.CallMsg{ + From: fund.Address(), + To: &toAddr, + Value: newBalance, + GasPrice: gasPrice, + } + + estimatedGas, err := client.EstimateGas(msg) + require.NoError(t, err) + txPrice := gasPrice * estimatedGas + // subtract gasPrice * estimatedGas from the balance and transfer the rest to the other account + // in order to leave no funds on the account + amountToSend := new(big.Int).Sub(newBalance, big.NewInt(int64(txPrice))) + txn, err = srv.Txn(key1).Transfer(fund.Address(), amountToSend). + GasLimit(estimatedGas). + Send() + require.NoError(t, err) + txn.NoFail(t) + + balance1, err = client.GetBalance(key1.Address(), ethgo.Latest) + require.NoError(t, err) + require.Equal(t, big.NewInt(0), balance1) }) t.Run("eth_getTransactionCount", func(t *testing.T) { - key1, _ := wallet.GenerateKey() + key1, err := wallet.GenerateKey() + require.NoError(t, err) - //nolint:godox - // TODO. return zero if the account does not exists in the state (Does not work) (to be fixed in EVM-521) - _, err := client.GetNonce(key1.Address(), ethgo.Latest) + nonce, err := client.GetNonce(key1.Address(), ethgo.Latest) + require.Equal(t, uint64(0), nonce) require.NoError(t, err) txn, err := srv.Txn(fund).Transfer(key1.Address(), big.NewInt(10000000000000000)).Send() @@ -91,7 +117,6 @@ func TestJsonRPC(t *testing.T) { require.NoError(t, err) require.Equal(t, nonce1, uint64(0)) - // Test. TODO. you can query the nonce at any block hash in time (to be fixed in EVM-521) //nolint:godox block, err := client.GetBlockByNumber(ethgo.BlockNumber(txn.Receipt().BlockNumber)-1, false) require.NoError(t, err) @@ -100,14 +125,31 @@ func TestJsonRPC(t *testing.T) { }) t.Run("eth_getStorage", func(t *testing.T) { - t.Skip("TODO") + key1, err := wallet.GenerateKey() + require.NoError(t, err) + + txn := srv.Txn(fund) + txn, err = txn.Transfer(key1.Address(), one).Send() + require.NoError(t, err) + txn.NoFail(t) + + txn = srv.Txn(fund) + txn, err = txn.Deploy(bytecode).Send() + require.NoError(t, err) + txn.NoFail(t) + + resp, err := client.GetStorageAt(txn.Receipt().ContractAddress, ethgo.Hash{}, ethgo.Latest) + require.NoError(t, err) + require.Equal(t, "0x0000000000000000000000000000000000000000000000000000000000000000", resp.String()) }) t.Run("eth_getCode", func(t *testing.T) { // we use a predefined private key so that the deployed contract address is deterministic. // Note that in order to work, this private key should only be used for this test. - priv, _ := hex.DecodeString("2c15bd0dc992a47ca660983ae4b611f4ffb6178e14e04e2b34d153f3a74ce741") - key1, _ := wallet.NewWalletFromPrivKey(priv) + priv, err := hex.DecodeString("2c15bd0dc992a47ca660983ae4b611f4ffb6178e14e04e2b34d153f3a74ce741") + require.NoError(t, err) + key1, err := wallet.NewWalletFromPrivKey(priv) + require.NoError(t, err) // fund the account so that it can deploy a contract txn, err := srv.Txn(fund).Transfer(key1.Address(), big.NewInt(10000000000000000)).Send() @@ -135,7 +177,6 @@ func TestJsonRPC(t *testing.T) { cases := []ethgo.BlockNumberOrHash{ ethgo.Latest, ethgo.BlockNumber(receipt.BlockNumber), - // receipt.BlockHash, TODO: It does not work (to be fixed in EVM-521) //nolint:godox } for _, c := range cases { code, err = client.GetCode(codeAddr, c) @@ -154,15 +195,42 @@ func TestJsonRPC(t *testing.T) { require.NotEqual(t, code, "0x") }) - t.Run("eth_getBlockByX", func(t *testing.T) { - t.Skip("TODO") + t.Run("eth_getBlockByHash", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + txn := srv.Txn(fund) + txn, err = txn.Transfer(key1.Address(), one).Send() + require.NoError(t, err) + txn.NoFail(t) + txReceipt := txn.Receipt() + + block, err := client.GetBlockByHash(txReceipt.BlockHash, false) + require.NoError(t, err) + require.Equal(t, txReceipt.BlockNumber, block.Number) + require.Equal(t, txReceipt.BlockHash, block.Hash) + }) + + t.Run("eth_getBlockByNumber", func(t *testing.T) { + key1, err := wallet.GenerateKey() + require.NoError(t, err) + txn := srv.Txn(fund) + txn, err = txn.Transfer(key1.Address(), one).Send() + require.NoError(t, err) + txn.NoFail(t) + txReceipt := txn.Receipt() + + block, err := client.GetBlockByNumber(ethgo.BlockNumber(txReceipt.BlockNumber), false) + require.NoError(t, err) + require.Equal(t, txReceipt.BlockNumber, block.Number) + require.Equal(t, txReceipt.BlockHash, block.Hash) }) t.Run("eth_getTransactionReceipt", func(t *testing.T) { - key1, _ := wallet.GenerateKey() + key1, err := wallet.GenerateKey() + require.NoError(t, err) txn := srv.Txn(fund) - txn, err := txn.Transfer(key1.Address(), one).Send() + txn, err = txn.Transfer(key1.Address(), one).Send() require.NoError(t, err) txn.NoFail(t) @@ -193,11 +261,12 @@ func TestJsonRPC(t *testing.T) { }) t.Run("eth_getTransactionByHash", func(t *testing.T) { - key1, _ := wallet.GenerateKey() + key1, err := wallet.GenerateKey() + require.NoError(t, err) // Test. We should be able to query the transaction by its hash txn := srv.Txn(fund) - txn, err := txn.Transfer(key1.Address(), one).Send() + txn, err = txn.Transfer(key1.Address(), one).Send() require.NoError(t, err) txn.NoFail(t) diff --git a/e2e/pos_poa_switch_test.go b/e2e/pos_poa_switch_test.go index be7d78d2dc..e80d0568a3 100644 --- a/e2e/pos_poa_switch_test.go +++ b/e2e/pos_poa_switch_test.go @@ -113,8 +113,8 @@ func TestPoAPoSSwitch(t *testing.T) { } // Stake balance - // 3 genesis validators will stake but 1 gensis validator won't - numStakedValidators := 3 + // 4 genesis validators will stake but 1 gensis validator won't + numStakedValidators := 4 wg = sync.WaitGroup{} for idx := 0; idx < numStakedValidators; idx++ { @@ -143,7 +143,7 @@ func TestPoAPoSSwitch(t *testing.T) { t.Fatalf("Unable to wait for all nodes to seal blocks, %v", waitErrors) } - expectedPoSValidators := genesisValidatorAddrs[:3] + expectedPoSValidators := genesisValidatorAddrs[:4] // Test in PoS wg = sync.WaitGroup{} @@ -159,7 +159,7 @@ func TestPoAPoSSwitch(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), framework.DefaultTimeout) defer cancel() - // every validator should have only 3 validators in validator set + // every validator should have only 4 validators in validator set validateSnapshot(ctx, srv, posStartAt, expectedPoSValidators) }(srv) } diff --git a/e2e/pos_test.go b/e2e/pos_test.go index c8935a3fea..4d8779a184 100644 --- a/e2e/pos_test.go +++ b/e2e/pos_test.go @@ -9,6 +9,11 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/jsonrpc" + "github.com/0xPolygon/polygon-edge/chain" ibftOp "github.com/0xPolygon/polygon-edge/consensus/ibft/proto" "github.com/0xPolygon/polygon-edge/contracts/staking" @@ -19,9 +24,6 @@ import ( txpoolOp "github.com/0xPolygon/polygon-edge/txpool/proto" "github.com/0xPolygon/polygon-edge/types" "github.com/golang/protobuf/ptypes/any" - "github.com/stretchr/testify/assert" - "github.com/umbracle/ethgo" - "github.com/umbracle/ethgo/jsonrpc" ) // foundInValidatorSet is a helper function for searching through the passed in set for a specific @@ -358,28 +360,36 @@ func TestPoS_UnstakeExploit(t *testing.T) { // Required default values numTransactions := 5 - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) + signer := crypto.NewSigner(chain.AllForksEnabled.At(0), 100) currentNonce := 0 // TxPool client clt := srv.TxnPoolOperator() - generateTx := func() *types.Transaction { - signedTx, signErr := signer.SignTx(&types.Transaction{ - Nonce: uint64(currentNonce), - From: types.ZeroAddress, - To: &stakingContractAddr, - GasPrice: bigGasPrice, - Gas: framework.DefaultGasLimit, - Value: big.NewInt(0), - V: big.NewInt(1), // it is necessary to encode in rlp, - Input: framework.MethodSig("unstake"), - }, senderKey) - - if signErr != nil { - t.Fatalf("Unable to sign transaction, %v", signErr) + generateTx := func(i int) *types.Transaction { + unsignedTx := &types.Transaction{ + Nonce: uint64(currentNonce), + From: types.ZeroAddress, + To: &stakingContractAddr, + Gas: framework.DefaultGasLimit, + Value: big.NewInt(0), + V: big.NewInt(1), // it is necessary to encode in rlp, + Input: framework.MethodSig("unstake"), + } + + // Just make very second transaction with dynamic gas fee + if i%2 == 0 { + unsignedTx.Type = types.DynamicFeeTx + unsignedTx.GasFeeCap = bigGasPrice + unsignedTx.GasTipCap = bigGasPrice + } else { + unsignedTx.Type = types.LegacyTx + unsignedTx.GasPrice = bigGasPrice } + signedTx, err := signer.SignTx(unsignedTx, senderKey) + require.NoError(t, err, "Unable to sign transaction") + currentNonce++ return signedTx @@ -390,7 +400,7 @@ func TestPoS_UnstakeExploit(t *testing.T) { for i := 0; i < numTransactions; i++ { var msg *txpoolOp.AddTxnReq - unstakeTxn := generateTx() + unstakeTxn := generateTx(i) msg = &txpoolOp.AddTxnReq{ Raw: &any.Any{ @@ -500,28 +510,36 @@ func TestPoS_StakeUnstakeExploit(t *testing.T) { // Required default values numTransactions := 6 - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) + signer := crypto.NewSigner(chain.AllForksEnabled.At(0), 100) currentNonce := 0 // TxPool client txpoolClient := srv.TxnPoolOperator() - generateTx := func(value *big.Int, methodName string) *types.Transaction { - signedTx, signErr := signer.SignTx(&types.Transaction{ - Nonce: uint64(currentNonce), - From: types.ZeroAddress, - To: &stakingContractAddr, - GasPrice: bigGasPrice, - Gas: framework.DefaultGasLimit, - Value: value, - V: big.NewInt(1), // it is necessary to encode in rlp - Input: framework.MethodSig(methodName), - }, senderKey) - - if signErr != nil { - t.Fatalf("Unable to sign transaction, %v", signErr) + generateTx := func(i int, value *big.Int, methodName string) *types.Transaction { + unsignedTx := &types.Transaction{ + Nonce: uint64(currentNonce), + From: types.ZeroAddress, + To: &stakingContractAddr, + Gas: framework.DefaultGasLimit, + Value: value, + V: big.NewInt(1), // it is necessary to encode in rlp + Input: framework.MethodSig(methodName), + } + + // Just make very second transaction with dynamic gas fee + if i%2 == 0 { + unsignedTx.Type = types.DynamicFeeTx + unsignedTx.GasFeeCap = bigGasPrice + unsignedTx.GasTipCap = bigGasPrice + } else { + unsignedTx.Type = types.LegacyTx + unsignedTx.GasPrice = bigGasPrice } + signedTx, err := signer.SignTx(unsignedTx, senderKey) + require.NoError(t, err, "Unable to sign transaction") + currentNonce++ return signedTx @@ -535,7 +553,7 @@ func TestPoS_StakeUnstakeExploit(t *testing.T) { var msg *txpoolOp.AddTxnReq if i%2 == 0 { - unstakeTxn := generateTx(zeroEth, "unstake") + unstakeTxn := generateTx(i, zeroEth, "unstake") msg = &txpoolOp.AddTxnReq{ Raw: &any.Any{ Value: unstakeTxn.MarshalRLP(), @@ -543,7 +561,7 @@ func TestPoS_StakeUnstakeExploit(t *testing.T) { From: types.ZeroAddress.String(), } } else { - stakeTxn := generateTx(oneEth, "stake") + stakeTxn := generateTx(i, oneEth, "stake") msg = &txpoolOp.AddTxnReq{ Raw: &any.Any{ Value: stakeTxn.MarshalRLP(), @@ -631,28 +649,35 @@ func TestPoS_StakeUnstakeWithinSameBlock(t *testing.T) { } // Required default values - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) + signer := crypto.NewSigner(chain.AllForksEnabled.At(0), 100) currentNonce := 0 // TxPool client txpoolClient := srv.TxnPoolOperator() - generateTx := func(value *big.Int, methodName string) *types.Transaction { - signedTx, signErr := signer.SignTx(&types.Transaction{ - Nonce: uint64(currentNonce), - From: types.ZeroAddress, - To: &stakingContractAddr, - GasPrice: bigGasPrice, - Gas: framework.DefaultGasLimit, - Value: value, - V: big.NewInt(1), // it is necessary to encode in rlp - Input: framework.MethodSig(methodName), - }, senderKey) - - if signErr != nil { - t.Fatalf("Unable to sign transaction, %v", signErr) + generateTx := func(dynamicTx bool, value *big.Int, methodName string) *types.Transaction { + unsignedTx := &types.Transaction{ + Nonce: uint64(currentNonce), + From: types.ZeroAddress, + To: &stakingContractAddr, + Gas: framework.DefaultGasLimit, + Value: value, + V: big.NewInt(1), // it is necessary to encode in rlp + Input: framework.MethodSig(methodName), } + if dynamicTx { + unsignedTx.Type = types.DynamicFeeTx + unsignedTx.GasFeeCap = bigGasPrice + unsignedTx.GasTipCap = bigGasPrice + } else { + unsignedTx.Type = types.LegacyTx + unsignedTx.GasPrice = bigGasPrice + } + + signedTx, err := signer.SignTx(unsignedTx, senderKey) + require.NoError(t, err, "Unable to signatransaction") + currentNonce++ return signedTx @@ -663,8 +688,8 @@ func TestPoS_StakeUnstakeWithinSameBlock(t *testing.T) { // addTxn is a helper method for generating and adding a transaction // through the operator command - addTxn := func(value *big.Int, methodName string) { - txn := generateTx(value, methodName) + addTxn := func(dynamicTx bool, value *big.Int, methodName string) { + txn := generateTx(dynamicTx, value, methodName) txnMsg := &txpoolOp.AddTxnReq{ Raw: &any.Any{ Value: txn.MarshalRLP(), @@ -681,10 +706,10 @@ func TestPoS_StakeUnstakeWithinSameBlock(t *testing.T) { } // Stake transaction - addTxn(oneEth, "stake") + addTxn(false, oneEth, "stake") // Unstake transaction - addTxn(zeroEth, "unstake") + addTxn(true, zeroEth, "unstake") // Wait for the transactions to go through totalGasUsed := srv.GetGasTotal(txHashes) diff --git a/e2e/transaction_test.go b/e2e/transaction_test.go index bb5c811771..b088391467 100644 --- a/e2e/transaction_test.go +++ b/e2e/transaction_test.go @@ -12,7 +12,10 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/jsonrpc" "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/contracts/abis" @@ -21,8 +24,6 @@ import ( "github.com/0xPolygon/polygon-edge/helper/tests" "github.com/0xPolygon/polygon-edge/types" "github.com/0xPolygon/polygon-edge/validators" - "github.com/stretchr/testify/assert" - "github.com/umbracle/ethgo/jsonrpc" ) func TestPreminedBalance(t *testing.T) { @@ -271,6 +272,7 @@ func getCount( // IBFT_Loop and Dev_Loop stress tests func generateStressTestTx( t *testing.T, + txNum int, currentNonce uint64, contractAddr types.Address, senderKey *ecdsa.PrivateKey, @@ -278,7 +280,7 @@ func generateStressTestTx( t.Helper() bigGasPrice := big.NewInt(framework.DefaultGasPrice) - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) + signer := crypto.NewSigner(chain.AllForksEnabled.At(0), 100) setNameMethod, ok := abis.StressTestABI.Methods["setName"] if !ok { @@ -294,21 +296,28 @@ func generateStressTestTx( t.Fatalf("Unable to encode inputs, %v", encodeErr) } - signedTx, signErr := signer.SignTx(&types.Transaction{ - Nonce: currentNonce, - From: types.ZeroAddress, - To: &contractAddr, - GasPrice: bigGasPrice, - Gas: framework.DefaultGasLimit, - Value: big.NewInt(0), - V: big.NewInt(1), // it is necessary to encode in rlp, - Input: append(setNameMethod.ID(), encodedInput...), - }, senderKey) - - if signErr != nil { - t.Fatalf("Unable to sign transaction, %v", signErr) + unsignedTx := &types.Transaction{ + Nonce: currentNonce, + From: types.ZeroAddress, + To: &contractAddr, + Gas: framework.DefaultGasLimit, + Value: big.NewInt(0), + V: big.NewInt(1), // it is necessary to encode in rlp, + Input: append(setNameMethod.ID(), encodedInput...), } + if txNum%2 == 0 { + unsignedTx.Type = types.DynamicFeeTx + unsignedTx.GasFeeCap = bigGasPrice + unsignedTx.GasTipCap = bigGasPrice + } else { + unsignedTx.Type = types.LegacyTx + unsignedTx.GasPrice = bigGasPrice + } + + signedTx, err := signer.SignTx(unsignedTx, senderKey) + require.NoError(t, err, "Unable to sign transaction") + return signedTx } @@ -331,6 +340,7 @@ func addStressTxnsWithHashes( for i := 0; i < numTransactions; i++ { setNameTxn := generateStressTestTx( t, + i, uint64(currentNonce), contractAddr, senderKey, diff --git a/e2e/txpool_test.go b/e2e/txpool_test.go index e78332e603..5ab6d80f9c 100644 --- a/e2e/txpool_test.go +++ b/e2e/txpool_test.go @@ -9,6 +9,9 @@ import ( "time" "github.com/0xPolygon/polygon-edge/chain" + + "github.com/stretchr/testify/require" + "github.com/0xPolygon/polygon-edge/txpool" "github.com/umbracle/ethgo" @@ -23,7 +26,7 @@ import ( var ( oneEth = framework.EthToWei(1) - signer = crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) + signer = crypto.NewSigner(chain.AllForksEnabled.At(0), 100) ) type generateTxReqParams struct { @@ -32,25 +35,34 @@ type generateTxReqParams struct { referenceKey *ecdsa.PrivateKey toAddress types.Address gasPrice *big.Int + gasFeeCap *big.Int + gasTipCap *big.Int value *big.Int t *testing.T } func generateTx(params generateTxReqParams) *types.Transaction { - signedTx, signErr := signer.SignTx(&types.Transaction{ - Nonce: params.nonce, - From: params.referenceAddr, - To: ¶ms.toAddress, - GasPrice: params.gasPrice, - Gas: 1000000, - Value: params.value, - V: big.NewInt(27), // it is necessary to encode in rlp - }, params.referenceKey) - - if signErr != nil { - params.t.Fatalf("Unable to sign transaction, %v", signErr) + unsignedTx := &types.Transaction{ + Nonce: params.nonce, + From: params.referenceAddr, + To: ¶ms.toAddress, + Gas: 1000000, + Value: params.value, + V: big.NewInt(27), // it is necessary to encode in rlp } + if params.gasPrice != nil { + unsignedTx.Type = types.LegacyTx + unsignedTx.GasPrice = params.gasPrice + } else { + unsignedTx.Type = types.DynamicFeeTx + unsignedTx.GasFeeCap = params.gasFeeCap + unsignedTx.GasTipCap = params.gasTipCap + } + + signedTx, err := signer.SignTx(unsignedTx, params.referenceKey) + require.NoError(params.t, err, "Unable to sign transaction") + return signedTx } @@ -67,33 +79,64 @@ func generateReq(params generateTxReqParams) *txpoolOp.AddTxnReq { func TestTxPool_ErrorCodes(t *testing.T) { gasPrice := big.NewInt(10000) + gasFeeCap := big.NewInt(1000000000) + gasTipCap := big.NewInt(100000000) devInterval := 5 testTable := []struct { name string defaultBalance *big.Int txValue *big.Int + gasPrice *big.Int + gasFeeCap *big.Int + gasTipCap *big.Int expectedError error }{ { // Test scenario: + // Add legacy tx with nonce 0 + // -> Check if tx has been parsed // Add tx with nonce 0 + // -> tx shouldn't be added, since the nonce is too low + name: "ErrNonceTooLow - legacy", + defaultBalance: framework.EthToWei(10), + txValue: oneEth, + gasPrice: gasPrice, + expectedError: txpool.ErrNonceTooLow, + }, + { + // Test scenario: + // Add dynamic fee tx with nonce 0 // -> Check if tx has been parsed // Add tx with nonce 0 // -> tx shouldn't be added, since the nonce is too low - "ErrNonceTooLow", - framework.EthToWei(10), - oneEth, - txpool.ErrNonceTooLow, + name: "ErrNonceTooLow - dynamic fees", + defaultBalance: framework.EthToWei(10), + txValue: oneEth, + gasFeeCap: gasFeeCap, + gasTipCap: gasTipCap, + expectedError: txpool.ErrNonceTooLow, }, { // Test scenario: - // Add tx with insufficient funds + // Add legacy tx with insufficient funds // -> Tx should be discarded because of low funds - "ErrInsufficientFunds", - framework.EthToWei(1), - framework.EthToWei(5), - txpool.ErrInsufficientFunds, + name: "ErrInsufficientFunds - legacy", + defaultBalance: framework.EthToWei(1), + txValue: framework.EthToWei(5), + gasPrice: gasPrice, + expectedError: txpool.ErrInsufficientFunds, + }, + { + // Test scenario: + // Add dynamic fee tx with insufficient funds + // -> Tx should be discarded because of low funds + name: "ErrInsufficientFunds - dynamic fee", + defaultBalance: framework.EthToWei(1), + txValue: framework.EthToWei(5), + gasFeeCap: gasFeeCap, + gasTipCap: gasTipCap, + expectedError: txpool.ErrInsufficientFunds, }, } @@ -119,7 +162,9 @@ func TestTxPool_ErrorCodes(t *testing.T) { referenceAddr: referenceAddr, referenceKey: referenceKey, toAddress: toAddress, - gasPrice: gasPrice, + gasPrice: testCase.gasPrice, + gasFeeCap: testCase.gasFeeCap, + gasTipCap: testCase.gasTipCap, value: testCase.txValue, t: t, }) @@ -188,7 +233,7 @@ func TestTxPool_TransactionCoalescing(t *testing.T) { client := srv.JSONRPC() // Required default values - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) + signer := crypto.NewEIP155Signer(100, true) // TxPool client clt := srv.TxnPoolOperator() @@ -340,7 +385,7 @@ func TestTxPool_RecoverableError(t *testing.T) { // 1. Send a first valid transaction with gasLimit = block gas limit - 1 // // 2. Send a second transaction with gasLimit = block gas limit / 2. Since there is not enough gas remaining, - // the transaction will be pushed back to the pending queue so that is can be executed in the next block. + // the transaction will be pushed back to the pending queue so that can be executed in the next block. // // 3. Send a third - valid - transaction, both the previous one and this one should be executed. // @@ -367,13 +412,15 @@ func TestTxPool_RecoverableError(t *testing.T) { From: senderAddress, }, { - Nonce: 2, - GasPrice: big.NewInt(framework.DefaultGasPrice), - Gas: 22000, - To: &receiverAddress, - Value: oneEth, - V: big.NewInt(27), - From: senderAddress, + Type: types.DynamicFeeTx, + Nonce: 2, + GasFeeCap: big.NewInt(10000000000), + GasTipCap: big.NewInt(1000000000), + Gas: 22000, + To: &receiverAddress, + Value: oneEth, + V: big.NewInt(27), + From: senderAddress, }, } diff --git a/forkmanager/fork.go b/forkmanager/fork.go new file mode 100644 index 0000000000..51bae5019a --- /dev/null +++ b/forkmanager/fork.go @@ -0,0 +1,87 @@ +package forkmanager + +import ( + "fmt" + + "github.com/0xPolygon/polygon-edge/chain" +) + +const InitialFork = "initialfork" + +// HandlerDesc gives description for the handler +// eq: "extra", "proposer_calculator", etc +type HandlerDesc string + +// Fork structure defines one fork +type Fork struct { + // name of the fork + Name string + // after the fork is activated, `FromBlockNumber` shows from which block is enabled + FromBlockNumber uint64 + // fork consensus parameters + Params *chain.ForkParams + // this value is false if fork is registered but not activated + IsActive bool + // map of all handlers registered for this fork + Handlers map[HandlerDesc]interface{} +} + +// forkHandler defines one custom handler +type forkHandler struct { + // Handler should be active from block `FromBlockNumber`` + FromBlockNumber uint64 + // instance of some structure, function etc + Handler interface{} +} + +// forkParamsBlock encapsulates block and actual fork params +type forkParamsBlock struct { + // Params should be active from block `FromBlockNumber`` + FromBlockNumber uint64 + // pointer to fork params + Params *chain.ForkParams +} + +func ForkManagerInit( + initialParams *chain.ForkParams, + factory func(*chain.Forks) error, + forks *chain.Forks) error { + if factory == nil { + return nil + } + + fm := GetInstance() + fm.Clear() + + // register initial fork + fm.RegisterFork(InitialFork, initialParams) + + // Register forks + for name, f := range *forks { + // check if fork is not supported by current edge version + if _, found := (*chain.AllForksEnabled)[name]; !found { + return fmt.Errorf("fork is not available: %s", name) + } + + fm.RegisterFork(name, f.Params) + } + + // Register handlers and additional forks here + if err := factory(forks); err != nil { + return err + } + + // Activate initial fork + if err := fm.ActivateFork(InitialFork, uint64(0)); err != nil { + return err + } + + // Activate forks + for name, f := range *forks { + if err := fm.ActivateFork(name, f.Block); err != nil { + return err + } + } + + return nil +} diff --git a/forkmanager/fork_manager.go b/forkmanager/fork_manager.go new file mode 100644 index 0000000000..0b7d7e2899 --- /dev/null +++ b/forkmanager/fork_manager.go @@ -0,0 +1,301 @@ +package forkmanager + +import ( + "fmt" + "reflect" + "sort" + "sync" + + "github.com/0xPolygon/polygon-edge/chain" +) + +var ( + forkManagerInstance *forkManager + forkManagerInstanceLock sync.Mutex +) + +type forkManager struct { + lock sync.Mutex + + forkMap map[string]*Fork + handlersMap map[HandlerDesc][]forkHandler + params []*forkParamsBlock +} + +// GeInstance returns fork manager singleton instance. Thread safe +func GetInstance() *forkManager { + forkManagerInstanceLock.Lock() + defer forkManagerInstanceLock.Unlock() + + if forkManagerInstance == nil { + forkManagerInstance = &forkManager{} + forkManagerInstance.Clear() + } + + return forkManagerInstance +} + +func (fm *forkManager) Clear() { + fm.lock.Lock() + defer fm.lock.Unlock() + + fm.forkMap = map[string]*Fork{} + fm.handlersMap = map[HandlerDesc][]forkHandler{} +} + +// RegisterFork registers fork by its name +func (fm *forkManager) RegisterFork(name string, forkParams *chain.ForkParams) { + fm.lock.Lock() + defer fm.lock.Unlock() + + fm.forkMap[name] = &Fork{ + Name: name, + FromBlockNumber: 0, + IsActive: false, + Params: forkParams, + Handlers: map[HandlerDesc]interface{}{}, + } +} + +// RegisterHandler registers handler by its name for specific fork +func (fm *forkManager) RegisterHandler(forkName string, handlerName HandlerDesc, handler interface{}) error { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[forkName] + if !exists { + return fmt.Errorf("fork does not exist: %s", forkName) + } + + fork.Handlers[handlerName] = handler + + return nil +} + +// ActivateFork activates fork from some block number +// All handlers and parameters belonging to this fork are also activated +func (fm *forkManager) ActivateFork(forkName string, blockNumber uint64) error { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[forkName] + if !exists { + return fmt.Errorf("fork does not exist: %s", forkName) + } + + if fork.IsActive { + return nil // already activated + } + + fork.IsActive = true + fork.FromBlockNumber = blockNumber + + for name, handler := range fork.Handlers { + fm.addHandler(name, blockNumber, handler) + } + + fm.addParams(blockNumber, fork.Params) + + return nil +} + +// DeactivateFork de-activates fork +// All handlers and parameters belong to this fork are also de-activated +func (fm *forkManager) DeactivateFork(forkName string) error { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[forkName] + if !exists { + return fmt.Errorf("fork does not exist: %s", forkName) + } + + if !fork.IsActive { + return nil // already deactivated + } + + fork.IsActive = false + + for forkHandlerName := range fork.Handlers { + fm.removeHandler(forkHandlerName, fork.FromBlockNumber) + } + + fm.removeParams(fork.FromBlockNumber) + + return nil +} + +// GetHandler retrieves handler for handler name and for a block number +func (fm *forkManager) GetHandler(name HandlerDesc, blockNumber uint64) interface{} { + fm.lock.Lock() + defer fm.lock.Unlock() + + handlers, exists := fm.handlersMap[name] + if !exists { + return nil + } + + // binary search to find the latest handler defined for a specific block + pos := sort.Search(len(handlers), func(i int) bool { + return handlers[i].FromBlockNumber > blockNumber + }) - 1 + if pos < 0 { + return nil + } + + return handlers[pos].Handler +} + +// GetParams retrieves chain.ForkParams for a block number +func (fm *forkManager) GetParams(blockNumber uint64) *chain.ForkParams { + fm.lock.Lock() + defer fm.lock.Unlock() + + // binary search to find the desired *chain.ForkParams + pos := sort.Search(len(fm.params), func(i int) bool { + return fm.params[i].FromBlockNumber > blockNumber + }) - 1 + if pos < 0 { + return nil + } + + return fm.params[pos].Params +} + +// IsForkRegistered checks if fork is registered +func (fm *forkManager) IsForkRegistered(name string) bool { + fm.lock.Lock() + defer fm.lock.Unlock() + + _, exists := fm.forkMap[name] + + return exists +} + +// IsForkEnabled checks if fork is registered and enabled for specific block +func (fm *forkManager) IsForkEnabled(name string, blockNumber uint64) bool { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[name] + if !exists { + return false + } + + return fork.IsActive && fork.FromBlockNumber <= blockNumber +} + +// GetForkBlock returns fork block if fork is registered and activated +func (fm *forkManager) GetForkBlock(name string) (uint64, error) { + fm.lock.Lock() + defer fm.lock.Unlock() + + fork, exists := fm.forkMap[name] + if !exists { + return 0, fmt.Errorf("fork does not exist: %s", name) + } + + if !fork.IsActive { + return 0, fmt.Errorf("fork is not active: %s", name) + } + + return fork.FromBlockNumber, nil +} + +func (fm *forkManager) addHandler(handlerName HandlerDesc, blockNumber uint64, handler interface{}) { + if handlers, exists := fm.handlersMap[handlerName]; !exists { + fm.handlersMap[handlerName] = []forkHandler{ + { + FromBlockNumber: blockNumber, + Handler: handler, + }, + } + } else { + // keep everything in sorted order + index := sort.Search(len(handlers), func(i int) bool { + return handlers[i].FromBlockNumber >= blockNumber + }) + handlers = append(handlers, forkHandler{}) + copy(handlers[index+1:], handlers[index:]) + handlers[index] = forkHandler{ + FromBlockNumber: blockNumber, + Handler: handler, + } + fm.handlersMap[handlerName] = handlers + } +} + +func (fm *forkManager) removeHandler(handlerName HandlerDesc, blockNumber uint64) { + handlers, exists := fm.handlersMap[handlerName] + if !exists { + return + } + + index := sort.Search(len(handlers), func(i int) bool { + return handlers[i].FromBlockNumber >= blockNumber + }) + + if index < len(handlers) && handlers[index].FromBlockNumber == blockNumber { + copy(handlers[index:], handlers[index+1:]) + handlers[len(handlers)-1] = forkHandler{} + fm.handlersMap[handlerName] = handlers[:len(handlers)-1] + } +} + +func (fm *forkManager) addParams(blockNumber uint64, params *chain.ForkParams) { + if params == nil { + return + } + + item := &forkParamsBlock{FromBlockNumber: blockNumber, Params: params} + + if len(fm.params) == 0 { + fm.params = append(fm.params, item) + } else { + // keep everything in sorted order + index := sort.Search(len(fm.params), func(i int) bool { + return fm.params[i].FromBlockNumber >= blockNumber + }) + + fm.params = append(fm.params, (*forkParamsBlock)(nil)) + copy(fm.params[index+1:], fm.params[index:]) + fm.params[index] = item + + if index > 0 { + // copy all nil parameters from previous + copyParams(item.Params, fm.params[index-1].Params) + } + + // update parameters for next + for i := index; i < len(fm.params)-1; i++ { + copyParams(fm.params[i+1].Params, fm.params[i].Params) + } + } +} + +func (fm *forkManager) removeParams(blockNumber uint64) { + index := sort.Search(len(fm.params), func(i int) bool { + return fm.params[i].FromBlockNumber >= blockNumber + }) + + if index < len(fm.params) && fm.params[index].FromBlockNumber == blockNumber { + copy(fm.params[index:], fm.params[index+1:]) + fm.params[len(fm.params)-1] = nil + fm.params = fm.params[:len(fm.params)-1] + } +} + +func copyParams(dest, src *chain.ForkParams) { + srcValue := reflect.ValueOf(src).Elem() + dstValue := reflect.ValueOf(dest).Elem() + + for i := 0; i < srcValue.NumField(); i++ { + dstField := dstValue.Field(i) + srcField := srcValue.Field(i) + + // copy if dst is nil, but src is not + if dstField.Kind() == reflect.Ptr && dstField.IsNil() && !srcField.IsNil() { + dstField.Set(srcField) + } + } +} diff --git a/forkmanager/fork_manager_test.go b/forkmanager/fork_manager_test.go new file mode 100644 index 0000000000..69a0bad964 --- /dev/null +++ b/forkmanager/fork_manager_test.go @@ -0,0 +1,228 @@ +package forkmanager + +import ( + "testing" + "time" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/helper/common" + "github.com/stretchr/testify/assert" +) + +const ( + HandlerA = HandlerDesc("HA") + HandlerB = HandlerDesc("HB") + HandlerC = HandlerDesc("HC") + HandlerD = HandlerDesc("HD") + + ForkA = "A" + ForkB = "B" + ForkC = "C" + ForkD = "D" + ForkE = "E" +) + +func TestForkManager(t *testing.T) { + t.Parallel() + + es1, es2, es3 := uint64(100), uint64(300), uint64(200) + mss1 := uint64(10002) + bt1, bt2 := common.Duration{Duration: time.Second * 5}, common.Duration{Duration: time.Second * 12} + + forkManager := GetInstance() + + forkManager.RegisterFork(ForkA, &chain.ForkParams{EpochSize: &es1, BlockTime: &bt1}) + forkManager.RegisterFork(ForkB, &chain.ForkParams{EpochSize: &es2, MaxValidatorSetSize: &mss1}) + forkManager.RegisterFork(ForkC, nil) + forkManager.RegisterFork(ForkD, &chain.ForkParams{EpochSize: &es3, BlockTime: &bt2}) + + assert.NoError(t, forkManager.RegisterHandler(ForkA, HandlerA, func() string { return "AAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkC, HandlerA, func() string { return "ACH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkA, HandlerB, func() string { return "BAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkB, HandlerB, func() string { return "BBH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkD, HandlerB, func() string { return "BDH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkC, HandlerC, func() string { return "CCH" })) + + assert.NoError(t, forkManager.ActivateFork(ForkD, 300)) + assert.NoError(t, forkManager.ActivateFork(ForkA, 0)) + assert.NoError(t, forkManager.ActivateFork(ForkC, 200)) + assert.NoError(t, forkManager.ActivateFork(ForkB, 100)) + + handlersACnt := len(forkManager.handlersMap[HandlerA]) + handlersBCnt := len(forkManager.handlersMap[HandlerB]) + + assert.Equal(t, 2, handlersACnt) + assert.Equal(t, 3, handlersBCnt) + + t.Run("activate not registered fork", func(t *testing.T) { + t.Parallel() + + assert.Error(t, forkManager.ActivateFork(ForkE, 100)) + }) + + t.Run("activate already activated fork", func(t *testing.T) { + t.Parallel() + + assert.NoError(t, forkManager.ActivateFork(ForkA, 100)) + + // count not changed + assert.Equal(t, handlersACnt, len(forkManager.handlersMap[HandlerA])) + assert.Equal(t, handlersBCnt, len(forkManager.handlersMap[HandlerB])) + }) + + t.Run("is fork enabled", func(t *testing.T) { + t.Parallel() + + assert.True(t, forkManager.IsForkEnabled(ForkA, 0)) + assert.True(t, forkManager.IsForkEnabled(ForkA, 100)) + assert.True(t, forkManager.IsForkEnabled(ForkA, 200)) + + assert.False(t, forkManager.IsForkEnabled(ForkB, 0)) + assert.True(t, forkManager.IsForkEnabled(ForkB, 100)) + assert.True(t, forkManager.IsForkEnabled(ForkB, 200)) + + assert.False(t, forkManager.IsForkEnabled(ForkC, 0)) + assert.False(t, forkManager.IsForkEnabled(ForkC, 100)) + assert.True(t, forkManager.IsForkEnabled(ForkC, 200)) + assert.True(t, forkManager.IsForkEnabled(ForkC, 300)) + + assert.False(t, forkManager.IsForkEnabled(ForkD, 0)) + assert.False(t, forkManager.IsForkEnabled(ForkD, 100)) + assert.False(t, forkManager.IsForkEnabled(ForkD, 200)) + assert.True(t, forkManager.IsForkEnabled(ForkD, 300)) + assert.True(t, forkManager.IsForkEnabled(ForkD, 400)) + + assert.False(t, forkManager.IsForkEnabled(ForkE, 0)) + }) + + t.Run("is fork supported", func(t *testing.T) { + t.Parallel() + + assert.True(t, forkManager.IsForkRegistered(ForkA)) + assert.True(t, forkManager.IsForkRegistered(ForkB)) + assert.True(t, forkManager.IsForkRegistered(ForkC)) + assert.True(t, forkManager.IsForkRegistered(ForkD)) + + assert.False(t, forkManager.IsForkRegistered(ForkE)) + }) + + t.Run("get fork block", func(t *testing.T) { + t.Parallel() + + b, err := forkManager.GetForkBlock(ForkA) + assert.NoError(t, err) + assert.Equal(t, uint64(0), b) + + b, err = forkManager.GetForkBlock(ForkB) + assert.NoError(t, err) + assert.Equal(t, uint64(100), b) + + b, err = forkManager.GetForkBlock(ForkC) + assert.NoError(t, err) + assert.Equal(t, uint64(200), b) + + b, err = forkManager.GetForkBlock(ForkD) + assert.NoError(t, err) + assert.Equal(t, uint64(300), b) + + _, err = forkManager.GetForkBlock(ForkE) + assert.Error(t, err) + }) + + t.Run("register handler not existing fork", func(t *testing.T) { + t.Parallel() + + assert.Error(t, forkManager.RegisterHandler(ForkE, HandlerD, func() {})) + }) + + t.Run("get handler", func(t *testing.T) { + t.Parallel() + + execute := func(name HandlerDesc, block uint64) string { + //nolint:forcetypeassert + return forkManager.GetHandler(name, block).(func() string)() + } + + for i := uint64(0); i < uint64(4); i++ { + assert.Equal(t, "AAH", execute(HandlerA, i)) + assert.Equal(t, "BAH", execute(HandlerB, i)) + assert.Nil(t, forkManager.GetHandler(HandlerC, i)) + + assert.Equal(t, "AAH", execute(HandlerA, 100+i)) + assert.Equal(t, "BBH", execute(HandlerB, 100+i)) + assert.Nil(t, forkManager.GetHandler(HandlerC, 100+i)) + + assert.Equal(t, "ACH", execute(HandlerA, 200+i)) + assert.Equal(t, "BBH", execute(HandlerB, 200+i)) + assert.Equal(t, "CCH", execute(HandlerC, 200+i)) + + assert.Equal(t, "ACH", execute(HandlerA, 300+i)) + assert.Equal(t, "BDH", execute(HandlerB, 300+i)) + assert.Equal(t, "CCH", execute(HandlerC, 300+i)) + } + + assert.Nil(t, forkManager.GetHandler(HandlerD, 0)) + }) + + t.Run("get params", func(t *testing.T) { + t.Parallel() + + for i := uint64(0); i < uint64(4); i++ { + assert.Equal(t, es1, *forkManager.GetParams(i).EpochSize) + assert.Equal(t, es2, *forkManager.GetParams(i + 100).EpochSize) + assert.Equal(t, es2, *forkManager.GetParams(i + 200).EpochSize) + assert.Equal(t, es3, *forkManager.GetParams(i + 300).EpochSize) + + assert.Nil(t, forkManager.GetParams(i).MaxValidatorSetSize) + assert.Equal(t, mss1, *forkManager.GetParams(i + 100).MaxValidatorSetSize) + assert.Equal(t, mss1, *forkManager.GetParams(i + 200).MaxValidatorSetSize) + assert.Equal(t, mss1, *forkManager.GetParams(i + 300).MaxValidatorSetSize) + + assert.Equal(t, bt1, *forkManager.GetParams(i).BlockTime) + assert.Equal(t, bt1, *forkManager.GetParams(i + 100).BlockTime) + assert.Equal(t, bt1, *forkManager.GetParams(i + 200).BlockTime) + assert.Equal(t, bt2, *forkManager.GetParams(i + 300).BlockTime) + } + }) +} + +func TestForkManager_Deactivate(t *testing.T) { + t.Parallel() + + forkManager := &forkManager{ + forkMap: map[string]*Fork{}, + handlersMap: map[HandlerDesc][]forkHandler{}, + } + mvs1, mvs2 := uint64(1), uint64(2) + + forkManager.RegisterFork(ForkA, &chain.ForkParams{MaxValidatorSetSize: &mvs1}) + forkManager.RegisterFork(ForkB, &chain.ForkParams{MaxValidatorSetSize: &mvs2}) + forkManager.RegisterFork(ForkC, &chain.ForkParams{}) + + assert.NoError(t, forkManager.RegisterHandler(ForkA, HandlerA, func() string { return "AAH" })) + assert.NoError(t, forkManager.RegisterHandler(ForkB, HandlerA, func() string { return "ABH" })) + + assert.NoError(t, forkManager.ActivateFork(ForkB, 10)) + assert.NoError(t, forkManager.ActivateFork(ForkC, 20)) + assert.NoError(t, forkManager.ActivateFork(ForkA, 0)) + + assert.Equal(t, 2, len(forkManager.handlersMap[HandlerA])) + assert.Equal(t, 3, len(forkManager.params)) + assert.Equal(t, mvs2, *forkManager.GetParams(30).MaxValidatorSetSize) + + assert.NoError(t, forkManager.DeactivateFork(ForkA)) + + assert.Equal(t, 1, len(forkManager.handlersMap[HandlerA])) + assert.Equal(t, 2, len(forkManager.params)) + assert.Nil(t, forkManager.GetParams(0)) + + assert.NoError(t, forkManager.DeactivateFork(ForkC)) + + assert.Equal(t, 1, len(forkManager.handlersMap[HandlerA])) + assert.Equal(t, 1, len(forkManager.params)) + + assert.NoError(t, forkManager.DeactivateFork(ForkB)) + + assert.Equal(t, 0, len(forkManager.handlersMap[HandlerA])) + assert.Equal(t, 0, len(forkManager.params)) +} diff --git a/gasprice/gasprice.go b/gasprice/gasprice.go new file mode 100644 index 0000000000..a800a26002 --- /dev/null +++ b/gasprice/gasprice.go @@ -0,0 +1,254 @@ +package gasprice + +import ( + "fmt" + "math/big" + "sort" + "sync" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/crypto" + "github.com/0xPolygon/polygon-edge/types" + "github.com/umbracle/ethgo" +) + +const couldNotFoundBlockFormat = "could not find block. Number: %d, Hash: %s" + +// DefaultGasHelperConfig is the default config for gas helper (as per ethereum) +var DefaultGasHelperConfig = &Config{ + NumOfBlocksToCheck: 20, + PricePercentile: 60, + SampleNumber: 3, + MaxPrice: ethgo.Gwei(500), + LastPrice: ethgo.Gwei(1), + IgnorePrice: big.NewInt(2), // 2 wei +} + +// Config is a struct that holds configuration of GasHelper +type Config struct { + // NumOfBlocksToCheck is the number of blocks to sample + NumOfBlocksToCheck uint64 + // PricePercentile is the sample percentile of transactions in a block + PricePercentile uint64 + // SampleNumber is number of transactions sampled in a block + SampleNumber uint64 + // MaxPrice is the tip max price + MaxPrice *big.Int + // LastPrice is the last price returned for maxPriorityFeePerGas + // when starting node it will be some default value + LastPrice *big.Int + // IgnorePrice is the lowest price to take into consideration + // when collecting transactions + IgnorePrice *big.Int +} + +// Blockchain is the interface representing blockchain +type Blockchain interface { + GetBlockByHash(hash types.Hash, full bool) (*types.Block, bool) + Header() *types.Header + Config() *chain.Params +} + +// GasStore interface is providing functions regarding gas and fees +type GasStore interface { + // MaxPriorityFeePerGas calculates the priority fee needed for transaction to be included in a block + MaxPriorityFeePerGas() (*big.Int, error) +} + +var _ GasStore = (*GasHelper)(nil) + +// GasHelper struct implements functions from the GasStore interface +type GasHelper struct { + // numOfBlocksToCheck is the number of blocks to sample + numOfBlocksToCheck uint64 + // pricePercentile is the sample percentile of transactions in a block + pricePercentile uint64 + // sampleNumber is number of transactions sampled in a block + sampleNumber uint64 + // maxPrice is the tip max price + maxPrice *big.Int + // lastPrice is the last price returned for maxPriorityFeePerGas + lastPrice *big.Int + // ignorePrice is the lowest price to take into consideration + // when collecting transactions + ignorePrice *big.Int + // backend is an abstraction of blockchain + backend Blockchain + // lastHeaderHash is the last header for which maxPriorityFeePerGas was returned + lastHeaderHash types.Hash + + lock sync.Mutex +} + +// NewGasHelper is the constructor function for GasHelper struct +func NewGasHelper(config *Config, backend Blockchain) *GasHelper { + pricePercentile := config.PricePercentile + if pricePercentile > 100 { + pricePercentile = 100 + } + + return &GasHelper{ + numOfBlocksToCheck: config.NumOfBlocksToCheck, + pricePercentile: pricePercentile, + sampleNumber: config.SampleNumber, + ignorePrice: config.IgnorePrice, + lastPrice: config.LastPrice, + maxPrice: config.MaxPrice, + backend: backend, + } +} + +// MaxPriorityFeePerGas calculates the priority fee needed for transaction to be included in a block +// The function does following: +// - takes chain header +// - iterates for numOfBlocksToCheck from chain header to previous blocks +// - collects at most the sample number of sorted transactions in block +// - if not enough transactions were collected and their tips, go through some more blocks to get +// more accurate calculation +// - when enough transactions and their tips are collected, take the one that is in pricePercentile +// - if given price is larger then maxPrice then return the maxPrice +func (g *GasHelper) MaxPriorityFeePerGas() (*big.Int, error) { + currentHeader := g.backend.Header() + + currentBlock, found := g.backend.GetBlockByHash(currentHeader.Hash, true) + if !found { + return nil, fmt.Errorf(couldNotFoundBlockFormat, currentHeader.Number, currentHeader.Hash) + } + + g.lock.Lock() + lastPrice := g.lastPrice + lastHeader := g.lastHeaderHash + g.lock.Unlock() + + if currentHeader.Hash == lastHeader { + // small optimization, if we calculated already the price for given block + return new(big.Int).Set(lastPrice), nil + } + + var allPrices []*big.Int + + collectPrices := func(block *types.Block) error { + baseFee := block.Header.BaseFee + txSorter := newTxByEffectiveTipSorter(block.Transactions, baseFee) + sort.Sort(txSorter) + + blockMiner := types.BytesToAddress(block.Header.Miner) + signer := crypto.NewSigner(g.backend.Config().Forks.At(block.Number()), + uint64(g.backend.Config().ChainID)) + blockTxPrices := make([]*big.Int, 0) + + for _, tx := range txSorter.txs { + tip := tx.EffectiveTip(baseFee) + + if tip.Cmp(g.ignorePrice) == -1 { + // ignore transactions with tip lower than ignore price + continue + } + + sender, err := signer.Sender(tx) + if err != nil { + return fmt.Errorf("could not get sender of transaction: %s. Error: %w", tx.Hash, err) + } + + if sender != blockMiner { + blockTxPrices = append(blockTxPrices, tip) + + // if sample number of txs from block is reached, + // don't process any more txs + if len(blockTxPrices) >= int(g.sampleNumber) { + break + } + } + } + + if len(blockTxPrices) == 0 { + // either block is empty or all transactions in block are sent by the miner. + // in this case add the latests calculated price for sampling + blockTxPrices = append(blockTxPrices, lastPrice) + } + + // add the block prices to the slice of all prices + allPrices = append(allPrices, blockTxPrices...) + + return nil + } + + // iterate from current block to previous blocks determined by numOfBlocksToCheck + // if chain doesn't have that many blocks, we need to stop the loop (currentBlock.Number() > 0) + for i := uint64(0); i < g.numOfBlocksToCheck && currentBlock.Number() > 0; i++ { + if err := collectPrices(currentBlock); err != nil { + return nil, err + } + + currentBlock, found = g.backend.GetBlockByHash(currentBlock.ParentHash(), true) + if !found { + return nil, fmt.Errorf(couldNotFoundBlockFormat, currentHeader.Number, currentHeader.Hash) + } + } + + // at least amount of transactions to get + minNumOfTx := int(g.numOfBlocksToCheck) * 2 + // collect some more blocks and transactions if not enough transactions were collected + for len(allPrices) < minNumOfTx && currentBlock.Number() > 0 { + if err := collectPrices(currentBlock); err != nil { + return nil, err + } + } + + price := lastPrice + + if len(allPrices) > 0 { + // sort prices from lowest to highest + sort.Slice(allPrices, func(i, j int) bool { + return allPrices[i].Cmp(allPrices[j]) < 0 + }) + // take the biggest price that is in the configured percentage + // by default it's 60, so it will take the price on that percentage + // of all prices in the array + price = allPrices[(len(allPrices)-1)*int(g.pricePercentile)/100] + } + + if price.Cmp(g.maxPrice) > 0 { + // if price is larger than the configured max price + // return max price + price = new(big.Int).Set(g.maxPrice) + } + + // cache the calculated price and header hash + g.lock.Lock() + g.lastPrice = price + g.lastHeaderHash = currentHeader.Hash + g.lock.Unlock() + + return price, nil +} + +// txSortedByEffectiveTip sorts transactions by effective tip from smallest to largest +type txSortedByEffectiveTip struct { + txs []*types.Transaction + baseFee uint64 +} + +// newTxByEffectiveTipSorter is constructor function for txSortedByEffectiveTip +func newTxByEffectiveTipSorter(txs []*types.Transaction, baseFee uint64) *txSortedByEffectiveTip { + return &txSortedByEffectiveTip{ + txs: txs, + baseFee: baseFee, + } +} + +// Len is implementation of sort.Interface +func (t *txSortedByEffectiveTip) Len() int { return len(t.txs) } + +// Swap is implementation of sort.Interface +func (t *txSortedByEffectiveTip) Swap(i, j int) { + t.txs[i], t.txs[j] = t.txs[j], t.txs[i] +} + +// Less is implementation of sort.Interface +func (t *txSortedByEffectiveTip) Less(i, j int) bool { + tip1 := t.txs[i].EffectiveTip(t.baseFee) + tip2 := t.txs[j].EffectiveTip(t.baseFee) + + return tip1.Cmp(tip2) < 0 +} diff --git a/gasprice/gasprice_test.go b/gasprice/gasprice_test.go new file mode 100644 index 0000000000..f4ff7bbde3 --- /dev/null +++ b/gasprice/gasprice_test.go @@ -0,0 +1,266 @@ +package gasprice + +import ( + "fmt" + "math/big" + "math/rand" + "testing" + "time" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/crypto" + "github.com/0xPolygon/polygon-edge/helper/tests" + "github.com/0xPolygon/polygon-edge/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/umbracle/ethgo" +) + +func TestGasHelper_MaxPriorityFeePerGas(t *testing.T) { + t.Parallel() + + var cases = []struct { + Name string + Expected *big.Int + Error bool + GetBackend func() Blockchain + }{ + { + Name: "Chain just started", + Expected: DefaultGasHelperConfig.LastPrice, + GetBackend: func() Blockchain { + genesis := &types.Header{ + Number: 0, + Hash: types.StringToHash("genesis"), + } + backend := new(backendMock) + backend.On("Header").Return(genesis) + backend.On("GetBlockByHash", mock.Anything, true).Return(&types.Block{ + Header: genesis, + Transactions: []*types.Transaction{}, + }, true) + + return backend + }, + }, + { + Name: "Block does not exist", + Error: true, + GetBackend: func() Blockchain { + header := &types.Header{ + Number: 0, + Hash: types.StringToHash("some header"), + } + backend := new(backendMock) + backend.On("Header").Return(header) + backend.On("GetBlockByHash", mock.Anything, true).Return(&types.Block{}, false) + + return backend + }, + }, + { + Name: "Empty blocks", + Expected: DefaultGasHelperConfig.LastPrice, // should return last (default) price + GetBackend: func() Blockchain { + backend := createTestBlocks(t, 10) + + return backend + }, + }, + { + Name: "All transactions by miner", + Expected: DefaultGasHelperConfig.LastPrice, // should return last (default) price + GetBackend: func() Blockchain { + backend := createTestBlocks(t, 10) + rand.Seed(time.Now().UTC().UnixNano()) + + senderKey, sender := tests.GenerateKeyAndAddr(t) + + for _, b := range backend.blocks { + signer := crypto.NewSigner(backend.Config().Forks.At(b.Number()), + uint64(backend.Config().ChainID)) + + b.Transactions = make([]*types.Transaction, 3) + b.Header.Miner = sender.Bytes() + + for i := 0; i < 3; i++ { + tx := &types.Transaction{ + From: sender, + Value: ethgo.Ether(1), + To: &types.ZeroAddress, + Type: types.DynamicFeeTx, + GasTipCap: ethgo.Gwei(uint64(rand.Intn(200))), + GasFeeCap: ethgo.Gwei(uint64(rand.Intn(200) + 200)), + } + + tx, err := signer.SignTx(tx, senderKey) + require.NoError(t, err) + + b.Transactions[i] = tx + } + } + + return backend + }, + }, + { + Name: "All transactions have small effective tip", + Expected: DefaultGasHelperConfig.LastPrice, // should return last (default) price + GetBackend: func() Blockchain { + backend := createTestBlocks(t, 10) + createTestTxs(t, backend, 3, 1) + + return backend + }, + }, + { + Name: "Number of blocks in chain smaller than numOfBlocksToCheck", + Expected: DefaultGasHelperConfig.LastPrice.Mul( + DefaultGasHelperConfig.LastPrice, big.NewInt(2)), // at least two times of default last price + GetBackend: func() Blockchain { + backend := createTestBlocks(t, 10) + createTestTxs(t, backend, 3, 200) + + return backend + }, + }, + { + Name: "Number of blocks in chain higher than numOfBlocksToCheck", + Expected: DefaultGasHelperConfig.LastPrice.Mul( + DefaultGasHelperConfig.LastPrice, big.NewInt(2)), // at least two times of default last price + GetBackend: func() Blockchain { + backend := createTestBlocks(t, 30) + createTestTxs(t, backend, 3, 200) + + return backend + }, + }, + { + Name: "Not enough transactions in first 20 blocks, so read some more blocks", + Expected: DefaultGasHelperConfig.LastPrice.Mul( + DefaultGasHelperConfig.LastPrice, big.NewInt(2)), // at least two times of default last price + GetBackend: func() Blockchain { + backend := createTestBlocks(t, 50) + createTestTxs(t, backend, 1, 200) + + return backend + }, + }, + } + + for _, tc := range cases { + tc := tc + t.Run(tc.Name, func(t *testing.T) { + t.Parallel() + + backend := tc.GetBackend() + gasHelper := NewGasHelper(DefaultGasHelperConfig, backend) + price, err := gasHelper.MaxPriorityFeePerGas() + + if tc.Error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.True(t, price.Cmp(tc.Expected) >= 0) + } + }) + } +} + +func createTestBlocks(t *testing.T, numOfBlocks int) *backendMock { + t.Helper() + + backend := &backendMock{blocks: make(map[types.Hash]*types.Block)} + genesis := &types.Block{ + Header: &types.Header{ + Number: 0, + Hash: types.StringToHash("genesis"), + Miner: types.ZeroAddress.Bytes(), + BaseFee: chain.GenesisBaseFee, + }, + } + backend.blocks[genesis.Hash()] = genesis + + currentBlock := genesis + + for i := 1; i <= numOfBlocks; i++ { + block := &types.Block{ + Header: &types.Header{ + Number: uint64(i), + Hash: types.BytesToHash([]byte(fmt.Sprintf("Block %d", i))), + Miner: types.ZeroAddress.Bytes(), + ParentHash: currentBlock.Hash(), + }, + } + + backend.blocks[block.Hash()] = block + currentBlock = block + } + + backend.On("Header").Return(currentBlock.Header) + + return backend +} + +func createTestTxs(t *testing.T, backend *backendMock, numOfTxsPerBlock, txCap int) { + t.Helper() + + rand.Seed(time.Now().UTC().UnixNano()) + + for _, b := range backend.blocks { + signer := crypto.NewSigner(backend.Config().Forks.At(b.Number()), + uint64(backend.Config().ChainID)) + + b.Transactions = make([]*types.Transaction, numOfTxsPerBlock) + + for i := 0; i < numOfTxsPerBlock; i++ { + senderKey, sender := tests.GenerateKeyAndAddr(t) + + tx := &types.Transaction{ + From: sender, + Value: ethgo.Ether(1), + To: &types.ZeroAddress, + Type: types.DynamicFeeTx, + GasTipCap: ethgo.Gwei(uint64(rand.Intn(txCap))), + GasFeeCap: ethgo.Gwei(uint64(rand.Intn(txCap) + txCap)), + } + + tx, err := signer.SignTx(tx, senderKey) + require.NoError(t, err) + + b.Transactions[i] = tx + } + } +} + +var _ Blockchain = (*backendMock)(nil) + +type backendMock struct { + mock.Mock + blocks map[types.Hash]*types.Block +} + +func (b *backendMock) Header() *types.Header { + args := b.Called() + + return args.Get(0).(*types.Header) //nolint:forcetypeassert +} + +func (b *backendMock) GetBlockByHash(hash types.Hash, full bool) (*types.Block, bool) { + if len(b.blocks) == 0 { + args := b.Called(hash, full) + + return args.Get(0).(*types.Block), args.Get(1).(bool) //nolint:forcetypeassert + } + + block, exists := b.blocks[hash] + + return block, exists +} + +func (b *backendMock) Config() *chain.Params { + return &chain.Params{ + ChainID: 1, + Forks: chain.AllForksEnabled, + } +} diff --git a/go.mod b/go.mod index e0b6d1afe3..dae9a321e4 100644 --- a/go.mod +++ b/go.mod @@ -1,235 +1,232 @@ module github.com/0xPolygon/polygon-edge -go 1.18 +go 1.20 require ( github.com/btcsuite/btcd v0.22.1 - github.com/containerd/cgroups v1.0.4 // indirect + github.com/containerd/cgroups v1.1.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect - github.com/envoyproxy/protoc-gen-validate v0.9.1 - github.com/golang/protobuf v1.5.2 + github.com/envoyproxy/protoc-gen-validate v1.0.2 + github.com/golang/protobuf v1.5.3 github.com/google/uuid v1.3.0 github.com/gorilla/websocket v1.5.0 - github.com/hashicorp/go-hclog v1.3.1 + github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-immutable-radix v1.3.1 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/hashicorp/hcl v1.0.0 - github.com/hashicorp/vault/api v1.8.2 - github.com/libp2p/go-libp2p v0.22.0 - github.com/libp2p/go-libp2p-kbucket v0.5.0 - github.com/libp2p/go-libp2p-pubsub v0.8.1 - github.com/miekg/dns v1.1.50 // indirect - github.com/multiformats/go-base32 v0.0.4 // indirect - github.com/multiformats/go-multiaddr v0.7.0 - github.com/multiformats/go-multihash v0.2.1 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect - github.com/prometheus/client_golang v1.13.1 + github.com/hashicorp/vault/api v1.9.2 + github.com/libp2p/go-libp2p v0.27.6 + github.com/libp2p/go-libp2p-kbucket v0.6.0 + github.com/libp2p/go-libp2p-pubsub v0.9.3 + github.com/miekg/dns v1.1.53 // indirect + github.com/multiformats/go-base32 v0.1.0 // indirect + github.com/multiformats/go-multiaddr v0.9.0 + github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/prometheus/client_golang v1.16.0 github.com/ryanuber/columnize v2.1.2+incompatible - github.com/spf13/cobra v1.6.1 - github.com/stretchr/testify v1.8.1 + github.com/spf13/cobra v1.7.0 + github.com/stretchr/testify v1.8.4 github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 - github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 + github.com/umbracle/fastrlp v0.1.1-0.20230504065717-58a1b8a9929d github.com/umbracle/go-eth-bn256 v0.0.0-20230125114011-47cb310d9b0b - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e - google.golang.org/grpc v1.50.1 - google.golang.org/protobuf v1.28.1 + golang.org/x/crypto v0.10.0 + google.golang.org/grpc v1.53.0-dev + google.golang.org/protobuf v1.31.0 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce ) require ( - cloud.google.com/go/secretmanager v1.8.0 + cloud.google.com/go/secretmanager v1.10.0 github.com/armon/go-metrics v0.4.1 github.com/aws/aws-sdk-go v1.44.61 github.com/benbjohnson/clock v1.3.0 // indirect github.com/coinbase/kryptology v1.8.0 github.com/fatih/color v1.13.0 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/ipfs/go-cid v0.2.0 // indirect - github.com/klauspost/compress v1.15.5 // indirect + github.com/ipfs/go-cid v0.4.1 // indirect + github.com/klauspost/compress v1.16.4 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mitchellh/mapstructure v1.5.0 - github.com/umbracle/ethgo v0.1.4-0.20230126112511-6a4d02533af6 + github.com/umbracle/ethgo v0.1.4-0.20230622091706-8230f57578b2 github.com/valyala/fastjson v1.6.3 // indirect - go.uber.org/zap v1.22.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/tools v0.3.0 - google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e + go.uber.org/zap v1.24.0 // indirect + golang.org/x/sys v0.9.0 // indirect + golang.org/x/tools v0.10.0 gopkg.in/yaml.v3 v3.0.1 - lukechampine.com/blake3 v1.1.7 // indirect + lukechampine.com/blake3 v1.2.1 // indirect ) require ( - github.com/0xPolygon/go-ibft v0.4.0 + github.com/0xPolygon/go-ibft v0.4.1-0.20230612114712-fa4235351cbc github.com/docker/docker v20.10.18+incompatible github.com/docker/go-connections v0.4.0 - go.etcd.io/bbolt v1.3.6 + go.etcd.io/bbolt v1.3.7 ) require ( - github.com/dave/jennifer v1.6.0 + github.com/dave/jennifer v1.6.1 github.com/quasilyte/go-ruleguard v0.3.19 github.com/quasilyte/go-ruleguard/dsl v0.3.22 - golang.org/x/sync v0.1.0 - gopkg.in/DataDog/dd-trace-go.v1 v1.43.1 - pgregory.net/rapid v0.5.5 + github.com/sethvargo/go-retry v0.2.4 + golang.org/x/sync v0.3.0 + google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2 + gopkg.in/DataDog/dd-trace-go.v1 v1.51.0 + pgregory.net/rapid v1.0.0 ) require ( - cloud.google.com/go/compute v1.10.0 // indirect - cloud.google.com/go/iam v0.5.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/DataDog/appsec-internal-go v1.0.0 // indirect + github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.45.0 // indirect + github.com/DataDog/go-libddwaf v1.2.0 // indirect + github.com/DataDog/go-tuf v0.3.0--fix-localmeta-fork // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.2 // indirect + github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/libp2p/go-yamux/v4 v4.0.0 // indirect + github.com/onsi/ginkgo/v2 v2.9.2 // indirect + github.com/outcaste-io/ristretto v0.2.1 // indirect + github.com/quic-go/qpack v0.4.0 // indirect + github.com/quic-go/qtls-go1-19 v0.3.2 // indirect + github.com/quic-go/qtls-go1-20 v0.2.2 // indirect + github.com/quic-go/quic-go v0.33.0 // indirect + github.com/quic-go/webtransport-go v0.5.2 // indirect + github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/secure-systems-lab/go-securesystemslib v0.6.0 // indirect + go.uber.org/dig v1.16.1 // indirect + go.uber.org/fx v1.19.2 // indirect + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + nhooyr.io/websocket v1.8.7 // indirect +) + +require ( + cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/iam v0.10.0 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/DataDog/datadog-agent/pkg/obfuscate v0.0.0-20211129110424-6491aa3bf583 // indirect - github.com/DataDog/datadog-go v4.8.2+incompatible // indirect - github.com/DataDog/datadog-go/v5 v5.0.2 // indirect + github.com/DataDog/datadog-agent/pkg/obfuscate v0.45.0-rc.1 // indirect + github.com/DataDog/datadog-go/v5 v5.1.1 // indirect github.com/DataDog/gostackparse v0.5.0 // indirect github.com/DataDog/sketches-go v1.2.1 // indirect - github.com/Microsoft/go-winio v0.5.1 // indirect + github.com/Microsoft/go-winio v0.6.0 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect github.com/andybalholm/brotli v1.0.4 // indirect - github.com/armon/go-radix v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/bwesterb/go-ristretto v1.2.0 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/cheekybits/genny v1.0.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/consensys/gnark-crypto v0.5.3 // indirect - github.com/containerd/continuity v0.0.0-20191214063359-1097c8bae83b // indirect - github.com/coreos/go-systemd/v22 v22.3.2 // indirect + github.com/containerd/continuity v0.3.0 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect - github.com/dgraph-io/ristretto v0.1.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/go-units v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-toolsmith/astcopy v1.0.2 // indirect github.com/go-toolsmith/astequal v1.0.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.6.0 // indirect + github.com/google/pprof v0.0.0-20230509042627-b1315fad0c5a // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.7.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-plugin v1.4.5 // indirect github.com/hashicorp/go-retryablehttp v0.7.1 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.5.0 // indirect - github.com/hashicorp/vault/sdk v0.6.0 // indirect - github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect - github.com/huin/goupnp v1.0.3 // indirect - github.com/inconshreveable/mousetrap v1.0.1 // indirect - github.com/ipfs/go-ipfs-util v0.0.2 // indirect + github.com/huin/goupnp v1.1.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-log/v2 v2.5.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/klauspost/cpuid/v2 v2.1.0 // indirect - github.com/koron/go-ssdp v0.0.3 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/koron/go-ssdp v0.0.4 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect - github.com/libp2p/go-msgio v0.2.0 // indirect + github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect + github.com/libp2p/go-msgio v0.3.0 // indirect github.com/libp2p/go-nat v0.1.0 // indirect - github.com/libp2p/go-netroute v0.2.0 // indirect - github.com/libp2p/go-openssl v0.1.0 // indirect + github.com/libp2p/go-netroute v0.2.1 // indirect github.com/libp2p/go-reuseport v0.2.0 // indirect - github.com/libp2p/go-yamux/v3 v3.1.2 // indirect - github.com/lucas-clemente/quic-go v0.28.1 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect - github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect - github.com/marten-seemann/qtls-go1-19 v0.1.0 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/mattn/go-isatty v0.0.16 // indirect - github.com/mattn/go-pointer v0.0.1 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/sha256-simd v1.0.0 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-base36 v0.2.0 // indirect github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.1.1 // indirect - github.com/multiformats/go-multicodec v0.5.0 // indirect - github.com/multiformats/go-multistream v0.3.3 // indirect - github.com/multiformats/go-varint v0.0.6 // indirect - github.com/nxadm/tail v1.4.8 // indirect - github.com/oklog/run v1.1.0 // indirect - github.com/opencontainers/go-digest v1.0.0-rc1 // indirect - github.com/opencontainers/image-spec v1.0.1 // indirect - github.com/opencontainers/runc v0.1.1 // indirect - github.com/opencontainers/runtime-spec v1.0.2 // indirect + github.com/multiformats/go-multibase v0.2.0 // indirect + github.com/multiformats/go-multicodec v0.9.0 // indirect + github.com/multiformats/go-multistream v0.4.1 // indirect + github.com/multiformats/go-varint v0.0.7 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.0.2 // indirect + github.com/opencontainers/runc v1.1.5 // indirect + github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/ory/dockertest v3.3.5+incompatible // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/philhofer/fwd v1.1.1 // indirect - github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.37.0 // indirect - github.com/prometheus/procfs v0.8.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/quasilyte/gogrep v0.5.0 // indirect github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.0 // indirect - github.com/tinylib/msgp v1.1.2 // indirect + github.com/tinylib/msgp v1.1.6 // indirect + github.com/trailofbits/go-fuzz-utils v0.0.0-20210901195358-9657fcfd256c github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.37.0 // indirect - github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect - go.opencensus.io v0.23.0 // indirect - go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.8.0 // indirect + go.opencensus.io v0.24.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 // indirect golang.org/x/exp/typeparams v0.0.0-20221002003631-540bb7301a08 // indirect - golang.org/x/mod v0.7.0 // indirect - golang.org/x/net v0.2.0 // indirect - golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1 // indirect - golang.org/x/text v0.4.0 // indirect - golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect + golang.org/x/mod v0.11.0 // indirect + golang.org/x/net v0.11.0 // indirect + golang.org/x/oauth2 v0.8.0 // indirect + golang.org/x/text v0.10.0 // indirect + golang.org/x/time v0.3.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.99.0 // indirect + google.golang.org/api v0.109.0 // indirect google.golang.org/appengine v1.6.7 // indirect - gopkg.in/square/go-jose.v2 v2.6.0 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gotest.tools/v3 v3.0.2 // indirect - inet.af/netaddr v0.0.0-20220617031823-097006376321 // indirect + inet.af/netaddr v0.0.0-20220811202034-502d2d690317 // indirect ) diff --git a/go.sum b/go.sum index 393da55bd3..69ab694e0c 100644 --- a/go.sum +++ b/go.sum @@ -1,73 +1,50 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.104.0 h1:gSmWO7DY1vOm0MVU6DNXM11BWHHsTUmsC5cv1fuW5X8= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.10.0 h1:aoLIYaA1fX3ywihqpBk2APQKOo20nXsp1GEZQbx5Jk4= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.5.0 h1:fz9X5zyTWBmamZsqvqZqD7khbifcZF/q+Z1J8pfhIUg= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/secretmanager v1.8.0 h1:4wYWL2t10q+xUtFFS0QuWlqwQguMrwC6FDpjtMM6cUI= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= +cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= +cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/iam v0.10.0 h1:fpP/gByFs6US1ma53v7VxhvbJpO2Aapng6wabJ99MuI= +cloud.google.com/go/iam v0.10.0/go.mod h1:nXAECrMt2qHpF6RZUZseteD6QyanL68reN4OXPw0UWM= +cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= +cloud.google.com/go/secretmanager v1.10.0 h1:pu03bha7ukxF8otyPKTFdDz+rr9sE3YauS5PliDXK60= +cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/0xPolygon/go-ibft v0.4.0 h1:WwevpA/J5PI2ztQuIis/0uRlVZrJgps9NhPewoYZDus= -github.com/0xPolygon/go-ibft v0.4.0/go.mod h1:mJGwdcGvLdg9obtnzBqx1aAzuhzvGeWav5AiUWN7F3Q= +github.com/0xPolygon/go-ibft v0.4.1-0.20230612114712-fa4235351cbc h1:LSrOswaGy5kmLZTr8B1t5WnSpm8plYGAmdrUd6lGhRw= +github.com/0xPolygon/go-ibft v0.4.1-0.20230612114712-fa4235351cbc/go.mod h1:mJGwdcGvLdg9obtnzBqx1aAzuhzvGeWav5AiUWN7F3Q= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/datadog-agent/pkg/obfuscate v0.0.0-20211129110424-6491aa3bf583 h1:3nVO1nQyh64IUY6BPZUpMYMZ738Pu+LsMt3E0eqqIYw= -github.com/DataDog/datadog-agent/pkg/obfuscate v0.0.0-20211129110424-6491aa3bf583/go.mod h1:EP9f4GqaDJyP1F5jTNMtzdIpw3JpNs3rMSJOnYywCiw= +github.com/DataDog/appsec-internal-go v1.0.0 h1:2u5IkF4DBj3KVeQn5Vg2vjPUtt513zxEYglcqnd500U= +github.com/DataDog/appsec-internal-go v1.0.0/go.mod h1:+Y+4klVWKPOnZx6XESG7QHydOaUGEXyH2j/vSg9JiNM= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.45.0-rc.1 h1:XyYvstMFpSyZtfJHWJm1Sf1meNyCdfhKJrjB6+rUNOk= +github.com/DataDog/datadog-agent/pkg/obfuscate v0.45.0-rc.1/go.mod h1:e933RWa4kAWuHi5jpzEuOiULlv21HcCFEVIYegmaB5c= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.45.0 h1:pnZo84OurElmbC/ibYrw1pZfaEFEEP2m8MgSSZK/D2U= +github.com/DataDog/datadog-agent/pkg/remoteconfig/state v0.45.0/go.mod h1:VVMDDibJxYEkwcLdZBT2g8EHKpbMT4JdOhRbQ9GdjbM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go v4.8.2+incompatible h1:qbcKSx29aBLD+5QLvlQZlGmRMF/FfGqFLFev/1TDzRo= -github.com/DataDog/datadog-go v4.8.2+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/DataDog/datadog-go/v5 v5.0.2 h1:UFtEe7662/Qojxkw1d6SboAeA0CPI3naKhVASwFn+04= -github.com/DataDog/datadog-go/v5 v5.0.2/go.mod h1:ZI9JFB4ewXbw1sBnF4sxsR2k1H3xjV+PUAOUsHvKpcU= +github.com/DataDog/datadog-go/v5 v5.1.1 h1:JLZ6s2K1pG2h9GkvEvMdEGqMDyVLEAccdX5TltWcLMU= +github.com/DataDog/datadog-go/v5 v5.1.1/go.mod h1:KhiYb2Badlv9/rofz+OznKoEF5XKTonWyhx5K83AP8E= +github.com/DataDog/go-libddwaf v1.2.0 h1:fKHP5U29E597eV2hU501fcW40bL8zcQ081jEGuRw2kM= +github.com/DataDog/go-libddwaf v1.2.0/go.mod h1:DI5y8obPajk+Tvy2o+nZc2g/5Ria/Rfq5/624k7pHpE= +github.com/DataDog/go-tuf v0.3.0--fix-localmeta-fork h1:yBq5PrAtrM4yVeSzQ+bn050+Ysp++RKF1QmtkL4VqvU= +github.com/DataDog/go-tuf v0.3.0--fix-localmeta-fork/go.mod h1:yA5JwkZsHTLuqq3zaRgUQf35DfDkpOZqgtBqHKpwrBs= github.com/DataDog/gostackparse v0.5.0 h1:jb72P6GFHPHz2W0onsN51cS3FkaMDcjb0QzgxxA4gDk= github.com/DataDog/gostackparse v0.5.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= github.com/DataDog/sketches-go v1.2.1 h1:qTBzWLnZ3kM2kw39ymh6rMcnN+5VULwFs++lEYUUsro= github.com/DataDog/sketches-go v1.2.1/go.mod h1:1xYmPLY1So10AwxV6MJV0J53XVH+WL9Ad1KetxVivVI= github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -75,15 +52,12 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.44.61 h1:NcpLSS3Z0MiVQIYugx4I40vSIEEAXT0baO684ExNRco= github.com/aws/aws-sdk-go v1.44.61/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -118,49 +92,51 @@ github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTx github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4= github.com/coinbase/kryptology v1.8.0 h1:Aoq4gdTsJhSU3lNWsD5BWmFSz2pE0GlmrljaOxepdYY= github.com/coinbase/kryptology v1.8.0/go.mod h1:RYXOAPdzOGUe3qlSFkMGn58i3xUA8hmxYHksuq+8ciI= github.com/consensys/bavard v0.1.8-0.20210915155054-088da2f7f54a/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.5.3 h1:4xLFGZR3NWEH2zy+YzvzHicpToQR8FXFbfLNvpGB+rE= github.com/consensys/gnark-crypto v0.5.3/go.mod h1:hOdPlWQV1gDLp7faZVeg8Y0iEPFaOUnCc4XeCCk96p0= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= -github.com/containerd/continuity v0.0.0-20191214063359-1097c8bae83b h1:pik3LX++5O3UiNWv45wfP/WT81l7ukBJzd3uUiifbSU= -github.com/containerd/continuity v0.0.0-20191214063359-1097c8bae83b/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= +github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= +github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/dave/jennifer v1.6.0 h1:MQ/6emI2xM7wt0tJzJzyUik2Q3Tcn2eE0vtYgh4GPVI= -github.com/dave/jennifer v1.6.0/go.mod h1:AxTG893FiZKqxy3FP1kL80VMshSMuz2G+EgvszgGRnk= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/dave/jennifer v1.6.1 h1:T4T/67t6RAA5AIV6+NP8Uk/BIsXgDoqEowgycdQQLuk= +github.com/dave/jennifer v1.6.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= -github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI= -github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= @@ -169,9 +145,9 @@ github.com/docker/docker v20.10.18+incompatible h1:SN84VYXTBNGn92T/QwIRPlum9zfem github.com/docker/docker v20.10.18+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= @@ -182,39 +158,47 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v0.9.1 h1:PS7VIOgmSVhWUEeZwTe7z7zouA22Cr590PzXKbZHOVY= -github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/flynn/go-docopt v0.0.0-20140912013429-f6dd2ebbb31e/go.mod h1:HyVoz1Mz5Co8TFO8EupIdlcpwShBmY98dkT2xeHkvEI= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= +github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= github.com/go-toolsmith/astcopy v1.0.2 h1:YnWf5Rnh1hUudj11kei53kI57quN/VH6Hp1n+erozn0= github.com/go-toolsmith/astcopy v1.0.2/go.mod h1:4TcEdbElGc9twQEYpVo/aieIXfHhiuLh4aLAck6dO7Y= @@ -223,36 +207,34 @@ github.com/go-toolsmith/astequal v1.0.3 h1:+LVdyRatFS+XO78SGV4I3TCEA0AC7fKEGma+f github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -263,19 +245,17 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -286,35 +266,29 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20230509042627-b1315fad0c5a h1:PEOGDI1kkyW37YqPWHLHc+D20D9+87Wt12TCcfTUo5Q= +github.com/google/pprof v0.0.0-20230509042627-b1315fad0c5a/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.6.0 h1:SXk3ABtQYDT/OH8jAyvEOQ58mgawq5C4o/4/89qN2ZU= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= +github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= +github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQZOmDhRqsv5mZf+Jb1RnSLxcqZcI= @@ -328,23 +302,19 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v1.3.1 h1:vDwF1DFNZhntP4DAjuTpOw3uEgMUpXh1pB5fW9DqHpo= -github.com/hashicorp/go-hclog v1.3.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.5 h1:oTE/oQR4eghggRg8VY7PAz3dr++VwDNBGCcOfIvHpBo= -github.com/hashicorp/go-plugin v1.4.5/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.7.1 h1:sUiuQAnLlbvmExtFQs72iFW/HXeUn8Z1aJLQ4LJJbTQ= github.com/hashicorp/go-retryablehttp v0.7.1/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 h1:p4AKXPPS24tO8Wc8i1gLvSKdmkiSY5xuju57czJ/IJQ= -github.com/hashicorp/go-secure-stdlib/mlock v0.1.2/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ= github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= @@ -355,32 +325,25 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.5.0 h1:O293SZ2Eg+AAYijkVK3jR786Am1bhDEh2GHT0tIVE5E= -github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= +github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/vault/api v1.8.2 h1:C7OL9YtOtwQbTKI9ogB0A1wffRbCN+rH/LLCHO3d8HM= -github.com/hashicorp/vault/api v1.8.2/go.mod h1:ML8aYzBIhY5m1MD1B2Q0JV89cC85YVH4t5kBaZiyVaE= -github.com/hashicorp/vault/sdk v0.6.0 h1:6Z+In5DXHiUfZvIZdMx7e2loL1PPyDjA4bVh9ZTIAhs= -github.com/hashicorp/vault/sdk v0.6.0/go.mod h1:+DRpzoXIdMvKc88R4qxr+edwy/RvH5QK8itmxLiDHLc= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I= -github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/hashicorp/vault/api v1.9.2 h1:YjkZLJ7K3inKgMZ0wzCU9OHqc+UqMQyXsPXnf3Cl2as= +github.com/hashicorp/vault/api v1.9.2/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= -github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ= -github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= +github.com/huin/goupnp v1.1.0 h1:gEe0Dp/lZmPZiDFzJJaOfUpOvv2MKUkoBX8lDrn9vKU= +github.com/huin/goupnp v1.1.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= -github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/ipfs/go-cid v0.2.0 h1:01JTiihFq9en9Vz0lc0VDWvZe/uBonGpzo4THP0vcQ0= -github.com/ipfs/go-cid v0.2.0/go.mod h1:P+HXFDF4CVhaVayiEb4wkAy7zBHxBwsJyt0Y5U6MLro= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk= github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8= @@ -396,50 +359,42 @@ github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABo github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.5 h1:qyCLMz2JCrKADihKOh9FxnW3houKeNsp2h5OEz0QSEA= -github.com/klauspost/compress v1.15.5/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0= -github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU= +github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= -github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8= -github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA= +github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= +github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= @@ -447,45 +402,29 @@ github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38y github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.22.0 h1:2Tce0kHOp5zASFKJbNzRElvh0iZwdtG5uZheNW8chIw= -github.com/libp2p/go-libp2p v0.22.0/go.mod h1:UDolmweypBSjQb2f7xutPnwZ/fxioLbMBxSjRksxxU4= -github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw= -github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI= -github.com/libp2p/go-libp2p-kbucket v0.5.0 h1:g/7tVm8ACHDxH29BGrpsQlnNeu+6OF1A9bno/4/U1oA= -github.com/libp2p/go-libp2p-kbucket v0.5.0/go.mod h1:zGzGCpQd78b5BNTDGHNDLaTt9aDK/A02xeZp9QeFC4U= -github.com/libp2p/go-libp2p-pubsub v0.8.1 h1:hSw09NauFUaA0FLgQPBJp6QOy0a2n+HSkb8IeOx8OnY= -github.com/libp2p/go-libp2p-pubsub v0.8.1/go.mod h1:e4kT+DYjzPUYGZeWk4I+oxCSYTXizzXii5LDRRhjKSw= +github.com/libp2p/go-libp2p v0.27.6 h1:KmGU5kskCaaerm53heqzfGOlrW2z8icZ+fnyqgrZs38= +github.com/libp2p/go-libp2p v0.27.6/go.mod h1:oMfQGTb9CHnrOuSM6yMmyK2lXz3qIhnkn2+oK3B1Y2g= +github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= +github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= +github.com/libp2p/go-libp2p-kbucket v0.6.0 h1:1uyqIdE6X7ihtbNg+vRc9EQEmZPEBaehvJ2W14rUrRQ= +github.com/libp2p/go-libp2p-kbucket v0.6.0/go.mod h1:efnPrfoP+WT/ONcC5eB0iADCDIJFXauXhylgJYO+VWw= +github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= +github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-msgio v0.2.0 h1:W6shmB+FeynDrUVl2dgFQvzfBZcXiyqY4VmpQLu9FqU= -github.com/libp2p/go-msgio v0.2.0/go.mod h1:dBVM1gW3Jk9XqHkU4eKdGvVHdLa51hoGfll6jMJMSlY= +github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= +github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg= github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM= github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= -github.com/libp2p/go-netroute v0.2.0 h1:0FpsbsvuSnAhXFnCY0VLFbJOzaK0VnP0r1QT/o4nWRE= -github.com/libp2p/go-netroute v0.2.0/go.mod h1:Vio7LTzZ+6hoT4CMZi5/6CpY3Snzh2vgZhWgxMNwlQI= -github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo= -github.com/libp2p/go-openssl v0.1.0/go.mod h1:OiOxwPpL3n4xlenjx2h7AwSGaFSC/KZvf6gNdOBQMtc= +github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= +github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560= github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtIlaURZZgOY4k= github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= -github.com/libp2p/go-yamux/v3 v3.1.2 h1:lNEy28MBk1HavUAlzKgShp+F6mn/ea1nDYWftZhFW9Q= -github.com/libp2p/go-yamux/v3 v3.1.2/go.mod h1:jeLEQgLXqE2YqX1ilAClIfCMDY+0uXQUKmmb/qp0gT4= -github.com/lucas-clemente/quic-go v0.28.1 h1:Uo0lvVxWg5la9gflIF9lwa39ONq85Xq2D91YNEIslzU= -github.com/lucas-clemente/quic-go v0.28.1/go.mod h1:oGz5DKK41cJt5+773+BSO9BXDsREY4HLf7+0odGAPO0= +github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ= +github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= -github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= -github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= -github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ= -github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= -github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM= -github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= -github.com/marten-seemann/qtls-go1-19 v0.1.0-beta.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= -github.com/marten-seemann/qtls-go1-19 v0.1.0 h1:rLFKD/9mp/uq1SYGYuVZhm83wkmU95pK5df3GufyYYU= -github.com/marten-seemann/qtls-go1-19 v0.1.0/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -495,16 +434,15 @@ github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0= -github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= +github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -513,107 +451,102 @@ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdn github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= -github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae h1:O4SWKdcHVCvYqyDV+9CJA1fcDN2L11Bule0iFy3YlAI= github.com/moby/term v0.0.0-20220808134915-39b0c02b01ae/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-base32 v0.0.4 h1:+qMh4a2f37b4xTNs6mqitDinryCI+tfO2dRVMN9mjSE= -github.com/multiformats/go-base32 v0.0.4/go.mod h1:jNLFzjPZtp3aIARHbJRZIaPuspdH0J6q39uUM5pnABM= -github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= -github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= +github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= +github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.7.0 h1:gskHcdaCyPtp9XskVwtvEeQOG465sCohbQIirSyqxrc= -github.com/multiformats/go-multiaddr v0.7.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs= +github.com/multiformats/go-multiaddr v0.9.0 h1:3h4V1LHIk5w4hJHekMKWALPXErDfz/sggzwC/NcqbDQ= +github.com/multiformats/go-multiaddr v0.9.0/go.mod h1:mI67Lb1EeTOYb8GQfL/7wpIZwc46ElrvzhYnoJOmTT0= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI= -github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8= -github.com/multiformats/go-multicodec v0.5.0 h1:EgU6cBe/D7WRwQb1KmnBvU7lrcFGMggZVTPtOW9dDHs= -github.com/multiformats/go-multicodec v0.5.0/go.mod h1:DiY2HFaEp5EhEXb/iYzVAunmyX/aSFMxq2KMKfWEues= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= +github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= -github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108= -github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc= -github.com/multiformats/go-multistream v0.3.3 h1:d5PZpjwRgVlbwfdTDjife7XszfZd8KYWfROYFlGcR8o= -github.com/multiformats/go-multistream v0.3.3/go.mod h1:ODRoqamLUsETKS9BNcII4gcRsJBU5VAwRIv7O39cEXg= +github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= +github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= +github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= -github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= -github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= -github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= +github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= +github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA= github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/outcaste-io/ristretto v0.2.1 h1:KCItuNIGJZcursqHr3ghO7fc5ddZLEHspL9UR0cQM64= +github.com/outcaste-io/ristretto v0.2.1/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= -github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= -github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -624,33 +557,25 @@ github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.13.1 h1:3gMjIY2+/hzmqhtUC/aQNYldJA6DtH3CgQvwS+02K1c= -github.com/prometheus/client_golang v1.13.1/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= -github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= -github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/quasilyte/go-ruleguard v0.3.19 h1:tfMnabXle/HzOb5Xe9CUZYWXKfkS1KwRmZyPmD9nVcc= github.com/quasilyte/go-ruleguard v0.3.19/go.mod h1:lHSn69Scl48I7Gt9cX3VrbsZYvYiBYszZOZW4A+oTEw= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= @@ -659,9 +584,23 @@ github.com/quasilyte/gogrep v0.5.0 h1:eTKODPXbI8ffJMN+W2aE0+oL0z/nh8/5eNdiO34SOA github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 h1:M8mH9eK4OUR4lu7Gd+PU1fV2/qnDNfzT635KRSObncs= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U= +github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E= +github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= +github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= +github.com/quic-go/webtransport-go v0.5.2 h1:GA6Bl6oZY+g/flt00Pnu0XtivSD8vukOu3lYhJjnGEk= +github.com/quic-go/webtransport-go v0.5.2/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= +github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052 h1:Qp27Idfgi6ACvFQat5+VJvlYToylpM/hcyLBI3WaKPA= +github.com/richardartoul/molecule v1.0.1-0.20221107223329-32cfee06a052/go.mod h1:uvX/8buq8uVeiZiFht+0lqSLBHF+uGV8BrTv8W/SIwk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -670,7 +609,13 @@ github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/secure-systems-lab/go-securesystemslib v0.3.1/go.mod h1:o8hhjkbNl2gOamKUA/eNW3xUrntHT9L4W89W1nfj43U= +github.com/secure-systems-lab/go-securesystemslib v0.6.0 h1:T65atpAVCJQK14UA57LMdZGpHi4QYSH/9FZyNGqMYIA= +github.com/secure-systems-lab/go-securesystemslib v0.6.0/go.mod h1:8Mtpo9JKks/qhPG4HGZ2LGMvrPbzuxwfz/f/zLfEWkk= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= +github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -694,23 +639,17 @@ github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go. github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= -github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= -github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -728,22 +667,31 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= -github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tinylib/msgp v1.1.6 h1:i+SbKraHhnrf9M5MYmvQhFnbLhAXSDWF8WWsuyRdocw= +github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= +github.com/trailofbits/go-fuzz-utils v0.0.0-20210901195358-9657fcfd256c h1:4WU+p200eLYtBsx3M5CKXvkjVdf5SC3W9nMg37y0TFI= +github.com/trailofbits/go-fuzz-utils v0.0.0-20210901195358-9657fcfd256c/go.mod h1:f3jBhpWvuZmue0HZK52GzRHJOYHYSILs/c8+K2S/J+o= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= -github.com/umbracle/ethgo v0.1.4-0.20230126112511-6a4d02533af6 h1:WqlyYNdrBECgDwDIEMxa4mLUSH/FfPdAuOnniUqNpJs= -github.com/umbracle/ethgo v0.1.4-0.20230126112511-6a4d02533af6/go.mod h1:8QIHEG/YfGnW4I5AND2Znl9W0LU3tXR9IGqgmSieiGo= -github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 h1:10Nbw6cACsnQm7r34zlpJky+IzxVLRk6MKTS2d3Vp0E= -github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/umbracle/ethgo v0.1.4-0.20230622091706-8230f57578b2 h1:yjKMn4wmRd1jFN2vgysTN+xbR673XzAIuBTncO1hWGo= +github.com/umbracle/ethgo v0.1.4-0.20230622091706-8230f57578b2/go.mod h1:J+OZNfRCtbaYW3AEc0m47GhwAzlNJjcr9vO86nzOr6E= +github.com/umbracle/fastrlp v0.1.1-0.20230504065717-58a1b8a9929d h1:HAg1Kpr9buwRxEiC2UXU9oT2AU8uCU7o3/WTH+Lt5wo= +github.com/umbracle/fastrlp v0.1.1-0.20230504065717-58a1b8a9929d/go.mod h1:5RHgqiFjd4vLJESMWagP/E7su+5Gzk0iqqmrotR8WdA= github.com/umbracle/go-eth-bn256 v0.0.0-20230125114011-47cb310d9b0b h1:5/xofhZiOG0I9DQXqDSPxqYObk6QI7mBGMJI+ngyIgc= github.com/umbracle/go-eth-bn256 v0.0.0-20230125114011-47cb310d9b0b/go.mod h1:H8SeC2PWEciymT92Mt07Qcfjr2FMEuCz/V+KPtPTy+U= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -754,38 +702,37 @@ github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLr github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow= -github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/dig v1.16.1 h1:+alNIBsl0qfY0j6epRubp/9obgtrObRAc5aD+6jbWY8= +go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk= +go.uber.org/fx v1.19.2 h1:SyFgYQFr1Wl0AYstE8vyYIzP4bFz2URrScjwC4cwUvY= +go.uber.org/fx v1.19.2/go.mod h1:43G1VcqSzbIv77y00p1DRAsyZS8WdzuYdhZXmEUkMyQ= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= -go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= -go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org/intern v0.0.0-20211027215823-ae77deb06f29 h1:UXLjNohABv4S58tHmeuIZDO6e3mHpW2Dx33gaNt03LE= go4.org/intern v0.0.0-20211027215823-ae77deb06f29/go.mod h1:cS2ma+47FKrLPdXFpr7CuxiTW3eyJbWew4qx0qtQWDA= @@ -794,61 +741,41 @@ go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760 h1:FyBZqvo go4.org/unsafe/assume-no-moving-gc v0.0.0-20220617031537-928513b29760/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20221002003631-540bb7301a08 h1:VpoGhesgULkabDHoDFGayS1wnkasmT95Jq2xZDwN45Q= golang.org/x/exp/typeparams v0.0.0-20221002003631-540bb7301a08/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -861,55 +788,30 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= +golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1 h1:3VPzK7eqH25j7GYw5w6g/GzNRc0/fYtrxz27z1gD4W0= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= +golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= +golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -917,13 +819,10 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -933,45 +832,25 @@ golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -981,41 +860,38 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= +golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= -golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1023,54 +899,22 @@ golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.3.0 h1:SrNbZl6ECOS1qFzgTdQfWXZM9XBkiA6tkFrH9YSTPHM= -golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= +golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1080,32 +924,12 @@ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNq google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.99.0 h1:tsBtOIklCE2OFxhmcYSVqGwSAN/Y897srxmcvAQnwK8= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= +google.golang.org/api v0.109.0 h1:sW9hgHyX497PP5//NUM7nqfV8D0iDfBApqq7sOh1XR8= +google.golang.org/api v0.109.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1113,54 +937,20 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e h1:halCgTFuLWDRD61piiNSxPsARANGD3Xl16hPrLgLiIg= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2 h1:O97sLx/Xmb/KIZHB/2/BzofxBs5QmmR0LcihPtllmbc= +google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.53.0-dev h1:Bi96+XIrXJLXPJUff19tRXb7mIijir7agn12zNMaPAg= +google.golang.org/grpc v1.53.0-dev/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1169,16 +959,14 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/DataDog/dd-trace-go.v1 v1.43.1 h1:Dez4VzRQWAI5YXJRBx58BiC0gONGuW/oY4l8fWKzOXY= -gopkg.in/DataDog/dd-trace-go.v1 v1.43.1/go.mod h1:YL9g+nlUY7ByCffD5pDytAqy99GNbytRV0EBpKuldM4= -gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/DataDog/dd-trace-go.v1 v1.51.0 h1:nFsTjolqdh8slG6F1B7AGdFHX7/kp26Jkb8UvGSIIFY= +gopkg.in/DataDog/dd-trace-go.v1 v1.51.0/go.mod h1:+m1wWLyQfqd6fX0uy6YFbP1soWgmjQ+5TveksDt/fHc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1187,12 +975,9 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1208,26 +993,23 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -inet.af/netaddr v0.0.0-20220617031823-097006376321 h1:B4dC8ySKTQXasnjDTMsoCMf1sQG4WsMej0WXaHxunmU= -inet.af/netaddr v0.0.0-20220617031823-097006376321/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k= -lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= -lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= -pgregory.net/rapid v0.5.5 h1:jkgx1TjbQPD/feRoK+S/mXw9e1uj6WilpHrXJowi6oA= -pgregory.net/rapid v0.5.5/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +inet.af/netaddr v0.0.0-20220811202034-502d2d690317 h1:U2fwK6P2EqmopP/hFLTOAjWTki0qgd4GMJn5X8wOleU= +inet.af/netaddr v0.0.0-20220811202034-502d2d690317/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k= +lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= +lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +pgregory.net/rapid v1.0.0 h1:iQaM2w5PZ6xvt6x7hbd7tiDS+nk7YPp5uCaEba+T/F4= +pgregory.net/rapid v1.0.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/helper/common/common.go b/helper/common/common.go index a758af509f..11139435d3 100644 --- a/helper/common/common.go +++ b/helper/common/common.go @@ -1,6 +1,7 @@ package common import ( + "context" "encoding/binary" "encoding/json" "errors" @@ -13,10 +14,12 @@ import ( "os/user" "path/filepath" "strconv" + "strings" "syscall" + "time" "github.com/0xPolygon/polygon-edge/helper/hex" - "github.com/0xPolygon/polygon-edge/types" + "github.com/sethvargo/go-retry" ) var ( @@ -25,8 +28,21 @@ var ( // Our staking repo is written in JS, as are many other clients // If we use higher value JS will not be able to parse it MaxSafeJSInt = uint64(math.Pow(2, 53) - 2) + + errInvalidDuration = errors.New("invalid duration") ) +// RetryForever will execute a function until it completes without error +func RetryForever(ctx context.Context, interval time.Duration, fn func(context.Context) error) { + _ = retry.Do(ctx, retry.NewConstant(interval), func(context.Context) error { + if err := fn(ctx); err != nil { + return retry.RetryableError(err) + } + + return nil + }) +} + // Min returns the strictly lower number func Min(a, b uint64) uint64 { if a < b { @@ -45,12 +61,21 @@ func Max(a, b uint64) uint64 { return b } +// BigMin returns the smallest of x or y. +func BigMin(x, y *big.Int) *big.Int { + if x.Cmp(y) > 0 { + return y + } + + return x +} + func ConvertUnmarshalledUint(x interface{}) (uint64, error) { switch tx := x.(type) { case float64: return uint64(roundFloat(tx)), nil case string: - v, err := types.ParseUint64orHex(&tx) + v, err := ParseUint64orHex(&tx) if err != nil { return 0, err } @@ -61,14 +86,26 @@ func ConvertUnmarshalledUint(x interface{}) (uint64, error) { } } -func roundFloat(num float64) int64 { - return int64(num + math.Copysign(0.5, num)) -} +// ParseUint64orHex parses the given uint64 hex string into the number. +// It can parse the string with 0x prefix as well. +func ParseUint64orHex(val *string) (uint64, error) { + if val == nil { + return 0, nil + } -func ToFixedFloat(num float64, precision int) float64 { - output := math.Pow(10, float64(precision)) + str := *val + base := 10 - return float64(roundFloat(num*output)) / output + if strings.HasPrefix(str, "0x") { + str = str[2:] + base = 16 + } + + return strconv.ParseUint(str, base, 64) +} + +func roundFloat(num float64) int64 { + return int64(num + math.Copysign(0.5, num)) } // SetupDataDir sets up the data directory and the corresponding sub-directories @@ -237,6 +274,42 @@ func (d *JSONNumber) UnmarshalJSON(data []byte) error { return nil } +// Duration is a wrapper struct for time.Duration which implements json (un)marshaling +type Duration struct { + time.Duration +} + +func (d Duration) MarshalJSON() ([]byte, error) { + return json.Marshal(d.String()) +} + +func (d *Duration) UnmarshalJSON(b []byte) error { + var ( + v interface{} + err error + ) + + if err = json.Unmarshal(b, &v); err != nil { + return err + } + + switch value := v.(type) { + case float64: + d.Duration = time.Duration(value) + + return nil + case string: + d.Duration, err = time.ParseDuration(value) + if err != nil { + return err + } + + return nil + } + + return errInvalidDuration +} + // GetTerminationSignalCh returns a channel to emit signals by ctrl + c func GetTerminationSignalCh() <-chan os.Signal { // wait for the user to quit with ctrl-c @@ -271,8 +344,6 @@ func PadLeftOrTrim(bb []byte, size int) []byte { // ExtendByteSlice extends given byte slice by needLength parameter and trims it func ExtendByteSlice(b []byte, needLength int) []byte { - b = b[:cap(b)] - if n := needLength - len(b); n > 0 { b = append(b, make([]byte, n)...) } diff --git a/helper/common/common_test.go b/helper/common/common_test.go index ff009409c5..6a7af9e4e4 100644 --- a/helper/common/common_test.go +++ b/helper/common/common_test.go @@ -1,8 +1,12 @@ package common import ( + "context" + "encoding/json" + "errors" "math/big" "testing" + "time" "github.com/stretchr/testify/require" ) @@ -60,3 +64,71 @@ func Test_BigIntDivCeil(t *testing.T) { require.Equal(t, c.result, BigIntDivCeil(big.NewInt(c.a), big.NewInt(c.b)).Int64()) } } + +func Test_Duration_Marshal_UnmarshalJSON(t *testing.T) { + t.Parallel() + + t.Run("use duration standalone", func(t *testing.T) { + t.Parallel() + + original := &Duration{Duration: 5 * time.Minute} + originalRaw, err := original.MarshalJSON() + require.NoError(t, err) + + other := &Duration{} + require.NoError(t, other.UnmarshalJSON(originalRaw)) + require.Equal(t, original, other) + }) + + t.Run("use duration in wrapper struct", func(t *testing.T) { + t.Parallel() + + type timer struct { + Elapsed Duration `json:"elapsed"` + } + + dur, err := time.ParseDuration("2h35m21s") + require.NoError(t, err) + + origTimer := &timer{Elapsed: Duration{dur}} + + timerRaw, err := json.Marshal(origTimer) + require.NoError(t, err) + + var otherTimer *timer + require.NoError(t, json.Unmarshal(timerRaw, &otherTimer)) + require.Equal(t, origTimer, otherTimer) + }) +} + +func TestRetryForever_AlwaysReturnError_ShouldNeverEnd(t *testing.T) { + interval := time.Millisecond * 10 + ended := false + + go func() { + RetryForever(context.Background(), interval, func(ctx context.Context) error { + return errors.New("") + }) + + ended = true + }() + time.Sleep(interval * 10) + require.False(t, ended) +} + +func TestRetryForever_ReturnNilAfterFirstRun_ShouldEnd(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + RetryForever(ctx, time.Millisecond*100, func(ctx context.Context) error { + select { + case <-ctx.Done(): + + return nil + default: + cancel() + + return errors.New("") + } + }) + <-ctx.Done() + require.True(t, errors.Is(ctx.Err(), context.Canceled)) +} diff --git a/helper/config/config.go b/helper/config/config.go deleted file mode 100644 index ce75a0981a..0000000000 --- a/helper/config/config.go +++ /dev/null @@ -1,25 +0,0 @@ -package config - -import ( - "github.com/0xPolygon/polygon-edge/chain" - "github.com/0xPolygon/polygon-edge/types" -) - -// GetWhitelist fetches whitelist object from the config -func GetWhitelist(config *chain.Chain) *chain.Whitelists { - return config.Params.Whitelists -} - -// GetDeploymentWhitelist fetches deployment whitelist from the genesis config -// if doesn't exist returns empty list -func GetDeploymentWhitelist(genesisConfig *chain.Chain) ([]types.Address, error) { - // Fetch whitelist config if exists, if not init - whitelistConfig := GetWhitelist(genesisConfig) - - // Extract deployment whitelist if exists, if not init - if whitelistConfig == nil { - return make([]types.Address, 0), nil - } - - return whitelistConfig.Deployment, nil -} diff --git a/helper/keccak/pool.go b/helper/keccak/pool.go index cf0bcc64be..d6934e9068 100644 --- a/helper/keccak/pool.go +++ b/helper/keccak/pool.go @@ -53,3 +53,13 @@ func Keccak256Rlp(dst []byte, src *fastrlp.Value) []byte { return dst } + +// PrefixedKeccak256Rlp hashes a fastrlp.Value using keccak-256 with the given prefix +func PrefixedKeccak256Rlp(prefix, dst []byte, src *fastrlp.Value) []byte { + h := DefaultKeccakPool.Get() + _, _ = h.Write(prefix) + dst = h.WriteRlp(dst, src) + DefaultKeccakPool.Put(h) + + return dst +} diff --git a/helper/predeployment/predeployment.go b/helper/predeployment/predeployment.go index ce6d0f4ce6..fb846829ee 100644 --- a/helper/predeployment/predeployment.go +++ b/helper/predeployment/predeployment.go @@ -153,7 +153,10 @@ func getPredeployAccount(address types.Address, input, deployedBytecode []byte) // the state needs to be walked to collect all touched all storage slots storageMap := getModifiedStorageMap(radix, address) - transition.Commit() + _, _, _, err := transition.Commit() //nolint:dogsled + if err != nil { + return nil, fmt.Errorf("failed to commit the state changes: %w", err) + } return &chain.GenesisAccount{ Balance: transition.GetBalance(address), @@ -182,24 +185,29 @@ func GenerateGenesisAccountFromFile( return nil, fmt.Errorf("unable to create contract ABI, %w", err) } - // Constructor arguments are passed in as an array of values. - // Structs are treated as sub-arrays with their corresponding values laid out - // in ABI encoding - parsedArguments, err := ParseArguments(constructorArgs) - if err != nil { - return nil, err - } + finalBytecode := artifact.Bytecode + constructorInfo := contractABI.Constructor - // Encode the constructor params - constructor, err := abi.Encode( - parsedArguments, - contractABI.Constructor.Inputs, - ) - if err != nil { - return nil, fmt.Errorf("unable to encode constructor arguments, %w", err) - } + if constructorInfo != nil { + // Constructor arguments are passed in as an array of values. + // Structs are treated as sub-arrays with their corresponding values laid out + // in ABI encoding + parsedArguments, err := ParseArguments(constructorArgs) + if err != nil { + return nil, err + } - finalBytecode := append(artifact.Bytecode, constructor...) + // Encode the constructor params + constructor, err := abi.Encode( + parsedArguments, + contractABI.Constructor.Inputs, + ) + if err != nil { + return nil, fmt.Errorf("unable to encode constructor arguments, %w", err) + } + + finalBytecode = append(artifact.Bytecode, constructor...) + } return getPredeployAccount(predeployAddress, finalBytecode, artifact.DeployedBytecode) } diff --git a/helper/tests/testing.go b/helper/tests/testing.go index 64971c065a..ce91641857 100644 --- a/helper/tests/testing.go +++ b/helper/tests/testing.go @@ -16,7 +16,6 @@ import ( "github.com/multiformats/go-multiaddr" "github.com/umbracle/ethgo" - "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/crypto" txpoolOp "github.com/0xPolygon/polygon-edge/txpool/proto" "github.com/0xPolygon/polygon-edge/types" @@ -237,7 +236,7 @@ type GenerateTxReqParams struct { } func generateTx(params GenerateTxReqParams) (*types.Transaction, error) { - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) + signer := crypto.NewEIP155Signer(100, true) signedTx, signErr := signer.SignTx(&types.Transaction{ Nonce: params.Nonce, diff --git a/jsonrpc/codec.go b/jsonrpc/codec.go index a32acd5df1..f8f5191f9a 100644 --- a/jsonrpc/codec.go +++ b/jsonrpc/codec.go @@ -15,6 +15,8 @@ type Request struct { Params json.RawMessage `json:"params,omitempty"` } +type BatchRequest []Request + // Response is a jsonrpc response interface type Response interface { GetID() interface{} @@ -93,6 +95,25 @@ func (e *ObjectError) Error() string { return string(data) } +func (e *ObjectError) MarshalJSON() ([]byte, error) { + var ds string + + data, ok := e.Data.([]byte) + if ok && len(data) > 0 { + ds = "0x" + string(data) + } + + return json.Marshal(&struct { + Code int `json:"code"` + Message string `json:"message"` + Data string `json:"data,omitempty"` + }{ + Code: e.Code, + Message: e.Message, + Data: ds, + }) +} + const ( pending = "pending" latest = "latest" @@ -190,8 +211,8 @@ func (b *BlockNumber) UnmarshalJSON(buffer []byte) error { } // NewRPCErrorResponse is used to create a custom error response -func NewRPCErrorResponse(id interface{}, errCode int, err string, jsonrpcver string) Response { - errObject := &ObjectError{errCode, err, nil} +func NewRPCErrorResponse(id interface{}, errCode int, err string, data []byte, jsonrpcver string) Response { + errObject := &ObjectError{errCode, err, data} response := &ErrorResponse{ JSONRPC: jsonrpcver, @@ -209,7 +230,7 @@ func NewRPCResponse(id interface{}, jsonrpcver string, reply []byte, err Error) case nil: response = &SuccessResponse{JSONRPC: jsonrpcver, ID: id, Result: reply} default: - response = NewRPCErrorResponse(id, err.ErrorCode(), err.Error(), jsonrpcver) + response = NewRPCErrorResponse(id, err.ErrorCode(), err.Error(), reply, jsonrpcver) } return response diff --git a/jsonrpc/debug_endpoint_test.go b/jsonrpc/debug_endpoint_test.go index cd3828a4d9..5fd5aa6441 100644 --- a/jsonrpc/debug_endpoint_test.go +++ b/jsonrpc/debug_endpoint_test.go @@ -562,35 +562,41 @@ func TestTraceCall(t *testing.T) { t.Parallel() var ( - from = types.StringToAddress("1") - to = types.StringToAddress("2") - gas = argUint64(10000) - gasPrice = argBytes(new(big.Int).SetUint64(10).Bytes()) - value = argBytes(new(big.Int).SetUint64(1000).Bytes()) - data = argBytes([]byte("data")) - input = argBytes([]byte("input")) - nonce = argUint64(1) + from = types.StringToAddress("1") + to = types.StringToAddress("2") + gas = argUint64(10000) + gasPrice = argBytes(new(big.Int).SetUint64(10).Bytes()) + gasTipCap = argBytes(new(big.Int).SetUint64(10).Bytes()) + gasFeeCap = argBytes(new(big.Int).SetUint64(10).Bytes()) + value = argBytes(new(big.Int).SetUint64(1000).Bytes()) + data = argBytes([]byte("data")) + input = argBytes([]byte("input")) + nonce = argUint64(1) blockNumber = BlockNumber(testBlock10.Number()) txArg = &txnArgs{ - From: &from, - To: &to, - Gas: &gas, - GasPrice: &gasPrice, - Value: &value, - Data: &data, - Input: &input, - Nonce: &nonce, + From: &from, + To: &to, + Gas: &gas, + GasPrice: &gasPrice, + GasTipCap: &gasTipCap, + GasFeeCap: &gasFeeCap, + Value: &value, + Data: &data, + Input: &input, + Nonce: &nonce, } decodedTx = &types.Transaction{ - Nonce: uint64(nonce), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), - Gas: uint64(gas), - To: &to, - Value: new(big.Int).SetBytes([]byte(value)), - Input: data, - From: from, + Nonce: uint64(nonce), + GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), + GasTipCap: new(big.Int).SetBytes([]byte(gasTipCap)), + GasFeeCap: new(big.Int).SetBytes([]byte(gasFeeCap)), + Gas: uint64(gas), + To: &to, + Value: new(big.Int).SetBytes([]byte(value)), + Input: data, + From: from, } ) diff --git a/jsonrpc/dispatcher.go b/jsonrpc/dispatcher.go index 77e2ba5161..0cc86aa23d 100644 --- a/jsonrpc/dispatcher.go +++ b/jsonrpc/dispatcher.go @@ -7,9 +7,12 @@ import ( "fmt" "math" "reflect" + "strconv" "strings" + "time" "unicode" + "github.com/armon/go-metrics" "github.com/hashicorp/go-hclog" ) @@ -58,6 +61,10 @@ type dispatcherParams struct { blockRangeLimit uint64 } +func (dp dispatcherParams) isExceedingBatchLengthLimit(value uint64) bool { + return dp.jsonRPCBatchLengthLimit != 0 && value > dp.jsonRPCBatchLengthLimit +} + func newDispatcher( logger hclog.Logger, store JSONRPCStore, @@ -161,22 +168,23 @@ type wsConn interface { // as per https://www.jsonrpc.org/specification, the `id` in JSON-RPC 2.0 // can only be a string or a non-decimal integer -func formatFilterResponse(id interface{}, resp string) (string, Error) { +func formatID(id interface{}) (interface{}, Error) { switch t := id.(type) { case string: - return fmt.Sprintf(`{"jsonrpc":"2.0","id":"%s","result":"%s"}`, t, resp), nil + return t, nil case float64: if t == math.Trunc(t) { - return fmt.Sprintf(`{"jsonrpc":"2.0","id":%d,"result":"%s"}`, int(t), resp), nil + return int(t), nil } else { return "", NewInvalidRequestError("Invalid json request") } case nil: - return fmt.Sprintf(`{"jsonrpc":"2.0","id":null,"result":"%s"}`, resp), nil + return nil, nil default: return "", NewInvalidRequestError("Invalid json request") } } + func (d *Dispatcher) handleSubscribe(req Request, conn wsConn) (string, Error) { var params []interface{} if err := json.Unmarshal(req.Params, ¶ms); err != nil { @@ -231,54 +239,90 @@ func (d *Dispatcher) RemoveFilterByWs(conn wsConn) { } func (d *Dispatcher) HandleWs(reqBody []byte, conn wsConn) ([]byte, error) { - var req Request - if err := json.Unmarshal(reqBody, &req); err != nil { - return NewRPCResponse(req.ID, "2.0", nil, NewInvalidRequestError("Invalid json request")).Bytes() - } + const ( + openSquareBracket byte = '[' + closeSquareBracket byte = ']' + comma byte = ',' + ) - // if the request method is eth_subscribe we need to create a - // new filter with ws connection - if req.Method == "eth_subscribe" { - filterID, err := d.handleSubscribe(req, conn) - if err != nil { - return NewRPCResponse(req.ID, "2.0", nil, err).Bytes() - } + reqBody = bytes.TrimLeft(reqBody, " \t\r\n") - resp, err := formatFilterResponse(req.ID, filterID) + // if body begins with [ consider it as a batch request + if len(reqBody) > 0 && reqBody[0] == openSquareBracket { + var batchReq BatchRequest + err := json.Unmarshal(reqBody, &batchReq) if err != nil { - return NewRPCResponse(req.ID, "2.0", nil, err).Bytes() + return NewRPCResponse(nil, "2.0", nil, + NewInvalidRequestError("Invalid json batch request")).Bytes() } - return []byte(resp), nil - } - - if req.Method == "eth_unsubscribe" { - ok, err := d.handleUnsubscribe(req) - if err != nil { - return nil, err + // if not disabled, avoid handling long batch requests + if d.params.isExceedingBatchLengthLimit(uint64(len(batchReq))) { + return NewRPCResponse( + nil, + "2.0", + nil, + NewInvalidRequestError("Batch request length too long"), + ).Bytes() } - res := "false" - if ok { - res = "true" - } + responses := make([][]byte, len(batchReq)) - resp, err := formatFilterResponse(req.ID, res) - if err != nil { - return NewRPCResponse(req.ID, "2.0", nil, err).Bytes() + for i, req := range batchReq { + responses[i], err = d.handleSingleWs(req, conn).Bytes() + if err != nil { + return nil, err + } } - return []byte(resp), nil + var buf bytes.Buffer + + // batch output should look like: + // [ { "requestId": "1", "status": 200 }, { "requestId": "2", "status": 200 } ] + buf.WriteByte(openSquareBracket) // [ + buf.Write(bytes.Join(responses, []byte{comma})) // join responses with the comma separator + buf.WriteByte(closeSquareBracket) // ] + + return buf.Bytes(), nil + } + + var req Request + if err := json.Unmarshal(reqBody, &req); err != nil { + return NewRPCResponse(req.ID, "2.0", nil, NewInvalidRequestError("Invalid json request")).Bytes() } - // its a normal query that we handle with the dispatcher - resp, err := d.handleReq(req) + return d.handleSingleWs(req, conn).Bytes() +} + +func (d *Dispatcher) handleSingleWs(req Request, conn wsConn) Response { + id, err := formatID(req.ID) if err != nil { - return nil, err + return NewRPCResponse(nil, "2.0", nil, err) + } + + var response []byte + + switch req.Method { + case "eth_subscribe": + var filterID string + + // if the request method is eth_subscribe we need to create a new filter with ws connection + if filterID, err = d.handleSubscribe(req, conn); err == nil { + response = []byte(fmt.Sprintf("\"%s\"", filterID)) + } + case "eth_unsubscribe": + var ok bool + + if ok, err = d.handleUnsubscribe(req); err == nil { + response = []byte(strconv.FormatBool(ok)) + } + default: + // its a normal query that we handle with the dispatcher + response, err = d.handleReq(req) } - return NewRPCResponse(req.ID, "2.0", resp, err).Bytes() + return NewRPCResponse(id, "2.0", response, err) } func (d *Dispatcher) Handle(reqBody []byte) ([]byte, error) { @@ -303,7 +347,7 @@ func (d *Dispatcher) Handle(reqBody []byte) ([]byte, error) { } // handle batch requests - var requests []Request + var requests BatchRequest if err := json.Unmarshal(reqBody, &requests); err != nil { return NewRPCResponse( nil, @@ -314,7 +358,7 @@ func (d *Dispatcher) Handle(reqBody []byte) ([]byte, error) { } // if not disabled, avoid handling long batch requests - if d.params.jsonRPCBatchLengthLimit != 0 && len(requests) > int(d.params.jsonRPCBatchLengthLimit) { + if d.params.isExceedingBatchLengthLimit(uint64(len(requests))) { return NewRPCResponse( nil, "2.0", @@ -328,7 +372,7 @@ func (d *Dispatcher) Handle(reqBody []byte) ([]byte, error) { for _, req := range requests { var response, err = d.handleReq(req) if err != nil { - errorResponse := NewRPCResponse(req.ID, "2.0", nil, err) + errorResponse := NewRPCResponse(req.ID, "2.0", response, err) responses = append(responses, errorResponse) continue @@ -371,18 +415,33 @@ func (d *Dispatcher) handleReq(req Request) ([]byte, Error) { } } - output := fd.fv.Call(inArgs) - if err := getError(output[1]); err != nil { - d.logInternalError(req.Method, err) - - return nil, NewInvalidRequestError(err.Error()) - } - var ( data []byte err error + ok bool ) + start := time.Now().UTC() + output := fd.fv.Call(inArgs) // call rpc endpoint function + // measure execution time of rpc endpoint function + metrics.SetGauge([]string{jsonRPCMetric, req.Method + "_time"}, float32(time.Now().UTC().Sub(start).Seconds())) + + if err := getError(output[1]); err != nil { + // measure error on the rpc endpoint function + metrics.IncrCounter([]string{jsonRPCMetric, req.Method + "_errors"}, 1) + d.logInternalError(req.Method, err) + + if res := output[0].Interface(); res != nil { + data, ok = res.([]byte) + + if !ok { + return nil, NewInternalError(err.Error()) + } + } + + return data, NewInvalidRequestError(err.Error()) + } + if res := output[0].Interface(); res != nil { data, err = json.Marshal(res) if err != nil { @@ -396,7 +455,7 @@ func (d *Dispatcher) handleReq(req Request) ([]byte, Error) { } func (d *Dispatcher) logInternalError(method string, err error) { - d.logger.Error("failed to dispatch", "method", method, "err", err) + d.logger.Warn("failed to dispatch", "method", method, "err", err) } func (d *Dispatcher) registerService(serviceName string, service interface{}) error { diff --git a/jsonrpc/dispatcher_test.go b/jsonrpc/dispatcher_test.go index 3c5ca9ad8a..171edf2ac1 100644 --- a/jsonrpc/dispatcher_test.go +++ b/jsonrpc/dispatcher_test.go @@ -2,6 +2,7 @@ package jsonrpc import ( "encoding/json" + "fmt" "math/big" "reflect" "testing" @@ -102,6 +103,8 @@ func TestDispatcher_HandleWebsocketConnection_EthSubscribe(t *testing.T) { } func TestDispatcher_WebsocketConnection_RequestFormats(t *testing.T) { + t.Parallel() + store := newMockStore() dispatcher := newTestDispatcher(t, hclog.NewNullLogger(), @@ -212,6 +215,8 @@ func (m *mockService) Filter(f LogQuery) (interface{}, error) { } func TestDispatcherFuncDecode(t *testing.T) { + t.Parallel() + srv := &mockService{msgCh: make(chan interface{}, 10)} dispatcher := newTestDispatcher(t, @@ -290,20 +295,29 @@ func TestDispatcherFuncDecode(t *testing.T) { } func TestDispatcherBatchRequest(t *testing.T) { - handle := func(dispatcher *Dispatcher, reqBody []byte) []byte { - res, _ := dispatcher.Handle(reqBody) - - return res - } + t.Parallel() - cases := []struct { + type caseData struct { name string desc string dispatcher *Dispatcher reqBody []byte err *ObjectError batchResponse []*SuccessResponse - }{ + } + + mock := &mockWsConn{ + SetFilterIDFn: func(s string) { + }, + GetFilterIDFn: func() string { + return "" + }, + WriteMessageFn: func(i int, b []byte) error { + return nil + }, + } + + cases := []caseData{ { "leading-whitespace", "test with leading whitespace (\" \\t\\n\\n\\r\\)", @@ -425,14 +439,12 @@ func TestDispatcherBatchRequest(t *testing.T) { }, } - for _, c := range cases { - res := handle(c.dispatcher, c.reqBody) - + check := func(c caseData, res []byte) { if c.err != nil { var resp ErrorResponse assert.NoError(t, expectBatchJSONResult(res, &resp)) - assert.Equal(t, resp.Error, c.err) + assert.Equal(t, c.err, resp.Error) } else { var batchResp []SuccessResponse assert.NoError(t, expectBatchJSONResult(res, &batchResp)) @@ -440,21 +452,87 @@ func TestDispatcherBatchRequest(t *testing.T) { if c.name == "leading-whitespace" { assert.Len(t, batchResp, 4) for index, resp := range batchResp { - assert.Equal(t, resp.Error, c.batchResponse[index].Error) + assert.Equal(t, c.batchResponse[index].Error, resp.Error) } } else if c.name == "valid-batch-req" { assert.Len(t, batchResp, 6) for index, resp := range batchResp { - assert.Equal(t, resp.Error, c.batchResponse[index].Error) + assert.Equal(t, c.batchResponse[index].Error, resp.Error) } } else if c.name == "no-limits" { assert.Len(t, batchResp, 12) for index, resp := range batchResp { - assert.Equal(t, resp.Error, c.batchResponse[index].Error) + assert.Equal(t, c.batchResponse[index].Error, resp.Error) } } } } + + for _, c := range cases { + c := c + + t.Run(c.name, func(t *testing.T) { + t.Parallel() + + res, _ := c.dispatcher.HandleWs(c.reqBody, mock) + + check(c, res) + + res, _ = c.dispatcher.Handle(c.reqBody) + + check(c, res) + }) + } +} + +func TestDispatcher_WebsocketConnection_Unsubscribe(t *testing.T) { + t.Parallel() + + store := newMockStore() + dispatcher := newTestDispatcher(t, + hclog.NewNullLogger(), + store, + &dispatcherParams{ + chainID: 0, + priceLimit: 0, + jsonRPCBatchLengthLimit: 20, + blockRangeLimit: 1000, + }, + ) + mockConn := &mockWsConn{ + SetFilterIDFn: func(s string) { + }, + GetFilterIDFn: func() string { + return "" + }, + WriteMessageFn: func(i int, b []byte) error { + return nil + }, + } + + resp := SuccessResponse{} + reqUnsub := func(n string) []byte { + return []byte(fmt.Sprintf(`{"method": "eth_unsubscribe", "params": [%s]}`, n)) + } + + // non existing subscription + r, err := dispatcher.HandleWs(reqUnsub("\"787832\""), mockConn) + require.NoError(t, err) + + require.NoError(t, json.Unmarshal(r, &resp)) + assert.Equal(t, "false", string(resp.Result)) + + r, err = dispatcher.HandleWs([]byte(`{"method": "eth_subscribe", "params": ["newHeads"]}`), mockConn) + require.NoError(t, err) + + require.NoError(t, json.Unmarshal(r, &resp)) + + // existing subscription + r, err = dispatcher.HandleWs(reqUnsub(string(resp.Result)), mockConn) + require.NoError(t, err) + + require.NoError(t, json.Unmarshal(r, &resp)) + assert.Equal(t, "true", string(resp.Result)) } func newTestDispatcher(t *testing.T, logger hclog.Logger, store JSONRPCStore, params *dispatcherParams) *Dispatcher { diff --git a/jsonrpc/eth_blockchain_test.go b/jsonrpc/eth_blockchain_test.go index f29b689780..d59019809d 100644 --- a/jsonrpc/eth_blockchain_test.go +++ b/jsonrpc/eth_blockchain_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/0xPolygon/polygon-edge/blockchain" + "github.com/0xPolygon/polygon-edge/helper/hex" "github.com/0xPolygon/polygon-edge/helper/progress" "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/types" @@ -95,7 +96,7 @@ func TestEth_Block_GetBlockTransactionCountByNumber(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, res, "expected to return block, but got nil") - assert.Equal(t, res, 10) + assert.Equal(t, "0xa", res) } func TestEth_GetTransactionByHash(t *testing.T) { @@ -188,30 +189,58 @@ func TestEth_GetTransactionReceipt(t *testing.T) { eth := newTestEthEndpoint(store) block := newTestBlock(1, hash4) store.add(block) - txn := newTestTransaction(uint64(0), addr0) - block.Transactions = append(block.Transactions, txn) - rec := &types.Receipt{ + txn0 := newTestTransaction(uint64(0), addr0) + txn1 := newTestTransaction(uint64(1), addr1) + block.Transactions = []*types.Transaction{txn0, txn1} + receipt1 := &types.Receipt{ Logs: []*types.Log{ { + // log 0 + Topics: []types.Hash{ + hash1, + }, + }, + { + // log 1 + Topics: []types.Hash{ + hash2, + }, + }, + { + // log 2 + Topics: []types.Hash{ + hash3, + }, + }, + }, + } + receipt1.SetStatus(types.ReceiptSuccess) + receipt2 := &types.Receipt{ + Logs: []*types.Log{ + { + // log 3 Topics: []types.Hash{ hash4, }, }, }, } - rec.SetStatus(types.ReceiptSuccess) - store.receipts[hash4] = []*types.Receipt{rec} + receipt2.SetStatus(types.ReceiptSuccess) + store.receipts[hash4] = []*types.Receipt{receipt1, receipt2} - res, err := eth.GetTransactionReceipt(txn.Hash) + res, err := eth.GetTransactionReceipt(txn1.Hash) assert.NoError(t, err) assert.NotNil(t, res) //nolint:forcetypeassert response := res.(*receipt) - assert.Equal(t, txn.Hash, response.TxHash) + assert.Equal(t, txn1.Hash, response.TxHash) assert.Equal(t, block.Hash(), response.BlockHash) assert.NotNil(t, response.Logs) + assert.Len(t, response.Logs, 1) + assert.Equal(t, uint64(3), uint64(response.Logs[0].LogIndex)) + assert.Equal(t, uint64(1), uint64(response.Logs[0].TxIndex)) }) } @@ -304,7 +333,7 @@ func TestEth_Call(t *testing.T) { Nonce: argUintPtr(0), } - res, err := eth.Call(contractCall, BlockNumberOrHash{}) + res, err := eth.Call(contractCall, BlockNumberOrHash{}, nil) assert.Error(t, err) assert.Contains(t, err.Error(), store.ethCallError.Error()) @@ -328,11 +357,38 @@ func TestEth_Call(t *testing.T) { Nonce: argUintPtr(0), } - res, err := eth.Call(contractCall, BlockNumberOrHash{}) + res, err := eth.Call(contractCall, BlockNumberOrHash{}, nil) assert.NoError(t, err) assert.NotNil(t, res) }) + + t.Run("returns error and result as data of a reverted transaction execution", func(t *testing.T) { + t.Parallel() + + returnValue := []byte("Reverted()") + + store := newMockBlockStore() + store.add(newTestBlock(100, hash1)) + store.ethCallError = runtime.ErrExecutionReverted + store.returnValue = returnValue + eth := newTestEthEndpoint(store) + contractCall := &txnArgs{ + From: &addr0, + To: &addr1, + Gas: argUintPtr(100000), + GasPrice: argBytesPtr([]byte{0x64}), + Value: argBytesPtr([]byte{0x64}), + Data: nil, + Nonce: argUintPtr(0), + } + + res, err := eth.Call(contractCall, BlockNumberOrHash{}, nil) + assert.Error(t, err) + assert.NotNil(t, res) + bres := res.([]byte) //nolint:forcetypeassert + assert.Equal(t, []byte(hex.EncodeToString(returnValue)), bres) + }) } type testStore interface { @@ -348,6 +404,7 @@ type mockBlockStore struct { isSyncing bool averageGasPrice int64 ethCallError error + returnValue []byte } func newMockBlockStore() *mockBlockStore { @@ -517,14 +574,21 @@ func (m *mockBlockStore) GetAvgGasPrice() *big.Int { return big.NewInt(m.averageGasPrice) } -func (m *mockBlockStore) ApplyTxn(header *types.Header, txn *types.Transaction) (*runtime.ExecutionResult, error) { - return &runtime.ExecutionResult{Err: m.ethCallError}, nil +func (m *mockBlockStore) ApplyTxn(header *types.Header, txn *types.Transaction, overrides types.StateOverride) (*runtime.ExecutionResult, error) { + return &runtime.ExecutionResult{ + Err: m.ethCallError, + ReturnValue: m.returnValue, + }, nil } func (m *mockBlockStore) SubscribeEvents() blockchain.Subscription { return nil } +func (m *mockBlockStore) FilterExtra(extra []byte) ([]byte, error) { + return extra, nil +} + func newTestBlock(number uint64, hash types.Hash) *types.Block { return &types.Block{ Header: &types.Header{ diff --git a/jsonrpc/eth_endpoint.go b/jsonrpc/eth_endpoint.go index ba06b25a65..cbea344587 100644 --- a/jsonrpc/eth_endpoint.go +++ b/jsonrpc/eth_endpoint.go @@ -1,14 +1,15 @@ package jsonrpc import ( + "encoding/hex" "errors" "fmt" "math/big" "github.com/hashicorp/go-hclog" - "github.com/umbracle/fastrlp" "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/gasprice" "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/progress" "github.com/0xPolygon/polygon-edge/state" @@ -62,17 +63,24 @@ type ethBlockchainStore interface { GetAvgGasPrice() *big.Int // ApplyTxn applies a transaction object to the blockchain - ApplyTxn(header *types.Header, txn *types.Transaction) (*runtime.ExecutionResult, error) + ApplyTxn(header *types.Header, txn *types.Transaction, override types.StateOverride) (*runtime.ExecutionResult, error) // GetSyncProgression retrieves the current sync progression, if any GetSyncProgression() *progress.Progression } +type ethFilter interface { + // FilterExtra filters extra data from header extra that is not included in block hash + FilterExtra(extra []byte) ([]byte, error) +} + // ethStore provides access to the methods needed by eth endpoint type ethStore interface { ethTxPoolStore ethStateStore ethBlockchainStore + ethFilter + gasprice.GasStore } // Eth is the eth jsonrpc endpoint @@ -122,6 +130,10 @@ func (e *Eth) GetBlockByNumber(number BlockNumber, fullTx bool) (interface{}, er return nil, nil } + if err := e.filterExtra(block); err != nil { + return nil, err + } + return toBlock(block, fullTx), nil } @@ -132,9 +144,30 @@ func (e *Eth) GetBlockByHash(hash types.Hash, fullTx bool) (interface{}, error) return nil, nil } + if err := e.filterExtra(block); err != nil { + return nil, err + } + return toBlock(block, fullTx), nil } +func (e *Eth) filterExtra(block *types.Block) error { + // we need to copy it because the store returns header from storage directly + // and not a copy, so changing it, actually changes it in storage as well + headerCopy := block.Header.Copy() + + filteredExtra, err := e.store.FilterExtra(headerCopy.ExtraData) + if err != nil { + return err + } + + headerCopy.ExtraData = filteredExtra + // no need to recompute hash (filtered out data is not in the hash in the first place) + block.Header = headerCopy + + return nil +} + func (e *Eth) GetBlockTransactionCountByNumber(number BlockNumber) (interface{}, error) { num, err := GetNumericBlockNumber(number, e.store) if err != nil { @@ -147,7 +180,7 @@ func (e *Eth) GetBlockTransactionCountByNumber(number BlockNumber) (interface{}, return nil, nil } - return len(block.Transactions), nil + return *types.EncodeUint64(uint64(len(block.Transactions))), nil } // BlockNumber returns current block number @@ -285,35 +318,40 @@ func (e *Eth) GetTransactionReceipt(hash types.Hash) (interface{}, error) { return nil, nil } // find the transaction in the body - indx := -1 + txIndex := -1 + logIndex := 0 for i, txn := range block.Transactions { if txn.Hash == hash { - indx = i + txIndex = i break } + + // accumulate receipt logs indexes from block transactions + // that are before the desired transaction + logIndex += len(receipts[i].Logs) } - if indx == -1 { + if txIndex == -1 { // txn not found return nil, nil } - txn := block.Transactions[indx] - raw := receipts[indx] + txn := block.Transactions[txIndex] + raw := receipts[txIndex] logs := make([]*Log, len(raw.Logs)) - for indx, elem := range raw.Logs { - logs[indx] = &Log{ + for i, elem := range raw.Logs { + logs[i] = &Log{ Address: elem.Address, Topics: elem.Topics, Data: argBytes(elem.Data), BlockHash: block.Hash(), BlockNumber: argUint64(block.Number()), TxHash: txn.Hash, - TxIndex: argUint64(indx), - LogIndex: argUint64(indx), + TxIndex: argUint64(txIndex), + LogIndex: argUint64(logIndex + i), Removed: false, } } @@ -324,7 +362,7 @@ func (e *Eth) GetTransactionReceipt(hash types.Hash) (interface{}, error) { LogsBloom: raw.LogsBloom, Status: argUint64(*raw.Status), TxHash: txn.Hash, - TxIndex: argUint64(indx), + TxIndex: argUint64(txIndex), BlockHash: block.Hash(), BlockNumber: argUint64(block.Number()), GasUsed: argUint64(raw.GasUsed), @@ -358,24 +396,7 @@ func (e *Eth) GetStorageAt( return nil, err } - //nolint:godox - // TODO: GetStorage should return the values already parsed (to be fixed in EVM-522) - - // Parse the RLP value - p := &fastrlp.Parser{} - - v, err := p.Parse(result) - if err != nil { - return argBytesPtr(types.ZeroHash[:]), nil - } - - data, err := v.Bytes() - if err != nil { - return argBytesPtr(types.ZeroHash[:]), nil - } - - // Pad to return 32 bytes data - return argBytesPtr(types.BytesToHash(data).Bytes()), nil + return argBytesPtr(result), nil } // GasPrice returns the average gas price based on the last x blocks @@ -388,8 +409,45 @@ func (e *Eth) GasPrice() (interface{}, error) { return argUint64(common.Max(e.priceLimit, avgGasPrice)), nil } +type overrideAccount struct { + Nonce *argUint64 `json:"nonce"` + Code *argBytes `json:"code"` + Balance *argUint64 `json:"balance"` + State *map[types.Hash]types.Hash `json:"state"` + StateDiff *map[types.Hash]types.Hash `json:"stateDiff"` +} + +func (o *overrideAccount) ToType() types.OverrideAccount { + res := types.OverrideAccount{} + + if o.Nonce != nil { + res.Nonce = (*uint64)(o.Nonce) + } + + if o.Code != nil { + res.Code = *o.Code + } + + if o.Balance != nil { + res.Balance = new(big.Int).SetUint64(*(*uint64)(o.Balance)) + } + + if o.State != nil { + res.State = *o.State + } + + if o.StateDiff != nil { + res.StateDiff = *o.StateDiff + } + + return res +} + +// StateOverride is the collection of overridden accounts. +type stateOverride map[types.Address]overrideAccount + // Call executes a smart contract call using the transaction object data -func (e *Eth) Call(arg *txnArgs, filter BlockNumberOrHash) (interface{}, error) { +func (e *Eth) Call(arg *txnArgs, filter BlockNumberOrHash, apiOverride *stateOverride) (interface{}, error) { header, err := GetHeaderFromBlockNumberOrHash(filter, e.store) if err != nil { return nil, err @@ -404,15 +462,23 @@ func (e *Eth) Call(arg *txnArgs, filter BlockNumberOrHash) (interface{}, error) transaction.Gas = header.GasLimit } + var override types.StateOverride + if apiOverride != nil { + override = types.StateOverride{} + for addr, o := range *apiOverride { + override[addr] = o.ToType() + } + } + // The return value of the execution is saved in the transition (returnValue field) - result, err := e.store.ApplyTxn(header, transaction) + result, err := e.store.ApplyTxn(header, transaction, override) if err != nil { return nil, err } // Check if an EVM revert happened if result.Reverted() { - return nil, constructErrorFromRevert(result) + return []byte(hex.EncodeToString(result.ReturnValue)), constructErrorFromRevert(result) } if result.Failed() { @@ -540,7 +606,7 @@ func (e *Eth) EstimateGas(arg *txnArgs, rawNum *BlockNumber) (interface{}, error txn := transaction.Copy() txn.Gas = gas - result, applyErr := e.store.ApplyTxn(header, txn) + result, applyErr := e.store.ApplyTxn(header, txn, nil) if applyErr != nil { // Check the application error. @@ -726,3 +792,13 @@ func (e *Eth) UninstallFilter(id string) (bool, error) { func (e *Eth) Unsubscribe(id string) (bool, error) { return e.filterManager.Uninstall(id), nil } + +// MaxPriorityFeePerGas calculates the priority fee needed for transaction to be included in a block +func (e *Eth) MaxPriorityFeePerGas() (interface{}, error) { + priorityFee, err := e.store.MaxPriorityFeePerGas() + if err != nil { + return nil, err + } + + return argBigPtr(priorityFee), nil +} diff --git a/jsonrpc/eth_endpoint_test.go b/jsonrpc/eth_endpoint_test.go index 696bed3a1d..c8309141b6 100644 --- a/jsonrpc/eth_endpoint_test.go +++ b/jsonrpc/eth_endpoint_test.go @@ -35,22 +35,26 @@ func TestEth_DecodeTxn(t *testing.T) { { name: "should be successful", arg: &txnArgs{ - From: &addr1, - To: &addr2, - Gas: toArgUint64Ptr(21000), - GasPrice: toArgBytesPtr(big.NewInt(10000).Bytes()), - Value: toArgBytesPtr(oneEther.Bytes()), - Data: nil, - Nonce: toArgUint64Ptr(0), + From: &addr1, + To: &addr2, + Gas: toArgUint64Ptr(21000), + GasPrice: toArgBytesPtr(big.NewInt(10000).Bytes()), + GasTipCap: toArgBytesPtr(big.NewInt(10000).Bytes()), + GasFeeCap: toArgBytesPtr(big.NewInt(10000).Bytes()), + Value: toArgBytesPtr(oneEther.Bytes()), + Data: nil, + Nonce: toArgUint64Ptr(0), }, res: &types.Transaction{ - From: addr1, - To: &addr2, - Gas: 21000, - GasPrice: big.NewInt(10000), - Value: oneEther, - Input: []byte{}, - Nonce: 0, + From: addr1, + To: &addr2, + Gas: 21000, + GasPrice: big.NewInt(10000), + GasTipCap: big.NewInt(10000), + GasFeeCap: big.NewInt(10000), + Value: oneEther, + Input: []byte{}, + Nonce: 0, }, err: nil, }, @@ -64,13 +68,15 @@ func TestEth_DecodeTxn(t *testing.T) { Data: nil, }, res: &types.Transaction{ - From: types.ZeroAddress, - To: &addr2, - Gas: 21000, - GasPrice: big.NewInt(10000), - Value: oneEther, - Input: []byte{}, - Nonce: 0, + From: types.ZeroAddress, + To: &addr2, + Gas: 21000, + GasPrice: big.NewInt(10000), + GasTipCap: new(big.Int), + GasFeeCap: new(big.Int), + Value: oneEther, + Input: []byte{}, + Nonce: 0, }, err: nil, }, @@ -90,13 +96,15 @@ func TestEth_DecodeTxn(t *testing.T) { Data: nil, }, res: &types.Transaction{ - From: addr1, - To: &addr2, - Gas: 21000, - GasPrice: big.NewInt(10000), - Value: oneEther, - Input: []byte{}, - Nonce: 10, + From: addr1, + To: &addr2, + Gas: 21000, + GasPrice: big.NewInt(10000), + GasTipCap: new(big.Int), + GasFeeCap: new(big.Int), + Value: oneEther, + Input: []byte{}, + Nonce: 10, }, err: nil, }, @@ -111,13 +119,15 @@ func TestEth_DecodeTxn(t *testing.T) { Nonce: toArgUint64Ptr(1), }, res: &types.Transaction{ - From: addr1, - To: &addr2, - Gas: 21000, - GasPrice: big.NewInt(10000), - Value: new(big.Int).SetBytes([]byte{}), - Input: []byte{}, - Nonce: 1, + From: addr1, + To: &addr2, + Gas: 21000, + GasPrice: big.NewInt(10000), + GasTipCap: new(big.Int), + GasFeeCap: new(big.Int), + Value: new(big.Int).SetBytes([]byte{}), + Input: []byte{}, + Nonce: 1, }, err: nil, }, @@ -131,13 +141,15 @@ func TestEth_DecodeTxn(t *testing.T) { Nonce: toArgUint64Ptr(1), }, res: &types.Transaction{ - From: addr1, - To: &addr2, - Gas: 0, - GasPrice: big.NewInt(10000), - Value: new(big.Int).SetBytes([]byte{}), - Input: []byte{}, - Nonce: 1, + From: addr1, + To: &addr2, + Gas: 0, + GasPrice: big.NewInt(10000), + GasTipCap: new(big.Int), + GasFeeCap: new(big.Int), + Value: new(big.Int).SetBytes([]byte{}), + Input: []byte{}, + Nonce: 1, }, err: nil, }, @@ -230,6 +242,59 @@ func TestEth_GetNextNonce(t *testing.T) { } } +func TestEth_TxnType(t *testing.T) { + // Set up the mock accounts + accounts := []struct { + address types.Address + account *Account + }{ + { + types.StringToAddress("123"), + &Account{ + Nonce: 5, + }, + }, + } + + // Set up the mock store + store := newMockStore() + for _, acc := range accounts { + store.SetAccount(acc.address, acc.account) + } + + // Setup Txn + args := &txnArgs{ + From: &addr1, + To: &addr2, + Gas: toArgUint64Ptr(21000), + GasPrice: toArgBytesPtr(big.NewInt(10000).Bytes()), + GasTipCap: toArgBytesPtr(big.NewInt(10000).Bytes()), + GasFeeCap: toArgBytesPtr(big.NewInt(10000).Bytes()), + Value: toArgBytesPtr(oneEther.Bytes()), + Data: nil, + Nonce: toArgUint64Ptr(0), + Type: toArgUint64Ptr(uint64(types.DynamicFeeTx)), + } + + expectedRes := &types.Transaction{ + From: addr1, + To: &addr2, + Gas: 21000, + GasPrice: big.NewInt(10000), + GasTipCap: big.NewInt(10000), + GasFeeCap: big.NewInt(10000), + Value: oneEther, + Input: []byte{}, + Nonce: 0, + Type: types.DynamicFeeTx, + } + res, err := DecodeTxn(args, store) + + expectedRes.ComputeHash() + assert.NoError(t, err) + assert.Equal(t, expectedRes, res) +} + func newTestEthEndpoint(store testStore) *Eth { return &Eth{ hclog.NewNullLogger(), store, 100, nil, 0, diff --git a/jsonrpc/eth_state_test.go b/jsonrpc/eth_state_test.go index af3ff5cbd5..79750433dc 100644 --- a/jsonrpc/eth_state_test.go +++ b/jsonrpc/eth_state_test.go @@ -11,7 +11,6 @@ import ( "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/types" "github.com/stretchr/testify/assert" - "github.com/umbracle/fastrlp" ) var ( @@ -555,10 +554,7 @@ func TestEth_State_GetStorageAt(t *testing.T) { } account := store.account for index, data := range storage { - a := &fastrlp.Arena{} - value := a.NewBytes(data.Bytes()) - newData := value.MarshalTo(nil) - account.Storage(index, newData) + account.Storage(index, data.Bytes()) } } @@ -616,10 +612,7 @@ func getExampleStore() *mockSpecialStore { // the latest block gas limit for the upper bound, or the specified // gas limit in the transaction func TestEth_EstimateGas_GasLimit(t *testing.T) { - //nolint:godox - // TODO Make this test run in parallel when the race condition is fixed in gas estimation (to be fixed in EVM-523) - store := getExampleStore() - ethEndpoint := newTestEthEndpoint(store) + t.Parallel() testTable := []struct { name string @@ -654,7 +647,14 @@ func TestEth_EstimateGas_GasLimit(t *testing.T) { } for _, testCase := range testTable { + testCase := testCase + t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + + store := getExampleStore() + ethEndpoint := newTestEthEndpoint(store) + // Set up the apply hook if errors.Is(testCase.expectedError, state.ErrNotEnoughIntrinsicGas) { // We want to trigger a situation where no value in the gas range is correct @@ -840,7 +840,7 @@ func (m *mockSpecialStore) GetForksInTime(blockNumber uint64) chain.ForksInTime return chain.ForksInTime{} } -func (m *mockSpecialStore) ApplyTxn(header *types.Header, txn *types.Transaction) (*runtime.ExecutionResult, error) { +func (m *mockSpecialStore) ApplyTxn(header *types.Header, txn *types.Transaction, overrides types.StateOverride) (*runtime.ExecutionResult, error) { if m.applyTxnHook != nil { return m.applyTxnHook(header, txn) } diff --git a/jsonrpc/filter_manager.go b/jsonrpc/filter_manager.go index 2e20dd0ad0..489e1a3eb2 100644 --- a/jsonrpc/filter_manager.go +++ b/jsonrpc/filter_manager.go @@ -375,10 +375,11 @@ func (f *FilterManager) getLogsFromBlock(query *LogQuery, block *types.Block) ([ return nil, err } + logIdx := uint64(0) logs := make([]*Log, 0) for idx, receipt := range receipts { - for logIdx, log := range receipt.Logs { + for _, log := range receipt.Logs { if query.Match(log) { logs = append(logs, &Log{ Address: log.Address, @@ -391,6 +392,8 @@ func (f *FilterManager) getLogsFromBlock(query *LogQuery, block *types.Block) ([ LogIndex: argUint64(logIdx), }) } + + logIdx++ } } diff --git a/jsonrpc/filter_manager_test.go b/jsonrpc/filter_manager_test.go index a8658f0ed7..e4aa1092a4 100644 --- a/jsonrpc/filter_manager_test.go +++ b/jsonrpc/filter_manager_test.go @@ -16,6 +16,7 @@ import ( "github.com/gorilla/websocket" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_GetLogsForQuery(t *testing.T) { @@ -154,6 +155,82 @@ func Test_GetLogsForQuery(t *testing.T) { } } +func Test_getLogsFromBlock(t *testing.T) { + t.Parallel() + + numOfLogs := 4 + + block := &types.Block{ + Header: &types.Header{Hash: types.StringToHash("someHash"), Number: 1}, + Transactions: []*types.Transaction{ + createTestTransaction(types.StringToHash("tx1")), + createTestTransaction(types.StringToHash("tx2")), + createTestTransaction(types.StringToHash("tx3")), + }, + } + + // setup test with block with 3 transactions and 4 logs + store := &mockBlockStore{receipts: map[types.Hash][]*types.Receipt{ + block.Header.Hash: { + { + // transaction 1 logs + Logs: []*types.Log{ + { + Topics: []types.Hash{ + hash1, + }, + }, + { + Topics: []types.Hash{ + hash2, + }, + }, + }, + }, + { + // transaction 2 logs + Logs: []*types.Log{ + { + Topics: []types.Hash{ + hash3, + }, + }, + }, + }, + { + // transaction 3 logs + Logs: []*types.Log{ + { + Topics: []types.Hash{ + hash4, + }, + }, + }, + }, + }, + }} + + store.appendBlocksToStore([]*types.Block{block}) + + f := NewFilterManager(hclog.NewNullLogger(), store, 1000) + + t.Cleanup(func() { + defer f.Close() + }) + + logs, err := f.getLogsFromBlock(&LogQuery{ + fromBlock: 1, + toBlock: 1, + }, block) + + require.NoError(t, err) + require.Len(t, logs, numOfLogs) + + for i := 0; i < numOfLogs; i++ { + require.Equal(t, uint64(i), uint64(logs[i].LogIndex)) + } +} + func Test_GetLogFilterFromID(t *testing.T) { t.Parallel() diff --git a/jsonrpc/helper.go b/jsonrpc/helper.go index 2bdd7be6fa..4f3fcdc820 100644 --- a/jsonrpc/helper.go +++ b/jsonrpc/helper.go @@ -189,6 +189,14 @@ func DecodeTxn(arg *txnArgs, store nonceGetter) (*types.Transaction, error) { arg.GasPrice = argBytesPtr([]byte{}) } + if arg.GasTipCap == nil { + arg.GasTipCap = argBytesPtr([]byte{}) + } + + if arg.GasFeeCap == nil { + arg.GasFeeCap = argBytesPtr([]byte{}) + } + var input []byte if arg.Data != nil { input = *arg.Data @@ -208,14 +216,23 @@ func DecodeTxn(arg *txnArgs, store nonceGetter) (*types.Transaction, error) { arg.Gas = argUintPtr(0) } + txType := types.LegacyTx + if arg.Type != nil { + txType = types.TxType(*arg.Type) + } + txn := &types.Transaction{ - From: *arg.From, - Gas: uint64(*arg.Gas), - GasPrice: new(big.Int).SetBytes(*arg.GasPrice), - Value: new(big.Int).SetBytes(*arg.Value), - Input: input, - Nonce: uint64(*arg.Nonce), + From: *arg.From, + Gas: uint64(*arg.Gas), + GasPrice: new(big.Int).SetBytes(*arg.GasPrice), + GasTipCap: new(big.Int).SetBytes(*arg.GasTipCap), + GasFeeCap: new(big.Int).SetBytes(*arg.GasFeeCap), + Value: new(big.Int).SetBytes(*arg.Value), + Input: input, + Nonce: uint64(*arg.Nonce), + Type: txType, } + if arg.To != nil { txn.To = arg.To } diff --git a/jsonrpc/helper_test.go b/jsonrpc/helper_test.go index 56b67b14c6..2e1cbf1f91 100644 --- a/jsonrpc/helper_test.go +++ b/jsonrpc/helper_test.go @@ -630,6 +630,8 @@ func TestDecodeTxn(t *testing.T) { to = types.StringToAddress("2") gas = argUint64(uint64(1)) gasPrice = argBytes(new(big.Int).SetUint64(2).Bytes()) + gasTipCap = argBytes(new(big.Int).SetUint64(2).Bytes()) + gasFeeCap = argBytes(new(big.Int).SetUint64(2).Bytes()) value = argBytes(new(big.Int).SetUint64(4).Bytes()) data = argBytes(new(big.Int).SetUint64(8).Bytes()) input = argBytes(new(big.Int).SetUint64(16).Bytes()) @@ -649,23 +651,27 @@ func TestDecodeTxn(t *testing.T) { { name: "should return mapped transaction", arg: &txnArgs{ - From: &from, - To: &to, - Gas: &gas, - GasPrice: &gasPrice, - Value: &value, - Input: &input, - Nonce: &nonce, + From: &from, + To: &to, + Gas: &gas, + GasPrice: &gasPrice, + GasTipCap: &gasTipCap, + GasFeeCap: &gasFeeCap, + Value: &value, + Input: &input, + Nonce: &nonce, }, store: &debugEndpointMockStore{}, expected: &types.Transaction{ - From: from, - To: &to, - Gas: uint64(gas), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), - Value: new(big.Int).SetBytes([]byte(value)), - Input: input, - Nonce: uint64(nonce), + From: from, + To: &to, + Gas: uint64(gas), + GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), + GasTipCap: new(big.Int).SetBytes([]byte(gasTipCap)), + GasFeeCap: new(big.Int).SetBytes([]byte(gasFeeCap)), + Value: new(big.Int).SetBytes([]byte(value)), + Input: input, + Nonce: uint64(nonce), }, err: false, }, @@ -681,13 +687,15 @@ func TestDecodeTxn(t *testing.T) { }, store: &debugEndpointMockStore{}, expected: &types.Transaction{ - From: types.ZeroAddress, - To: &to, - Gas: uint64(gas), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), - Value: new(big.Int).SetBytes([]byte(value)), - Input: input, - Nonce: uint64(0), + From: types.ZeroAddress, + To: &to, + Gas: uint64(gas), + GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), + GasTipCap: new(big.Int), + GasFeeCap: new(big.Int), + Value: new(big.Int).SetBytes([]byte(value)), + Input: input, + Nonce: uint64(0), }, err: false, }, @@ -714,13 +722,15 @@ func TestDecodeTxn(t *testing.T) { }, }, expected: &types.Transaction{ - From: from, - To: &to, - Gas: uint64(gas), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), - Value: new(big.Int).SetBytes([]byte(value)), - Input: input, - Nonce: uint64(stateNonce), + From: from, + To: &to, + Gas: uint64(gas), + GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), + GasTipCap: new(big.Int), + GasFeeCap: new(big.Int), + Value: new(big.Int).SetBytes([]byte(value)), + Input: input, + Nonce: uint64(stateNonce), }, err: false, }, @@ -738,13 +748,15 @@ func TestDecodeTxn(t *testing.T) { }, store: &debugEndpointMockStore{}, expected: &types.Transaction{ - From: from, - To: &to, - Gas: uint64(gas), - GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), - Value: new(big.Int).SetBytes([]byte(value)), - Input: data, - Nonce: uint64(nonce), + From: from, + To: &to, + Gas: uint64(gas), + GasPrice: new(big.Int).SetBytes([]byte(gasPrice)), + GasTipCap: new(big.Int), + GasFeeCap: new(big.Int), + Value: new(big.Int).SetBytes([]byte(value)), + Input: data, + Nonce: uint64(nonce), }, err: false, }, @@ -757,13 +769,15 @@ func TestDecodeTxn(t *testing.T) { }, store: &debugEndpointMockStore{}, expected: &types.Transaction{ - From: from, - To: &to, - Gas: uint64(0), - GasPrice: new(big.Int), - Value: new(big.Int), - Input: []byte{}, - Nonce: uint64(nonce), + From: from, + To: &to, + Gas: uint64(0), + GasPrice: new(big.Int), + GasTipCap: new(big.Int), + GasFeeCap: new(big.Int), + Value: new(big.Int), + Input: []byte{}, + Nonce: uint64(nonce), }, err: false, }, diff --git a/jsonrpc/mocks_test.go b/jsonrpc/mocks_test.go index f1738dfc00..1078090d39 100644 --- a/jsonrpc/mocks_test.go +++ b/jsonrpc/mocks_test.go @@ -196,3 +196,7 @@ func (m *mockStore) GetStateSyncProof(stateSyncID uint64) (types.Proof, error) { return ssp, nil } + +func (m *mockStore) FilterExtra(extra []byte) ([]byte, error) { + return extra, nil +} diff --git a/jsonrpc/testsuite/block-empty.json b/jsonrpc/testsuite/block-empty.json index 3c77c97506..55408d0795 100644 --- a/jsonrpc/testsuite/block-empty.json +++ b/jsonrpc/testsuite/block-empty.json @@ -18,5 +18,6 @@ "nonce": "0x0a00000000000000", "hash": "0x0800000000000000000000000000000000000000000000000000000000000000", "transactions": null, - "uncles": null -} \ No newline at end of file + "uncles": null, + "baseFee": "0xf" +} diff --git a/jsonrpc/testsuite/block-with-no-basefee.json b/jsonrpc/testsuite/block-with-no-basefee.json new file mode 100644 index 0000000000..293c7cb582 --- /dev/null +++ b/jsonrpc/testsuite/block-with-no-basefee.json @@ -0,0 +1,22 @@ +{ + "parentHash": "0x0100000000000000000000000000000000000000000000000000000000000000", + "sha3Uncles": "0x0200000000000000000000000000000000000000000000000000000000000000", + "miner": "0x0100000000000000000000000000000000000000", + "stateRoot": "0x0400000000000000000000000000000000000000000000000000000000000000", + "transactionsRoot": "0x0500000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x0600000000000000000000000000000000000000000000000000000000000000", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "difficulty": "0xa", + "totalDifficulty": "0x0", + "size": "0x0", + "number": "0xb", + "gasLimit": "0xc", + "gasUsed": "0xd", + "timestamp": "0xe", + "extraData": "0x616263646566", + "mixHash": "0x0700000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x0a00000000000000", + "hash": "0x0800000000000000000000000000000000000000000000000000000000000000", + "transactions": null, + "uncles": null +} diff --git a/jsonrpc/testsuite/block-with-txn-bodies.json b/jsonrpc/testsuite/block-with-txn-bodies.json index e6435a01af..80fdb4a40b 100644 --- a/jsonrpc/testsuite/block-with-txn-bodies.json +++ b/jsonrpc/testsuite/block-with-txn-bodies.json @@ -32,8 +32,10 @@ "from": "0x0300000000000000000000000000000000000000", "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "blockNumber": "0x1", - "transactionIndex": "0x2" + "transactionIndex": "0x2", + "type": "0x0" } ], - "uncles": null -} \ No newline at end of file + "uncles": null, + "baseFee": "0xf" +} diff --git a/jsonrpc/testsuite/block-with-txn-hashes.json b/jsonrpc/testsuite/block-with-txn-hashes.json index e3cebad1b7..5925537af4 100644 --- a/jsonrpc/testsuite/block-with-txn-hashes.json +++ b/jsonrpc/testsuite/block-with-txn-hashes.json @@ -20,5 +20,6 @@ "transactions": [ "0x0800000000000000000000000000000000000000000000000000000000000000" ], - "uncles": null -} \ No newline at end of file + "uncles": null, + "baseFee": "0xf" +} diff --git a/jsonrpc/testsuite/transaction-eip1559.json b/jsonrpc/testsuite/transaction-eip1559.json new file mode 100644 index 0000000000..33b072339c --- /dev/null +++ b/jsonrpc/testsuite/transaction-eip1559.json @@ -0,0 +1,19 @@ +{ + "nonce": "0x1", + "gasPrice": "0xa", + "gasTipCap": "0xa", + "gasFeeCap": "0xa", + "gas": "0x64", + "to": "0x0000000000000000000000000000000000000000", + "value": "0x3e8", + "input": "0x0102", + "v": "0x1", + "r": "0x2", + "s": "0x3", + "hash": "0x0200000000000000000000000000000000000000000000000000000000000000", + "from": "0x0300000000000000000000000000000000000000", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blockNumber": "0x1", + "transactionIndex": "0x2", + "type": "0x2" +} \ No newline at end of file diff --git a/jsonrpc/testsuite/transaction-pending.json b/jsonrpc/testsuite/transaction-pending.json index ccbbe31fac..f7e0f6de3b 100644 --- a/jsonrpc/testsuite/transaction-pending.json +++ b/jsonrpc/testsuite/transaction-pending.json @@ -12,5 +12,6 @@ "from": "0x0300000000000000000000000000000000000000", "blockHash": null, "blockNumber": null, - "transactionIndex": null + "transactionIndex": null, + "type": "0x0" } \ No newline at end of file diff --git a/jsonrpc/testsuite/transaction-sealed.json b/jsonrpc/testsuite/transaction-sealed.json index 86b238547f..c54be34d8c 100644 --- a/jsonrpc/testsuite/transaction-sealed.json +++ b/jsonrpc/testsuite/transaction-sealed.json @@ -12,5 +12,6 @@ "from": "0x0300000000000000000000000000000000000000", "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "blockNumber": "0x1", - "transactionIndex": "0x2" + "transactionIndex": "0x2", + "type": "0x0" } \ No newline at end of file diff --git a/jsonrpc/txpool_endpoint.go b/jsonrpc/txpool_endpoint.go index f786df059f..0d91a06ec7 100644 --- a/jsonrpc/txpool_endpoint.go +++ b/jsonrpc/txpool_endpoint.go @@ -41,6 +41,8 @@ type StatusResponse struct { type txpoolTransaction struct { Nonce argUint64 `json:"nonce"` GasPrice argBig `json:"gasPrice"` + GasFeeCap *argBig `json:"gasFeeCap,omitempty"` + GasTipCap *argBig `json:"gasTipCap,omitempty"` Gas argUint64 `json:"gas"` To *types.Address `json:"to"` Value argBig `json:"value"` @@ -53,9 +55,23 @@ type txpoolTransaction struct { } func toTxPoolTransaction(t *types.Transaction) *txpoolTransaction { + var gasTipCap, gasFeeCap *argBig + + if t.GasTipCap != nil { + gasTipCapVal := argBig(*t.GasTipCap) + gasTipCap = &gasTipCapVal + } + + if t.GasFeeCap != nil { + gasFeeCapVal := argBig(*t.GasFeeCap) + gasFeeCap = &gasFeeCapVal + } + return &txpoolTransaction{ Nonce: argUint64(t.Nonce), GasPrice: argBig(*t.GasPrice), + GasFeeCap: gasFeeCap, + GasTipCap: gasTipCap, Gas: argUint64(t.Gas), To: t.To, Value: argBig(*t.Value), diff --git a/jsonrpc/types.go b/jsonrpc/types.go index e09bb89327..2e2a5e3f57 100644 --- a/jsonrpc/types.go +++ b/jsonrpc/types.go @@ -9,6 +9,8 @@ import ( "github.com/0xPolygon/polygon-edge/types" ) +const jsonRPCMetric = "json_rpc" + // For union type of transaction and types.Hash type transactionOrHash interface { getHash() types.Hash @@ -17,6 +19,8 @@ type transactionOrHash interface { type transaction struct { Nonce argUint64 `json:"nonce"` GasPrice argBig `json:"gasPrice"` + GasTipCap *argBig `json:"gasTipCap,omitempty"` + GasFeeCap *argBig `json:"gasFeeCap,omitempty"` Gas argUint64 `json:"gas"` To *types.Address `json:"to"` Value argBig `json:"value"` @@ -29,6 +33,7 @@ type transaction struct { BlockHash *types.Hash `json:"blockHash"` BlockNumber *argUint64 `json:"blockNumber"` TxIndex *argUint64 `json:"transactionIndex"` + Type argUint64 `json:"type"` } func (t transaction) getHash() types.Hash { return t.Hash } @@ -64,6 +69,17 @@ func toTransaction( S: argBig(*t.S), Hash: t.Hash, From: t.From, + Type: argUint64(t.Type), + } + + if t.GasTipCap != nil { + gasTipCap := argBig(*t.GasTipCap) + res.GasTipCap = &gasTipCap + } + + if t.GasFeeCap != nil { + gasFeeCap := argBig(*t.GasFeeCap) + res.GasFeeCap = &gasFeeCap } if blockNumber != nil { @@ -102,6 +118,7 @@ type block struct { Hash types.Hash `json:"hash"` Transactions []transactionOrHash `json:"transactions"` Uncles []types.Hash `json:"uncles"` + BaseFee argUint64 `json:"baseFee,omitempty"` } func (b *block) Copy() *block { @@ -140,6 +157,7 @@ func toBlock(b *types.Block, fullTx bool) *block { Hash: h.Hash, Transactions: []transactionOrHash{}, Uncles: []types.Hash{}, + BaseFee: argUint64(h.BaseFee), } for idx, txn := range b.Transactions { @@ -307,14 +325,17 @@ func encodeToHex(b []byte) []byte { // txnArgs is the transaction argument for the rpc endpoints type txnArgs struct { - From *types.Address - To *types.Address - Gas *argUint64 - GasPrice *argBytes - Value *argBytes - Data *argBytes - Input *argBytes - Nonce *argUint64 + From *types.Address + To *types.Address + Gas *argUint64 + GasPrice *argBytes + GasTipCap *argBytes + GasFeeCap *argBytes + Value *argBytes + Data *argBytes + Input *argBytes + Nonce *argUint64 + Type *argUint64 } type progression struct { diff --git a/jsonrpc/types_test.go b/jsonrpc/types_test.go index a3958c9c8e..3f2ef341ee 100644 --- a/jsonrpc/types_test.go +++ b/jsonrpc/types_test.go @@ -143,64 +143,64 @@ func TestBlock_Copy(t *testing.T) { var testsuite embed.FS func TestBlock_Encoding(t *testing.T) { - b := block{ - ParentHash: types.Hash{0x1}, - Sha3Uncles: types.Hash{0x2}, - Miner: types.Address{0x1}.Bytes(), - StateRoot: types.Hash{0x4}, - TxRoot: types.Hash{0x5}, - ReceiptsRoot: types.Hash{0x6}, - LogsBloom: types.Bloom{0x0}, - Difficulty: 10, - Number: 11, - GasLimit: 12, - GasUsed: 13, - Timestamp: 14, - ExtraData: []byte{97, 98, 99, 100, 101, 102}, - MixHash: types.Hash{0x7}, - Nonce: types.Nonce{10}, - Hash: types.Hash{0x8}, + getBlock := func() block { + return block{ + ParentHash: types.Hash{0x1}, + Sha3Uncles: types.Hash{0x2}, + Miner: types.Address{0x1}.Bytes(), + StateRoot: types.Hash{0x4}, + TxRoot: types.Hash{0x5}, + ReceiptsRoot: types.Hash{0x6}, + LogsBloom: types.Bloom{0x0}, + Difficulty: 10, + Number: 11, + GasLimit: 12, + GasUsed: 13, + Timestamp: 14, + ExtraData: []byte{97, 98, 99, 100, 101, 102}, + MixHash: types.Hash{0x7}, + Nonce: types.Nonce{10}, + Hash: types.Hash{0x8}, + BaseFee: 15, + } } - testBlock := func(name string) { + testBlock := func(name string, b block) { res, err := json.Marshal(b) require.NoError(t, err) data, err := testsuite.ReadFile(name) require.NoError(t, err) - - data = removeWhiteSpace(data) - require.Equal(t, res, data) + require.JSONEq(t, string(data), string(res)) } t.Run("empty block", func(t *testing.T) { - testBlock("testsuite/block-empty.json") + testBlock("testsuite/block-empty.json", getBlock()) + }) + + t.Run("block with no base fee", func(t *testing.T) { + b := getBlock() + b.BaseFee = 0 + testBlock("testsuite/block-with-no-basefee.json", b) }) t.Run("block with transaction hashes", func(t *testing.T) { + b := getBlock() b.Transactions = []transactionOrHash{ transactionHash{0x8}, } - testBlock("testsuite/block-with-txn-hashes.json") + testBlock("testsuite/block-with-txn-hashes.json", b) }) t.Run("block with transaction bodies", func(t *testing.T) { + b := getBlock() b.Transactions = []transactionOrHash{ mockTxn(), } - testBlock("testsuite/block-with-txn-bodies.json") + testBlock("testsuite/block-with-txn-bodies.json", b) }) } -func removeWhiteSpace(d []byte) []byte { - s := string(d) - s = strings.Replace(s, "\n", "", -1) - s = strings.Replace(s, "\t", "", -1) - s = strings.Replace(s, " ", "", -1) - - return []byte(s) -} - func mockTxn() *transaction { to := types.Address{} @@ -219,34 +219,46 @@ func mockTxn() *transaction { BlockHash: &types.ZeroHash, BlockNumber: argUintPtr(1), TxIndex: argUintPtr(2), + Type: argUint64(types.LegacyTx), } return tt } func TestTransaction_Encoding(t *testing.T) { - tt := mockTxn() - - testTransaction := func(name string) { + testTransaction := func(name string, tt *transaction) { res, err := json.Marshal(tt) require.NoError(t, err) data, err := testsuite.ReadFile(name) require.NoError(t, err) - - data = removeWhiteSpace(data) - require.Equal(t, res, data) + require.JSONEq(t, string(data), string(res)) } t.Run("sealed", func(t *testing.T) { - testTransaction("testsuite/transaction-sealed.json") + tt := mockTxn() + + testTransaction("testsuite/transaction-sealed.json", tt) }) t.Run("pending", func(t *testing.T) { + tt := mockTxn() tt.BlockHash = nil tt.BlockNumber = nil tt.TxIndex = nil - testTransaction("testsuite/transaction-pending.json") + testTransaction("testsuite/transaction-pending.json", tt) + }) + + t.Run("eip-1559", func(t *testing.T) { + gasTipCap := argBig(*big.NewInt(10)) + gasFeeCap := argBig(*big.NewInt(10)) + + tt := mockTxn() + tt.GasTipCap = &gasTipCap + tt.GasFeeCap = &gasFeeCap + tt.Type = argUint64(types.DynamicFeeTx) + + testTransaction("testsuite/transaction-eip1559.json", tt) }) } diff --git a/network/gossip.go b/network/gossip.go index b044949515..562bb46682 100644 --- a/network/gossip.go +++ b/network/gossip.go @@ -4,8 +4,10 @@ import ( "context" "errors" "reflect" + "sync" "sync/atomic" + "github.com/armon/go-metrics" "github.com/hashicorp/go-hclog" pubsub "github.com/libp2p/go-libp2p-pubsub" "github.com/libp2p/go-libp2p/core/peer" @@ -22,10 +24,11 @@ const ( type Topic struct { logger hclog.Logger - topic *pubsub.Topic - typ reflect.Type - closeCh chan struct{} - closed *uint64 + topic *pubsub.Topic + typ reflect.Type + closeCh chan struct{} + closed atomic.Bool + waitGroup sync.WaitGroup } func (t *Topic) createObj() proto.Message { @@ -38,17 +41,19 @@ func (t *Topic) createObj() proto.Message { } func (t *Topic) Close() { - if atomic.SwapUint64(t.closed, 1) > 0 { + if t.closed.Swap(true) { // Already closed. return } + close(t.closeCh) // close all subscribers + t.waitGroup.Wait() // wait for all the subscribers to finish + + // if all subscribers are finished, close the topic if t.topic != nil { t.topic.Close() t.topic = nil } - - close(t.closeCh) } func (t *Topic) Publish(obj proto.Message) error { @@ -57,6 +62,8 @@ func (t *Topic) Publish(obj proto.Message) error { return err } + metrics.SetGauge([]string{networkMetrics, "egress_bytes"}, float32(len(data))) + return t.topic.Publish(context.Background(), data) } @@ -67,7 +74,7 @@ func (t *Topic) Subscribe(handler func(obj interface{}, from peer.ID)) error { } // Mark topic active. - atomic.StoreUint64(t.closed, 0) + t.closed.Store(false) go t.readLoop(sub, handler) @@ -75,6 +82,9 @@ func (t *Topic) Subscribe(handler func(obj interface{}, from peer.ID)) error { } func (t *Topic) readLoop(sub *pubsub.Subscription, handler func(obj interface{}, from peer.ID)) { + t.waitGroup.Add(1) + defer t.waitGroup.Done() + ctx, cancelFn := context.WithCancel(context.Background()) go func() { @@ -91,6 +101,7 @@ func (t *Topic) readLoop(sub *pubsub.Subscription, handler func(obj interface{}, } t.logger.Error("failed to get topic", "err", err) + metrics.IncrCounter([]string{networkMetrics, "bad_messages"}, float32(1)) continue } @@ -99,10 +110,13 @@ func (t *Topic) readLoop(sub *pubsub.Subscription, handler func(obj interface{}, obj := t.createObj() if err := proto.Unmarshal(msg.Data, obj); err != nil { t.logger.Error("failed to unmarshal topic", "err", err) + metrics.IncrCounter([]string{networkMetrics, "bad_messages"}, float32(1)) return } + metrics.SetGauge([]string{networkMetrics, "ingress_bytes"}, float32(len(msg.Data))) + handler(obj, msg.GetFrom()) }() } @@ -119,8 +133,8 @@ func (s *Server) NewTopic(protoID string, obj proto.Message) (*Topic, error) { topic: topic, typ: reflect.TypeOf(obj).Elem(), closeCh: make(chan struct{}), - closed: new(uint64), } + tt.closed.Store(false) return tt, nil } diff --git a/network/gossip_test.go b/network/gossip_test.go index 57dd16c224..9655c7762d 100644 --- a/network/gossip_test.go +++ b/network/gossip_test.go @@ -111,7 +111,6 @@ func TestSimpleGossip(t *testing.T) { func Test_RepeatedClose(t *testing.T) { topic := &Topic{ closeCh: make(chan struct{}), - closed: new(uint64), } // Call Close() twice to ensure that underlying logic (e.g. channel close) is diff --git a/network/server.go b/network/server.go index 081bfcc061..b6be58f3a4 100644 --- a/network/server.go +++ b/network/server.go @@ -400,7 +400,7 @@ func (s *Server) runDial() { //nolint:godox // TODO: Right now the dial task are done sequentially because Connect // is a blocking request. In the future we should try to make up to - // maxDials requests concurrently (to be fixed in EVM-541) + // maxDials requests concurrently (to be fixed in EVM-543) for s.connectionCounts.HasFreeOutboundConn() { tt := s.dialQueue.PopTask() if tt == nil { @@ -473,7 +473,12 @@ func (s *Server) IsConnected(peerID peer.ID) bool { // GetProtocols fetches the list of node-supported protocols func (s *Server) GetProtocols(peerID peer.ID) ([]string, error) { - return s.host.Peerstore().GetProtocols(peerID) + protocols, err := s.host.Peerstore().GetProtocols(peerID) + if err != nil { + return nil, err + } + + return protocol.ConvertToStrings(protocols), nil } // removePeer removes a peer from the networking server's peer list, diff --git a/network/server_discovery.go b/network/server_discovery.go index 26d17f3da5..09f8c4fdee 100644 --- a/network/server_discovery.go +++ b/network/server_discovery.go @@ -206,8 +206,11 @@ func (s *Server) setupDiscovery() error { // Set the PeerAdded event handler routingTable.PeerAdded = func(p peer.ID) { - info := s.host.Peerstore().PeerInfo(p) - s.addToDialQueue(&info, common.PriorityRandomDial) + // this is called from the lock. because of that execute addToDialQueue on separated routine + go func() { + info := s.host.Peerstore().PeerInfo(p) + s.addToDialQueue(&info, common.PriorityRandomDial) + }() } // Set the PeerRemoved event handler diff --git a/network/server_identity.go b/network/server_identity.go index c1c5541ee3..27ed6bc9a7 100644 --- a/network/server_identity.go +++ b/network/server_identity.go @@ -42,8 +42,6 @@ func (s *Server) AddPeer(id peer.ID, direction network.Direction) { // Emit the event alerting listeners // WARNING: THIS CALL IS POTENTIALLY BLOCKING - // UNDER HEAVY LOAD. IT SHOULD BE SUBSTITUTED - // WITH AN EVENT SYSTEM THAT ACTUALLY WORKS s.emitEvent(id, peerEvent.PeerConnected) } diff --git a/network/server_test.go b/network/server_test.go index 62badbd85f..5d9ed1fd7e 100644 --- a/network/server_test.go +++ b/network/server_test.go @@ -608,6 +608,7 @@ func TestSelfConnection_WithBootNodes(t *testing.T) { } func TestRunDial(t *testing.T) { + t.Skip() // setupServers returns server and list of peer's server setupServers := func(t *testing.T, maxPeers []int64) []*Server { t.Helper() @@ -1025,13 +1026,7 @@ func TestPeerAdditionDeletion(t *testing.T) { } t.Run("peers are added correctly", func(t *testing.T) { - server := createServer() - - //nolint:godox - // TODO increase this number to something astronomical - // when the networking package has an event system that actually works, - // as emitEvent can completely bug out when under load inside Server.AddPeer (to be fixed in EVM-525) - generateAndAddPeers(server, 10) + generateAndAddPeers(createServer(), 2500) }) t.Run("no duplicate peers added", func(t *testing.T) { diff --git a/scripts/README.md b/scripts/README.md index bfda08cc3f..0599d0832a 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -1,10 +1,12 @@ -# Run servers form local binary +# Run servers from local binary ## Prerequisites When deploying with `polybft` consensus, there are some additional dependencies: * [npm](https://nodejs.org/en/) -* [go 1.18.x](https://go.dev/dl/) +* [go 1.20.x](https://go.dev/dl/) +* [jq](https://jqlang.github.io/jq) +* Netcat (nc) ## Local development Running `polygon-edge` from local binary can be done very easily by using provided `scripts` folder. @@ -33,4 +35,4 @@ To do that simply run `make download-submodules`. ### Production This is **NOT** a production ready deployment. It is to be used in *development* / *test* environments only. -For production usage, please check out the official [docs](https://wiki.polygon.technology/docs/edge/overview/). \ No newline at end of file +For production usage, please check out the official [docs](https://wiki.polygon.technology/docs/edge/overview/). diff --git a/scripts/cluster b/scripts/cluster index 149fdfb6ab..df005c31f9 100755 --- a/scripts/cluster +++ b/scripts/cluster @@ -1,29 +1,132 @@ #!/usr/bin/env bash +dp_error_flag=0 + +# Check if jq is installed +if [[ "$1" == "polybft" ]] && ! command -v jq >/dev/null 2>&1; then + echo "jq is not installed." + echo "Manual installation instructions: Visit https://jqlang.github.io/jq/ for more information." + dp_error_flag=1 +fi + +# Check if nc is installed +if [[ "$1" == "polybft" ]] && ! command -v nc >/dev/null 2>&1; then + echo "Netcat (nc) is not installed." + dp_error_flag=1 +fi + +# Stop script if any of the dependencies have failed +if [[ "$dp_error_flag" -eq 1]]; then + echo "Missing dependencies. Please install them and run the script again." + exit 1 +fi + function initIbftConsensus() { - echo "Running with ibft consensus" - ./polygon-edge secrets init --insecure --data-dir test-chain- --num 4 + echo "Running with ibft consensus" + ./polygon-edge secrets init --insecure --data-dir test-chain- --num 4 - node1_id=$(./polygon-edge secrets output --data-dir test-chain-1 | grep Node | head -n 1 | awk -F ' ' '{print $4}') - node2_id=$(./polygon-edge secrets output --data-dir test-chain-2 | grep Node | head -n 1 | awk -F ' ' '{print $4}') + node1_id=$(./polygon-edge secrets output --data-dir test-chain-1 | grep Node | head -n 1 | awk -F ' ' '{print $4}') + node2_id=$(./polygon-edge secrets output --data-dir test-chain-2 | grep Node | head -n 1 | awk -F ' ' '{print $4}') - genesis_params="--consensus ibft --ibft-validators-prefix-path test-chain- \ + genesis_params="--consensus ibft --ibft-validators-prefix-path test-chain- \ --bootnode /ip4/127.0.0.1/tcp/30301/p2p/$node1_id \ --bootnode /ip4/127.0.0.1/tcp/30302/p2p/$node2_id" } function initPolybftConsensus() { - echo "Running with polybft consensus" - genesis_params="--consensus polybft --validator-set-size=4 --bridge-json-rpc http://127.0.0.1:8545" - ./polygon-edge polybft-secrets --insecure --data-dir test-chain- --num 4 - ./polygon-edge manifest + echo "Running with polybft consensus" + genesis_params="--consensus polybft" + + address1=$(./polygon-edge polybft-secrets --insecure --data-dir test-chain-1 | grep Public | head -n 1 | awk -F ' ' '{print $5}') + address2=$(./polygon-edge polybft-secrets --insecure --data-dir test-chain-2 | grep Public | head -n 1 | awk -F ' ' '{print $5}') + address3=$(./polygon-edge polybft-secrets --insecure --data-dir test-chain-3 | grep Public | head -n 1 | awk -F ' ' '{print $5}') + address4=$(./polygon-edge polybft-secrets --insecure --data-dir test-chain-4 | grep Public | head -n 1 | awk -F ' ' '{print $5}') } function createGenesis() { - ./polygon-edge genesis $genesis_params \ - --block-gas-limit 10000000 \ - --premine 0x85da99c8a7c2c95964c8efd687e95e632fc533d6:1000000000000000000000 \ - --epoch-size 10 + ./polygon-edge genesis $genesis_params \ + --block-gas-limit 10000000 \ + --premine 0x85da99c8a7c2c95964c8efd687e95e632fc533d6:1000000000000000000000 \ + --premine 0x0000000000000000000000000000000000000000 \ + --epoch-size 10 \ + --reward-wallet 0xDEADBEEF:1000000 \ + --native-token-config "Polygon:MATIC:18:true:$address1" \ + --burn-contract 0:0x0000000000000000000000000000000000000000 +} + +function initRootchain() { + echo "Initializing rootchain" + + if [ "$1" == "write-logs" ]; then + echo "Writing rootchain server logs to the file..." + ./polygon-edge rootchain server 2>&1 | tee ./rootchain-server.log & + else + ./polygon-edge rootchain server >/dev/null & + fi + + set +e + t=1 + while [ $t -gt 0 ]; do + nc -z 127.0.0.1 8545 &1 | tee ./validator-4.log & - wait + wait else ./polygon-edge server --data-dir ./test-chain-1 --chain genesis.json \ --grpc-address :10000 --libp2p :30301 --jsonrpc :10002 \ @@ -55,29 +158,25 @@ function startServerFromBinary() { ./polygon-edge server --data-dir ./test-chain-4 --chain genesis.json \ --grpc-address :40000 --libp2p :30304 --jsonrpc :40002 \ --num-block-confirmations 2 --seal --log-level DEBUG & - wait + wait fi } function startServerFromDockerCompose() { - case "$1" in - "ibft") - docker-compose -f ./docker/local/docker-compose.yml up -d --build - ;; - "polybft") - cd core-contracts && npm install && npm run compile && cd - - go run ./consensus/polybft/contractsapi/artifacts-gen/main.go - EDGE_CONSENSUS=polybft docker-compose -f ./docker/local/docker-compose.yml up -d --build - ;; - esac + if [ "$1" != "polybft" ] + then + export EDGE_CONSENSUS="$1" + fi + + docker-compose -f ./docker/local/docker-compose.yml up -d --build } function destroyDockerEnvironment() { - docker-compose -f ./docker/local/docker-compose.yml down -v + docker-compose -f ./docker/local/docker-compose.yml down -v } function stopDockerEnvironment() { - docker-compose -f ./docker/local/docker-compose.yml stop + docker-compose -f ./docker/local/docker-compose.yml stop } set -e @@ -85,53 +184,53 @@ set -e # Reset test-dirs rm -rf test-chain-* rm -f genesis.json -rm -f manifest.json # Build binary go build -o polygon-edge . # If --docker flag is set run docker environment otherwise run from binary case "$2" in - "--docker") - # cluster {consensus} --docker destroy - if [ "$3" == "destroy" ]; then - destroyDockerEnvironment - echo "Docker $1 environment destroyed!" - exit 0 - # cluster {consensus} --docker stop - elif [ "$3" == "stop" ]; then - stopDockerEnvironment - echo "Docker $1 environment stoped!" - exit 0; - fi - - # cluster {consensus} --docker - echo "Running $1 docker environment..." - startServerFromDockerCompose $1 - echo "Docker $1 environment deployed." +"--docker") + # cluster {consensus} --docker destroy + if [ "$3" == "destroy" ]; then + destroyDockerEnvironment + echo "Docker $1 environment destroyed!" exit 0 - ;; - # cluster {consensus} - *) - echo "Running $1 environment from local binary..." - # Initialize ibft or polybft consensus - if [ "$1" == "ibft" ]; then - # Initialize ibft consensus - initIbftConsensus - # Create genesis file and start the server from binary - createGenesis - startServerFromBinary $2 - exit 0; - elif [ "$1" == "polybft" ]; then - # Initialize polybft consensus - initPolybftConsensus - # Create genesis file and start the server from binary - createGenesis - startServerFromBinary $2 - exit 0; - else - echo "Unsupported consensus mode. Supported modes are: ibft and polybft " - exit 1; - fi + # cluster {consensus} --docker stop + elif [ "$3" == "stop" ]; then + stopDockerEnvironment + echo "Docker $1 environment stoped!" + exit 0 + fi + + # cluster {consensus} --docker + echo "Running $1 docker environment..." + startServerFromDockerCompose $1 + echo "Docker $1 environment deployed." + exit 0 + ;; +# cluster {consensus} +*) + echo "Running $1 environment from local binary..." + # Initialize ibft or polybft consensus + if [ "$1" == "ibft" ]; then + # Initialize ibft consensus + initIbftConsensus + # Create genesis file and start the server from binary + createGenesis + startServerFromBinary $2 + exit 0 + elif [ "$1" == "polybft" ]; then + # Initialize polybft consensus + initPolybftConsensus + # Create genesis file and start the server from binary + createGenesis + initRootchain $2 + startServerFromBinary $2 + exit 0 + else + echo "Unsupported consensus mode. Supported modes are: ibft and polybft " + exit 1 + fi ;; esac diff --git a/scripts/fuzzAll b/scripts/fuzzAll new file mode 100755 index 0000000000..ece67fb600 --- /dev/null +++ b/scripts/fuzzAll @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e + +fuzzTime=${1:-10} + +files=$(grep -r --include='**_test.go' --files-with-matches 'func Fuzz' .) + +for file in ${files} +do + funcs=$(grep -o 'func Fuzz\w*' $file | sed 's/func //') + for func in ${funcs} + do + echo "Fuzzing $func in $file" + parentDir=$(dirname $file) + go test $parentDir -run=$func -fuzz=$func -fuzztime=${fuzzTime}s + done +done diff --git a/secrets/awsssm/aws_ssm.go b/secrets/awsssm/aws_ssm.go index 51d444f03b..c7661e6a14 100644 --- a/secrets/awsssm/aws_ssm.go +++ b/secrets/awsssm/aws_ssm.go @@ -20,6 +20,9 @@ type AwsSsmManager struct { // The AWS region region string + // Custom AWS endpoint, e.g. localstack + endpoint string + // The AWS SSM client client *ssm.SSM @@ -44,8 +47,9 @@ func SecretsManagerFactory( // / Set up the base object awsSsmManager := &AwsSsmManager{ - logger: params.Logger.Named(string(secrets.AWSSSM)), - region: fmt.Sprintf("%v", config.Extra["region"]), + logger: params.Logger.Named(string(secrets.AWSSSM)), + region: fmt.Sprintf("%v", config.Extra["region"]), + endpoint: config.ServerURL, } // Set the base path to store the secrets in SSM @@ -61,15 +65,20 @@ func SecretsManagerFactory( // Setup sets up the AWS SSM secrets manager func (a *AwsSsmManager) Setup() error { + cfg := aws.NewConfig().WithRegion(a.region) + if a.endpoint != "" { + cfg = cfg.WithEndpoint(a.endpoint) + } + sess, err := session.NewSessionWithOptions(session.Options{ - Config: aws.Config{Region: aws.String(a.region)}, + Config: *cfg, SharedConfigState: session.SharedConfigEnable, }) if err != nil { return fmt.Errorf("unable to initialize AWS SSM client: %w", err) } - ssmsvc := ssm.New(sess, aws.NewConfig().WithRegion(a.region)) + ssmsvc := ssm.New(sess, cfg) a.client = ssmsvc return nil diff --git a/secrets/helper/helper.go b/secrets/helper/helper.go index 5d525c98f4..5217639af0 100644 --- a/secrets/helper/helper.go +++ b/secrets/helper/helper.go @@ -3,10 +3,7 @@ package helper import ( "errors" "fmt" - "math/big" - bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" - "github.com/0xPolygon/polygon-edge/consensus/polybft/wallet" "github.com/0xPolygon/polygon-edge/crypto" "github.com/0xPolygon/polygon-edge/helper/hex" "github.com/0xPolygon/polygon-edge/network" @@ -22,6 +19,8 @@ import ( "github.com/umbracle/ethgo/abi" ) +var addressTypeABI = abi.MustNewType("address") + // SetupLocalSecretsManager is a helper method for boilerplate local secrets manager setup func SetupLocalSecretsManager(dataDir string) (secrets.SecretsManager, error) { return local.SecretsManagerFactory( @@ -143,39 +142,6 @@ func InitNetworkingPrivateKey(secretsManager secrets.SecretsManager) (libp2pCryp return libp2pKey, keyErr } -func InitValidatorBLSSignature( - secretsManager secrets.SecretsManager, account *wallet.Account, chainID int64) ([]byte, error) { - if secretsManager.HasSecret(secrets.ValidatorBLSSignature) { - return nil, fmt.Errorf(`secrets "%s" has been already initialized`, secrets.ValidatorBLSSignature) - } - - // Generate the signature - s, err := MakeKOSKSignature( - account.Bls, - types.Address(account.Ecdsa.Address()), - chainID, - bls.DomainValidatorSet, - ) - if err != nil { - return nil, err - } - - sb, err := s.Marshal() - if err != nil { - return nil, err - } - - // Write the signature to the secrets manager storage - if err := secretsManager.SetSecret( - secrets.ValidatorBLSSignature, - []byte(hex.EncodeToString(sb)), - ); err != nil { - return nil, err - } - - return sb, nil -} - // LoadValidatorAddress loads ECDSA key by SecretsManager and returns validator address func LoadValidatorAddress(secretsManager secrets.SecretsManager) (types.Address, error) { if !secretsManager.HasSecret(secrets.ValidatorKey) { @@ -243,17 +209,6 @@ func LoadNodeID(secretsManager secrets.SecretsManager) (string, error) { return nodeID.String(), nil } -// LoadBLSSignature loads BLS Signature from SecretsManager and returns it -func LoadBLSSignature(secretsManager secrets.SecretsManager) (string, error) { - if !secretsManager.HasSecret(secrets.ValidatorBLSSignature) { - return "", nil - } - - s, err := secretsManager.GetSecret(secrets.ValidatorBLSSignature) - - return string(s), err -} - // InitCloudSecretsManager returns the cloud secrets manager from the provided config func InitCloudSecretsManager(secretsConfig *secrets.SecretsManagerConfig) (secrets.SecretsManager, error) { var secretsManager secrets.SecretsManager @@ -286,17 +241,3 @@ func InitCloudSecretsManager(secretsConfig *secrets.SecretsManagerConfig) (secre return secretsManager, nil } - -// MakeKOSKSignature creates KOSK signature which prevents rogue attack -func MakeKOSKSignature( - privateKey *bls.PrivateKey, address types.Address, chainID int64, domain []byte) (*bls.Signature, error) { - message, err := abi.Encode( - []interface{}{address, big.NewInt(chainID)}, - abi.MustNewType("tuple(address, uint256)")) - if err != nil { - return nil, err - } - - // abi.Encode adds 12 zero bytes before actual address bytes - return privateKey.Sign(message[12:], domain) -} diff --git a/secrets/helper/helper_test.go b/secrets/helper/helper_test.go deleted file mode 100644 index 189e082f7a..0000000000 --- a/secrets/helper/helper_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package helper - -import ( - "testing" - - bls "github.com/0xPolygon/polygon-edge/consensus/polybft/signer" - "github.com/0xPolygon/polygon-edge/helper/hex" - "github.com/0xPolygon/polygon-edge/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_MakeKOSKSignature(t *testing.T) { - t.Parallel() - - expected := "127cfb8e2512b447056f33b91fca6cb2a7039e8b330edc4e5e5287f1c58bba5206373a97c9f09db144c8db5681c39e013ee6039ebbe36e0448e9f704f2d326c0" - bytes, _ := hex.DecodeString("3139343634393730313533353434353137333331343333303931343932303731313035313730303336303738373134363131303435323837383335373237343933383834303135343336383231") - - pk, err := bls.UnmarshalPrivateKey(bytes) - require.NoError(t, err) - - address := types.BytesToAddress((pk.PublicKey().Marshal())[:types.AddressLength]) - - signature, err := MakeKOSKSignature(pk, address, 10, bls.DomainValidatorSet) - require.NoError(t, err) - - signatureBytes, err := signature.Marshal() - require.NoError(t, err) - - assert.Equal(t, expected, hex.EncodeToString(signatureBytes)) - - signature, err = MakeKOSKSignature(pk, address, 100, bls.DomainValidatorSet) - require.NoError(t, err) - - signatureBytes, err = signature.Marshal() - require.NoError(t, err) - - assert.NotEqual(t, expected, hex.EncodeToString(signatureBytes)) -} diff --git a/secrets/local/local.go b/secrets/local/local.go index dcf44de407..2a08d1a36d 100644 --- a/secrets/local/local.go +++ b/secrets/local/local.go @@ -84,13 +84,6 @@ func (l *LocalSecretsManager) Setup() error { secrets.ValidatorBLSKeyLocal, ) - // baseDir/consensus/validator.sig - l.secretPathMap[secrets.ValidatorBLSSignature] = filepath.Join( - l.path, - secrets.ConsensusFolderLocal, - secrets.ValidatorBLSSignatureLocal, - ) - // baseDir/libp2p/libp2p.key l.secretPathMap[secrets.NetworkKey] = filepath.Join( l.path, diff --git a/secrets/secrets.go b/secrets/secrets.go index d9a9c9070b..4dcd30205e 100644 --- a/secrets/secrets.go +++ b/secrets/secrets.go @@ -31,17 +31,13 @@ const ( // NetworkKey is the libp2p private key secret used for networking NetworkKey = "network-key" - - // ValidatorBLSSignature is the BLS signature of the validator node - ValidatorBLSSignature = "validator-bls-signature" ) // Define constant file names for the local StorageManager const ( - ValidatorKeyLocal = "validator.key" - ValidatorBLSKeyLocal = "validator-bls.key" - NetworkKeyLocal = "libp2p.key" - ValidatorBLSSignatureLocal = "validator.sig" + ValidatorKeyLocal = "validator.key" + ValidatorBLSKeyLocal = "validator-bls.key" + NetworkKeyLocal = "libp2p.key" ) // Define constant folder names for the local StorageManager diff --git a/server/builtin.go b/server/builtin.go index 8aa7a49c80..f98c2a4eb4 100644 --- a/server/builtin.go +++ b/server/builtin.go @@ -19,10 +19,14 @@ type GenesisFactoryHook func(config *chain.Chain, engineName string) func(*state type ConsensusType string +type ForkManagerFactory func(forks *chain.Forks) error + +type ForkManagerInitialParamsFactory func(config *chain.Chain) (*chain.ForkParams, error) + const ( DevConsensus ConsensusType = "dev" IBFTConsensus ConsensusType = "ibft" - PolyBFTConsensus ConsensusType = "polybft" + PolyBFTConsensus ConsensusType = consensusPolyBFT.ConsensusName DummyConsensus ConsensusType = "dummy" ) @@ -46,6 +50,14 @@ var genesisCreationFactory = map[ConsensusType]GenesisFactoryHook{ PolyBFTConsensus: consensusPolyBFT.GenesisPostHookFactory, } +var forkManagerFactory = map[ConsensusType]ForkManagerFactory{ + PolyBFTConsensus: consensusPolyBFT.ForkManagerFactory, +} + +var forkManagerInitialParamsFactory = map[ConsensusType]ForkManagerInitialParamsFactory{ + PolyBFTConsensus: consensusPolyBFT.ForkManagerInitialParamsFactory, +} + func ConsensusSupported(value string) bool { _, ok := consensusBackends[ConsensusType(value)] diff --git a/server/config.go b/server/config.go index 21ecf0fe4b..f7832ebf9b 100644 --- a/server/config.go +++ b/server/config.go @@ -24,7 +24,6 @@ type Config struct { PriceLimit uint64 MaxAccountEnqueued uint64 MaxSlots uint64 - BlockTime uint64 Telemetry *Telemetry Network *network.Config diff --git a/server/server.go b/server/server.go index 5bdb641040..e4a176217a 100644 --- a/server/server.go +++ b/server/server.go @@ -2,6 +2,7 @@ package server import ( "context" + "encoding/json" "errors" "fmt" "math/big" @@ -15,6 +16,8 @@ import ( "github.com/0xPolygon/polygon-edge/blockchain/storage/leveldb" "github.com/0xPolygon/polygon-edge/blockchain/storage/memory" consensusPolyBFT "github.com/0xPolygon/polygon-edge/consensus/polybft" + "github.com/0xPolygon/polygon-edge/forkmanager" + "github.com/0xPolygon/polygon-edge/gasprice" "github.com/0xPolygon/polygon-edge/archive" "github.com/0xPolygon/polygon-edge/blockchain" @@ -25,7 +28,6 @@ import ( "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/crypto" "github.com/0xPolygon/polygon-edge/helper/common" - configHelper "github.com/0xPolygon/polygon-edge/helper/config" "github.com/0xPolygon/polygon-edge/helper/progress" "github.com/0xPolygon/polygon-edge/jsonrpc" "github.com/0xPolygon/polygon-edge/network" @@ -34,7 +36,7 @@ import ( "github.com/0xPolygon/polygon-edge/state" itrie "github.com/0xPolygon/polygon-edge/state/immutable-trie" "github.com/0xPolygon/polygon-edge/state/runtime" - "github.com/0xPolygon/polygon-edge/state/runtime/allowlist" + "github.com/0xPolygon/polygon-edge/state/runtime/addresslist" "github.com/0xPolygon/polygon-edge/state/runtime/tracer" "github.com/0xPolygon/polygon-edge/txpool" "github.com/0xPolygon/polygon-edge/types" @@ -46,6 +48,11 @@ import ( "google.golang.org/grpc" ) +var ( + errBlockTimeMissing = errors.New("block time configuration is missing") + errBlockTimeInvalid = errors.New("block time configuration is invalid") +) + // Server is the central manager of the blockchain client type Server struct { logger hclog.Logger @@ -84,6 +91,9 @@ type Server struct { // stateSyncRelayer is handling state syncs execution (Polybft exclusive) stateSyncRelayer *statesyncrelayer.StateSyncRelayer + + // gasHelper is providing functions regarding gas and fees + gasHelper *gasprice.GasHelper } // newFileLogger returns logger instance that writes all logs to a specified file. @@ -206,12 +216,42 @@ func NewServer(config *Config) (*Server, error) { m.executor.GenesisPostHook = factory(m.config.Chain, engineName) } - // apply allow list genesis data + // apply allow list contracts deployer genesis data if m.config.Chain.Params.ContractDeployerAllowList != nil { - allowlist.ApplyGenesisAllocs(m.config.Chain.Genesis, contracts.AllowListContractsAddr, + addresslist.ApplyGenesisAllocs(m.config.Chain.Genesis, contracts.AllowListContractsAddr, m.config.Chain.Params.ContractDeployerAllowList) } + // apply block list contracts deployer genesis data + if m.config.Chain.Params.ContractDeployerBlockList != nil { + addresslist.ApplyGenesisAllocs(m.config.Chain.Genesis, contracts.BlockListContractsAddr, + m.config.Chain.Params.ContractDeployerBlockList) + } + + // apply transactions execution allow list genesis data + if m.config.Chain.Params.TransactionsAllowList != nil { + addresslist.ApplyGenesisAllocs(m.config.Chain.Genesis, contracts.AllowListTransactionsAddr, + m.config.Chain.Params.TransactionsAllowList) + } + + // apply transactions execution block list genesis data + if m.config.Chain.Params.TransactionsBlockList != nil { + addresslist.ApplyGenesisAllocs(m.config.Chain.Genesis, contracts.BlockListTransactionsAddr, + m.config.Chain.Params.TransactionsBlockList) + } + + // apply bridge allow list genesis data + if m.config.Chain.Params.BridgeAllowList != nil { + addresslist.ApplyGenesisAllocs(m.config.Chain.Genesis, contracts.AllowListBridgeAddr, + m.config.Chain.Params.BridgeAllowList) + } + + // apply bridge block list genesis data + if m.config.Chain.Params.BridgeBlockList != nil { + addresslist.ApplyGenesisAllocs(m.config.Chain.Genesis, contracts.BlockListBridgeAddr, + m.config.Chain.Params.BridgeBlockList) + } + var initialStateRoot = types.ZeroHash if ConsensusType(engineName) == PolyBFTConsensus { @@ -241,11 +281,33 @@ func NewServer(config *Config) (*Server, error) { return nil, err } + var initialParams *chain.ForkParams + + if pf := forkManagerInitialParamsFactory[ConsensusType(engineName)]; pf != nil { + if initialParams, err = pf(config.Chain); err != nil { + return nil, err + } + } + + if err := forkmanager.ForkManagerInit( + initialParams, + forkManagerFactory[ConsensusType(engineName)], + config.Chain.Params.Forks); err != nil { + return nil, err + } + // compute the genesis root state config.Chain.Genesis.StateRoot = genesisRoot - // use the eip155 signer - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), uint64(m.config.Chain.Params.ChainID)) + // Use the london signer with eip-155 as a fallback one + var signer crypto.TxSigner = crypto.NewLondonSigner( + uint64(m.config.Chain.Params.ChainID), + config.Chain.Params.Forks.IsActive(chain.Homestead, 0), + crypto.NewEIP155Signer( + uint64(m.config.Chain.Params.ChainID), + config.Chain.Params.Forks.IsActive(chain.Homestead, 0), + ), + ) // create storage instance for blockchain var db storage.Storage @@ -268,12 +330,22 @@ func NewServer(config *Config) (*Server, error) { // blockchain object blockchainConfig := &blockchain.Config{Chain: config.Chain, DataDir: config.DataDir} - m.blockchain, err = blockchain.NewBlockchain(logger, db, blockchainConfig, nil, m.executor, signer) + m.blockchain, err = blockchain.NewBlockchain( + logger, + db, + blockchainConfig, + nil, + m.executor, + signer, + ) if err != nil { return nil, err } + // here we can provide some other configuration + m.gasHelper = gasprice.NewGasHelper(gasprice.DefaultGasHelperConfig, m.blockchain) + m.executor.GetHash = m.blockchain.GetHashHelper { @@ -282,11 +354,6 @@ func NewServer(config *Config) (*Server, error) { Blockchain: m.blockchain, } - deploymentWhitelist, err := configHelper.GetDeploymentWhitelist(config.Chain) - if err != nil { - return nil, err - } - // start transaction pool m.txpool, err = txpool.NewTxPool( logger, @@ -295,10 +362,9 @@ func NewServer(config *Config) (*Server, error) { m.grpcServer, m.network, &txpool.Config{ - MaxSlots: m.config.MaxSlots, - PriceLimit: m.config.PriceLimit, - MaxAccountEnqueued: m.config.MaxAccountEnqueued, - DeploymentWhitelist: deploymentWhitelist, + MaxSlots: m.config.MaxSlots, + PriceLimit: m.config.PriceLimit, + MaxAccountEnqueued: m.config.MaxAccountEnqueued, }, ) if err != nil { @@ -496,6 +562,18 @@ func (s *Server) setupConsensus() error { engineConfig = map[string]interface{}{} } + var ( + blockTime = common.Duration{Duration: 0} + err error + ) + + if engineName != string(DummyConsensus) && engineName != string(DevConsensus) { + blockTime, err = extractBlockTime(engineConfig) + if err != nil { + return err + } + } + config := &consensus.Config{ Params: s.config.Chain.Params, Config: engineConfig, @@ -513,7 +591,7 @@ func (s *Server) setupConsensus() error { Grpc: s.grpcServer, Logger: s.logger, SecretsManager: s.secretsManager, - BlockTime: s.config.BlockTime, + BlockTime: uint64(blockTime.Seconds()), NumBlockConfirmations: s.config.NumBlockConfirmations, }, ) @@ -527,6 +605,32 @@ func (s *Server) setupConsensus() error { return nil } +// extractBlockTime extracts blockTime parameter from consensus engine configuration. +// If it is missing or invalid, an appropriate error is returned. +func extractBlockTime(engineConfig map[string]interface{}) (common.Duration, error) { + blockTimeGeneric, ok := engineConfig["blockTime"] + if !ok { + return common.Duration{}, errBlockTimeMissing + } + + blockTimeRaw, err := json.Marshal(blockTimeGeneric) + if err != nil { + return common.Duration{}, errBlockTimeInvalid + } + + var blockTime common.Duration + + if err := json.Unmarshal(blockTimeRaw, &blockTime); err != nil { + return common.Duration{}, errBlockTimeInvalid + } + + if blockTime.Seconds() < 1 { + return common.Duration{}, errBlockTimeInvalid + } + + return blockTime, nil +} + // setupRelayer sets up the relayer func (s *Server) setupRelayer() error { account, err := wallet.NewAccountFromSecret(s.secretsManager) @@ -571,6 +675,7 @@ type jsonRPCHub struct { *network.Server consensus.Consensus consensus.BridgeDataProvider + gasprice.GasStore } func (j *jsonRPCHub) GetPeers() int { @@ -629,6 +734,7 @@ func (j *jsonRPCHub) GetCode(root types.Hash, addr types.Address) ([]byte, error func (j *jsonRPCHub) ApplyTxn( header *types.Header, txn *types.Transaction, + override types.StateOverride, ) (result *runtime.ExecutionResult, err error) { blockCreator, err := j.GetConsensus().GetBlockCreator(header) if err != nil { @@ -640,6 +746,12 @@ func (j *jsonRPCHub) ApplyTxn( return } + if override != nil { + if err = transition.WithStateOverride(override); err != nil { + return + } + } + result, err = transition.Apply(txn) return @@ -792,6 +904,7 @@ func (s *Server) setupJSONRPC() error { Consensus: s.consensus, Server: s.network, BridgeDataProvider: s.consensus.GetBridgeProvider(), + GasStore: s.gasHelper, } conf := &jsonrpc.Config{ @@ -824,6 +937,7 @@ func (s *Server) setupGRPC() error { return err } + // Start server with infinite retries go func() { if err := s.grpcServer.Serve(lis); err != nil { s.logger.Error(err.Error()) @@ -903,11 +1017,13 @@ func (s *Server) startPrometheusServer(listenAddr *net.TCPAddr) *http.Server { ReadHeaderTimeout: 60 * time.Second, } - go func() { - s.logger.Info("Prometheus server started", "addr=", listenAddr.String()) + s.logger.Info("Prometheus server started", "addr=", listenAddr.String()) - if err := srv.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { - s.logger.Error("Prometheus HTTP server ListenAndServe", "err", err) + go func() { + if err := srv.ListenAndServe(); err != nil { + if !errors.Is(err, http.ErrServerClosed) { + s.logger.Error("Prometheus HTTP server ListenAndServe", "err", err) + } } }() diff --git a/server/server_metrics.go b/server/server_metrics.go index d7737ab180..ffcb0a1f6e 100644 --- a/server/server_metrics.go +++ b/server/server_metrics.go @@ -15,7 +15,10 @@ func (s *Server) setupTelemetry() error { inm := metrics.NewInmemSink(10*time.Second, time.Minute) metrics.DefaultInmemSignal(inm) - promSink, err := prometheus.NewPrometheusSink() + promSink, err := prometheus.NewPrometheusSinkFrom(prometheus.PrometheusOpts{ + Name: "edge_prometheus_sink", + Expiration: 0, + }) if err != nil { return err } diff --git a/sonar-project.properties b/sonar-project.properties index d79c46c4d5..5565a9e4d4 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,13 +1,13 @@ sonar.projectKey=polygon-edge sonar.sources=. -sonar.exclusions=**/*_test.go,**/vendor/**,**/*.py,**/core-contracts/** +sonar.exclusions=**/*_test.go,**/vendor/**,**/*.py,**/core-contracts/**,**/tests/** sonar.tests=. sonar.test.inclusions=**/*_test.go sonar.test.exclusions=**/vendor/** -sonar.coverage.exclusions=**/vendor/**,**/*.py +sonar.coverage.exclusions=**/vendor/**,**/*.py,**/tests/** # ===================================================== # Properties specific to Go diff --git a/state/executor.go b/state/executor.go index c51737abfb..3a0e1ebf9c 100644 --- a/state/executor.go +++ b/state/executor.go @@ -6,16 +6,18 @@ import ( "math" "math/big" + "github.com/hashicorp/go-hclog" + "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/contracts" "github.com/0xPolygon/polygon-edge/crypto" + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/state/runtime" - "github.com/0xPolygon/polygon-edge/state/runtime/allowlist" + "github.com/0xPolygon/polygon-edge/state/runtime/addresslist" "github.com/0xPolygon/polygon-edge/state/runtime/evm" "github.com/0xPolygon/polygon-edge/state/runtime/precompiled" "github.com/0xPolygon/polygon-edge/state/runtime/tracer" "github.com/0xPolygon/polygon-edge/types" - "github.com/hashicorp/go-hclog" ) const ( @@ -26,8 +28,6 @@ const ( TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract ) -var emptyCodeHashTwo = types.BytesToHash(crypto.Keccak256(nil)) - // GetHashByNumber returns the hash function of a block number type GetHashByNumber = func(i uint64) types.Hash @@ -112,7 +112,11 @@ func (e *Executor) WriteGenesis( } } - objs := txn.Commit(false) + objs, err := txn.Commit(false) + if err != nil { + return types.Hash{}, err + } + _, _, root := snap.Commit(objs) return types.BytesToHash(root), nil @@ -136,15 +140,11 @@ func (e *Executor) ProcessBlock( } for _, t := range block.Transactions { - if t.ExceedsBlockGasLimit(block.Header.GasLimit) { - if err := txn.WriteFailedReceipt(t); err != nil { - return nil, err - } - + if t.Gas > block.Header.GasLimit { continue } - if err := txn.Write(t); err != nil { + if err = txn.Write(t); err != nil { return nil, err } } @@ -179,15 +179,25 @@ func (e *Executor) BeginTxn( return nil, err } + burnContract := types.ZeroAddress + if forkConfig.London { + burnContract, err = e.config.CalculateBurnContract(header.Number) + if err != nil { + return nil, err + } + } + newTxn := NewTxn(auxSnap2) txCtx := runtime.TxContext{ - Coinbase: coinbaseReceiver, - Timestamp: int64(header.Timestamp), - Number: int64(header.Number), - Difficulty: types.BytesToHash(new(big.Int).SetUint64(header.Difficulty).Bytes()), - GasLimit: int64(header.GasLimit), - ChainID: e.config.ChainID, + Coinbase: coinbaseReceiver, + Timestamp: int64(header.Timestamp), + Number: int64(header.Number), + Difficulty: types.BytesToHash(new(big.Int).SetUint64(header.Difficulty).Bytes()), + BaseFee: new(big.Int).SetUint64(header.BaseFee), + GasLimit: int64(header.GasLimit), + ChainID: e.config.ChainID, + BurnContract: burnContract, } txn := &Transition{ @@ -213,7 +223,29 @@ func (e *Executor) BeginTxn( // enable contract deployment allow list (if any) if e.config.ContractDeployerAllowList != nil { - txn.deploymentAllowlist = allowlist.NewAllowList(txn, contracts.AllowListContractsAddr) + txn.deploymentAllowList = addresslist.NewAddressList(txn, contracts.AllowListContractsAddr) + } + + if e.config.ContractDeployerBlockList != nil { + txn.deploymentBlockList = addresslist.NewAddressList(txn, contracts.BlockListContractsAddr) + } + + // enable transactions allow list (if any) + if e.config.TransactionsAllowList != nil { + txn.txnAllowList = addresslist.NewAddressList(txn, contracts.AllowListTransactionsAddr) + } + + if e.config.TransactionsBlockList != nil { + txn.txnBlockList = addresslist.NewAddressList(txn, contracts.BlockListTransactionsAddr) + } + + // enable transactions allow list (if any) + if e.config.BridgeAllowList != nil { + txn.bridgeAllowList = addresslist.NewAddressList(txn, contracts.AllowListBridgeAddr) + } + + if e.config.BridgeBlockList != nil { + txn.bridgeBlockList = addresslist.NewAddressList(txn, contracts.BlockListBridgeAddr) } return txn, nil @@ -245,8 +277,12 @@ type Transition struct { precompiles *precompiled.Precompiled // allow list runtimes - deploymentAllowlist *allowlist.AllowList - txnAllowList *allowlist.AllowList + deploymentAllowList *addresslist.AddressList + deploymentBlockList *addresslist.AddressList + txnAllowList *addresslist.AddressList + txnBlockList *addresslist.AddressList + bridgeAllowList *addresslist.AddressList + bridgeBlockList *addresslist.AddressList } func NewTransition(config chain.ForksInTime, snap Snapshot, radix *Txn) *Transition { @@ -262,52 +298,52 @@ func NewTransition(config chain.ForksInTime, snap Snapshot, radix *Txn) *Transit } } -func (t *Transition) TotalGas() uint64 { - return t.totalGas -} - -func (t *Transition) Receipts() []*types.Receipt { - return t.receipts -} +func (t *Transition) WithStateOverride(override types.StateOverride) error { + for addr, o := range override { + if o.State != nil && o.StateDiff != nil { + return fmt.Errorf("cannot override both state and state diff") + } -var emptyFrom = types.Address{} + if o.Nonce != nil { + t.state.SetNonce(addr, *o.Nonce) + } -func (t *Transition) WriteFailedReceipt(txn *types.Transaction) error { - signer := crypto.NewSigner(t.config, uint64(t.ctx.ChainID)) + if o.Balance != nil { + t.state.SetBalance(addr, o.Balance) + } - if txn.From == emptyFrom && txn.Type == types.LegacyTx { - // Decrypt the from address - from, err := signer.Sender(txn) - if err != nil { - return NewTransitionApplicationError(err, false) + if o.Code != nil { + t.state.SetCode(addr, o.Code) } - txn.From = from - } + if o.State != nil { + t.state.SetFullStorage(addr, o.State) + } - receipt := &types.Receipt{ - CumulativeGasUsed: t.totalGas, - TransactionType: txn.Type, - TxHash: txn.Hash, - Logs: t.state.Logs(), + for k, v := range o.StateDiff { + t.state.SetState(addr, k, v) + } } - receipt.LogsBloom = types.CreateBloom([]*types.Receipt{receipt}) - receipt.SetStatus(types.ReceiptFailed) - t.receipts = append(t.receipts, receipt) + return nil +} - if txn.To == nil { - receipt.ContractAddress = crypto.CreateAddress(txn.From, txn.Nonce).Ptr() - } +func (t *Transition) TotalGas() uint64 { + return t.totalGas +} - return nil +func (t *Transition) Receipts() []*types.Receipt { + return t.receipts } +var emptyFrom = types.Address{} + // Write writes another transaction to the executor func (t *Transition) Write(txn *types.Transaction) error { var err error - if txn.From == emptyFrom && txn.Type == types.LegacyTx { + if txn.From == emptyFrom && + (txn.Type == types.LegacyTx || txn.Type == types.DynamicFeeTx) { // Decrypt the from address signer := crypto.NewSigner(t.config, uint64(t.ctx.ChainID)) @@ -339,7 +375,9 @@ func (t *Transition) Write(txn *types.Transaction) error { } // The suicided accounts are set as deleted for the next iteration - t.state.CleanDeleteObjects(true) + if err := t.state.CleanDeleteObjects(true); err != nil { + return fmt.Errorf("failed to clean deleted objects: %w", err) + } if result.Failed() { receipt.SetStatus(types.ReceiptFailed) @@ -366,14 +404,18 @@ func (t *Transition) Write(txn *types.Transaction) error { } // Commit commits the final result -func (t *Transition) Commit() (Snapshot, *types.Trace, types.Hash) { - objs := t.state.Commit(t.config.EIP155) +func (t *Transition) Commit() (Snapshot, *types.Trace, types.Hash, error) { + objs, err := t.state.Commit(t.config.EIP155) + if err != nil { + return nil, nil, types.ZeroHash, err + } + s2, snapTrace, root := t.snap.Commit(objs) t.trace.AccountTrie = snapTrace.AccountTrie t.trace.StorageTrie = snapTrace.StorageTrie - return s2, t.trace, types.BytesToHash(root) + return s2, t.trace, types.BytesToHash(root), nil } func (t *Transition) subGasPool(amount uint64) error { @@ -400,7 +442,9 @@ func (t *Transition) Apply(msg *types.Transaction) (*runtime.ExecutionResult, er result, err := t.apply(msg) if err != nil { - t.state.RevertToSnapshot(s) + if revertErr := t.state.RevertToSnapshot(s); revertErr != nil { + return nil, revertErr + } } if t.PostHook != nil { @@ -417,9 +461,18 @@ func (t *Transition) ContextPtr() *runtime.TxContext { } func (t *Transition) subGasLimitPrice(msg *types.Transaction) error { - // deduct the upfront max gas cost - upfrontGasCost := new(big.Int).Set(msg.GasPrice) - upfrontGasCost.Mul(upfrontGasCost, new(big.Int).SetUint64(msg.Gas)) + upfrontGasCost := new(big.Int).SetUint64(msg.Gas) + + factor := new(big.Int) + if msg.GasFeeCap != nil && msg.GasFeeCap.BitLen() > 0 { + // Apply EIP-1559 tx cost calculation factor + factor = factor.Set(msg.GasFeeCap) + } else { + // Apply legacy tx cost calculation factor + factor = factor.Set(msg.GasPrice) + } + + upfrontGasCost = upfrontGasCost.Mul(upfrontGasCost, factor) if err := t.state.SubBalance(msg.From, upfrontGasCost); err != nil { if errors.Is(err, runtime.ErrNotEnoughFunds) { @@ -442,6 +495,42 @@ func (t *Transition) nonceCheck(msg *types.Transaction) error { return nil } +// checkDynamicFees checks correctness of the EIP-1559 feature-related fields. +// Basically, makes sure gas tip cap and gas fee cap are good. +func (t *Transition) checkDynamicFees(msg *types.Transaction) error { + if msg.Type != types.DynamicFeeTx { + return nil + } + + if msg.GasFeeCap.BitLen() == 0 && msg.GasTipCap.BitLen() == 0 { + return nil + } + + if l := msg.GasFeeCap.BitLen(); l > 256 { + return fmt.Errorf("%w: address %v, GasFeeCap bit length: %d", ErrFeeCapVeryHigh, + msg.From.String(), l) + } + + if l := msg.GasTipCap.BitLen(); l > 256 { + return fmt.Errorf("%w: address %v, GasTipCap bit length: %d", ErrTipVeryHigh, + msg.From.String(), l) + } + + if msg.GasFeeCap.Cmp(msg.GasTipCap) < 0 { + return fmt.Errorf("%w: address %v, GasTipCap: %s, GasFeeCap: %s", ErrTipAboveFeeCap, + msg.From.String(), msg.GasTipCap, msg.GasFeeCap) + } + + // This will panic if baseFee is nil, but basefee presence is verified + // as part of header validation. + if msg.GasFeeCap.Cmp(t.ctx.BaseFee) < 0 { + return fmt.Errorf("%w: address %v, GasFeeCap: %s, BaseFee: %s", ErrFeeCapTooLow, + msg.From.String(), msg.GasFeeCap, t.ctx.BaseFee) + } + + return nil +} + // errors that can originate in the consensus rules checks of the apply method below // surfacing of these errors reject the transaction thus not including it in the block @@ -451,7 +540,22 @@ var ( ErrBlockLimitReached = fmt.Errorf("gas limit reached in the pool") ErrIntrinsicGasOverflow = fmt.Errorf("overflow in intrinsic gas calculation") ErrNotEnoughIntrinsicGas = fmt.Errorf("not enough gas supplied for intrinsic gas costs") - ErrNotEnoughFunds = fmt.Errorf("not enough funds for transfer with given value") + + // ErrTipAboveFeeCap is a sanity error to ensure no one is able to specify a + // transaction with a tip higher than the total fee cap. + ErrTipAboveFeeCap = errors.New("max priority fee per gas higher than max fee per gas") + + // ErrTipVeryHigh is a sanity error to avoid extremely big numbers specified + // in the tip field. + ErrTipVeryHigh = errors.New("max priority fee per gas higher than 2^256-1") + + // ErrFeeCapVeryHigh is a sanity error to avoid extremely big numbers specified + // in the fee cap field. + ErrFeeCapVeryHigh = errors.New("max fee per gas higher than 2^256-1") + + // ErrFeeCapTooLow is returned if the transaction fee cap is less than the + // the base fee of the block. + ErrFeeCapTooLow = errors.New("max fee per gas less than block base fee") ) type TransitionApplicationError struct { @@ -481,18 +585,20 @@ func NewGasLimitReachedTransitionApplicationError(err error) *GasLimitReachedTra } func (t *Transition) apply(msg *types.Transaction) (*runtime.ExecutionResult, error) { + var err error + if msg.Type == types.StateTx { - if err := checkAndProcessStateTx(msg, t); err != nil { - return nil, err - } + err = checkAndProcessStateTx(msg) } else { - if err := checkAndProcessLegacyTx(msg, t); err != nil { - return nil, err - } + err = checkAndProcessTx(msg, t) + } + + if err != nil { + return nil, err } // the amount of gas required is available in the block - if err := t.subGasPool(msg.Gas); err != nil { + if err = t.subGasPool(msg.Gas); err != nil { return nil, NewGasLimitReachedTransitionApplicationError(err) } @@ -513,7 +619,7 @@ func (t *Transition) apply(msg *types.Transaction) (*runtime.ExecutionResult, er return nil, NewTransitionApplicationError(ErrNotEnoughIntrinsicGas, false) } - gasPrice := new(big.Int).Set(msg.GasPrice) + gasPrice := msg.GetGasPrice(t.ctx.BaseFee.Uint64()) value := new(big.Int).Set(msg.Value) // set the specific transaction fields in the context @@ -535,14 +641,33 @@ func (t *Transition) apply(msg *types.Transaction) (*runtime.ExecutionResult, er t.ctx.Tracer.TxEnd(result.GasLeft) } - // refund the sender - remaining := new(big.Int).Mul(new(big.Int).SetUint64(result.GasLeft), msg.GasPrice) + // Refund the sender + remaining := new(big.Int).Mul(new(big.Int).SetUint64(result.GasLeft), gasPrice) t.state.AddBalance(msg.From, remaining) - // pay the coinbase - coinbaseFee := new(big.Int).Mul(new(big.Int).SetUint64(result.GasUsed), msg.GasPrice) + // Spec: https://eips.ethereum.org/EIPS/eip-1559#specification + // Define effective tip based on tx type. + // We use EIP-1559 fields of the tx if the london hardfork is enabled. + // Effective tip became to be either gas tip cap or (gas fee cap - current base fee) + effectiveTip := new(big.Int).Set(gasPrice) + if t.config.London && msg.Type == types.DynamicFeeTx { + effectiveTip = common.BigMin( + new(big.Int).Sub(msg.GasFeeCap, t.ctx.BaseFee), + new(big.Int).Set(msg.GasTipCap), + ) + } + + // Pay the coinbase fee as a miner reward using the calculated effective tip. + coinbaseFee := new(big.Int).Mul(new(big.Int).SetUint64(result.GasUsed), effectiveTip) t.state.AddBalance(t.ctx.Coinbase, coinbaseFee) + // Burn some amount if the london hardfork is applied. + // Basically, burn amount is just transferred to the current burn contract. + if t.config.London && msg.Type != types.StateTx { + burnAmount := new(big.Int).Mul(new(big.Int).SetUint64(result.GasUsed), t.ctx.BaseFee) + t.state.AddBalance(t.ctx.BurnContract, burnAmount) + } + // return gas to the pool t.addGasPool(result.GasLeft) @@ -574,9 +699,43 @@ func (t *Transition) Call2( } func (t *Transition) run(contract *runtime.Contract, host runtime.Host) *runtime.ExecutionResult { - // check allow list (if any) - if t.deploymentAllowlist != nil && t.deploymentAllowlist.Addr() == contract.CodeAddress { - return t.deploymentAllowlist.Run(contract, host, &t.config) + if result := t.handleAllowBlockListsUpdate(contract, host); result != nil { + return result + } + + // check txns access lists, allow list takes precedence over block list + if t.txnAllowList != nil { + if contract.Caller != contracts.SystemCaller { + role := t.txnAllowList.GetRole(contract.Caller) + if !role.Enabled() { + t.logger.Debug( + "Failing transaction. Caller is not in the transaction allowlist", + "contract.Caller", contract.Caller, + "contract.Address", contract.Address, + ) + + return &runtime.ExecutionResult{ + GasLeft: 0, + Err: runtime.ErrNotAuth, + } + } + } + } else if t.txnBlockList != nil { + if contract.Caller != contracts.SystemCaller { + role := t.txnBlockList.GetRole(contract.Caller) + if role == addresslist.EnabledRole { + t.logger.Debug( + "Failing transaction. Caller is in the transaction blocklist", + "contract.Caller", contract.Caller, + "contract.Address", contract.Address, + ) + + return &runtime.ExecutionResult{ + GasLeft: 0, + Err: runtime.ErrNotAuth, + } + } + } } // check the precompiles @@ -642,7 +801,12 @@ func (t *Transition) applyCall( result = t.run(c, host) if result.Failed() { - t.state.RevertToSnapshot(snapshot) + if err := t.state.RevertToSnapshot(snapshot); err != nil { + return &runtime.ExecutionResult{ + GasLeft: c.Gas, + Err: err, + } + } } t.captureCallEnd(c, result) @@ -650,21 +814,14 @@ func (t *Transition) applyCall( return result } -var emptyHash types.Hash - func (t *Transition) hasCodeOrNonce(addr types.Address) bool { - nonce := t.state.GetNonce(addr) - if nonce != 0 { + if t.state.GetNonce(addr) != 0 { return true } codeHash := t.state.GetCodeHash(addr) - if codeHash != emptyCodeHashTwo && codeHash != emptyHash { - return true - } - - return false + return codeHash != types.EmptyCodeHash && codeHash != types.ZeroHash } func (t *Transition) applyCreate(c *runtime.Contract, host runtime.Host) *runtime.ExecutionResult { @@ -680,7 +837,7 @@ func (t *Transition) applyCreate(c *runtime.Contract, host runtime.Host) *runtim // Increment the nonce of the caller t.state.IncrNonce(c.Caller) - // Check if there if there is a collision and the address already exists + // Check if there is a collision and the address already exists if t.hasCodeOrNonce(c.Address) { return &runtime.ExecutionResult{ GasLeft: 0, @@ -715,10 +872,31 @@ func (t *Transition) applyCreate(c *runtime.Contract, host runtime.Host) *runtim }() // check if contract creation allow list is enabled - if t.deploymentAllowlist != nil { - role := t.deploymentAllowlist.GetRole(c.Caller) + if t.deploymentAllowList != nil { + role := t.deploymentAllowList.GetRole(c.Caller) if !role.Enabled() { + t.logger.Debug( + "Failing contract deployment. Caller is not in the deployment allowlist", + "contract.Caller", c.Caller, + "contract.Address", c.Address, + ) + + return &runtime.ExecutionResult{ + GasLeft: 0, + Err: runtime.ErrNotAuth, + } + } + } else if t.deploymentBlockList != nil { + role := t.deploymentBlockList.GetRole(c.Caller) + + if role == addresslist.EnabledRole { + t.logger.Debug( + "Failing contract deployment. Caller is in the deployment blocklist", + "contract.Caller", c.Caller, + "contract.Address", c.Address, + ) + return &runtime.ExecutionResult{ GasLeft: 0, Err: runtime.ErrNotAuth, @@ -728,14 +906,22 @@ func (t *Transition) applyCreate(c *runtime.Contract, host runtime.Host) *runtim result = t.run(c, host) if result.Failed() { - t.state.RevertToSnapshot(snapshot) + if err := t.state.RevertToSnapshot(snapshot); err != nil { + return &runtime.ExecutionResult{ + Err: err, + } + } return result } if t.config.EIP158 && len(result.ReturnValue) > SpuriousDragonMaxCodeSize { // Contract size exceeds 'SpuriousDragon' size limit - t.state.RevertToSnapshot(snapshot) + if err := t.state.RevertToSnapshot(snapshot); err != nil { + return &runtime.ExecutionResult{ + Err: err, + } + } return &runtime.ExecutionResult{ GasLeft: 0, @@ -751,7 +937,11 @@ func (t *Transition) applyCreate(c *runtime.Contract, host runtime.Host) *runtim // Out of gas creating the contract if t.config.Homestead { - t.state.RevertToSnapshot(snapshot) + if err := t.state.RevertToSnapshot(snapshot); err != nil { + return &runtime.ExecutionResult{ + Err: err, + } + } result.GasLeft = 0 } @@ -766,6 +956,41 @@ func (t *Transition) applyCreate(c *runtime.Contract, host runtime.Host) *runtim return result } +func (t *Transition) handleAllowBlockListsUpdate(contract *runtime.Contract, + host runtime.Host) *runtime.ExecutionResult { + // check contract deployment allow list (if any) + if t.deploymentAllowList != nil && t.deploymentAllowList.Addr() == contract.CodeAddress { + return t.deploymentAllowList.Run(contract, host, &t.config) + } + + // check contract deployment block list (if any) + if t.deploymentBlockList != nil && t.deploymentBlockList.Addr() == contract.CodeAddress { + return t.deploymentBlockList.Run(contract, host, &t.config) + } + + // check bridge allow list (if any) + if t.bridgeAllowList != nil && t.bridgeAllowList.Addr() == contract.CodeAddress { + return t.bridgeAllowList.Run(contract, host, &t.config) + } + + // check bridge block list (if any) + if t.bridgeBlockList != nil && t.bridgeBlockList.Addr() == contract.CodeAddress { + return t.bridgeBlockList.Run(contract, host, &t.config) + } + + // check transaction allow list (if any) + if t.txnAllowList != nil && t.txnAllowList.Addr() == contract.CodeAddress { + return t.txnAllowList.Run(contract, host, &t.config) + } + + // check transaction block list (if any) + if t.txnBlockList != nil && t.txnBlockList.Addr() == contract.CodeAddress { + return t.txnBlockList.Run(contract, host, &t.config) + } + + return nil +} + func (t *Transition) SetState(addr types.Address, key types.Hash, value types.Hash) { t.state.SetState(addr, key, value) } @@ -928,17 +1153,22 @@ func TransactionGasCost(msg *types.Transaction, isHomestead, isIstanbul bool) (u return cost, nil } -// checkAndProcessLegacyTx - first check if this message satisfies all consensus rules before +// checkAndProcessTx - first check if this message satisfies all consensus rules before // applying the message. The rules include these clauses: // 1. the nonce of the message caller is correct -// 2. caller has enough balance to cover transaction fee(gaslimit * gasprice) -func checkAndProcessLegacyTx(msg *types.Transaction, t *Transition) error { +// 2. caller has enough balance to cover transaction fee(gaslimit * gasprice * val) or fee(gasfeecap * gasprice * val) +func checkAndProcessTx(msg *types.Transaction, t *Transition) error { // 1. the nonce of the message caller is correct if err := t.nonceCheck(msg); err != nil { return NewTransitionApplicationError(err, true) } - // 2. caller has enough balance to cover transaction fee(gaslimit * gasprice) + // 2. check dynamic fees of the transaction + if err := t.checkDynamicFees(msg); err != nil { + return NewTransitionApplicationError(err, true) + } + + // 3. caller has enough balance to cover transaction if err := t.subGasLimitPrice(msg); err != nil { return NewTransitionApplicationError(err, true) } @@ -946,7 +1176,7 @@ func checkAndProcessLegacyTx(msg *types.Transaction, t *Transition) error { return nil } -func checkAndProcessStateTx(msg *types.Transaction, t *Transition) error { +func checkAndProcessStateTx(msg *types.Transaction) error { if msg.GasPrice.Cmp(big.NewInt(0)) != 0 { return NewTransitionApplicationError( errors.New("gasPrice of state transaction must be zero"), diff --git a/state/executor_test.go b/state/executor_test.go new file mode 100644 index 0000000000..79ae3c96e3 --- /dev/null +++ b/state/executor_test.go @@ -0,0 +1,156 @@ +package state + +import ( + "fmt" + "math/big" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/state/runtime" + "github.com/0xPolygon/polygon-edge/types" +) + +func TestOverride(t *testing.T) { + t.Parallel() + + state := newStateWithPreState(map[types.Address]*PreState{ + {0x0}: { + Nonce: 1, + Balance: 1, + State: map[types.Hash]types.Hash{ + types.ZeroHash: {0x1}, + }, + }, + {0x1}: { + State: map[types.Hash]types.Hash{ + types.ZeroHash: {0x1}, + }, + }, + }) + + nonce := uint64(2) + balance := big.NewInt(2) + code := []byte{0x1} + + tt := NewTransition(chain.ForksInTime{}, state, newTxn(state)) + + require.Empty(t, tt.state.GetCode(types.ZeroAddress)) + + err := tt.WithStateOverride(types.StateOverride{ + {0x0}: types.OverrideAccount{ + Nonce: &nonce, + Balance: balance, + Code: code, + StateDiff: map[types.Hash]types.Hash{ + types.ZeroHash: {0x2}, + }, + }, + {0x1}: types.OverrideAccount{ + State: map[types.Hash]types.Hash{ + {0x1}: {0x1}, + }, + }, + }) + require.NoError(t, err) + + require.Equal(t, nonce, tt.state.GetNonce(types.ZeroAddress)) + require.Equal(t, balance, tt.state.GetBalance(types.ZeroAddress)) + require.Equal(t, code, tt.state.GetCode(types.ZeroAddress)) + require.Equal(t, types.Hash{0x2}, tt.state.GetState(types.ZeroAddress, types.ZeroHash)) + + // state is fully replaced + require.Equal(t, types.Hash{0x0}, tt.state.GetState(types.Address{0x1}, types.ZeroHash)) + require.Equal(t, types.Hash{0x1}, tt.state.GetState(types.Address{0x1}, types.Hash{0x1})) +} + +func Test_Transition_checkDynamicFees(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + baseFee *big.Int + tx *types.Transaction + wantErr assert.ErrorAssertionFunc + }{ + { + name: "happy path", + baseFee: big.NewInt(100), + tx: &types.Transaction{ + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(100), + GasTipCap: big.NewInt(100), + }, + wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { + assert.NoError(t, err, i) + + return false + }, + }, + { + name: "happy path with empty values", + baseFee: big.NewInt(0), + tx: &types.Transaction{ + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(0), + GasTipCap: big.NewInt(0), + }, + wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { + assert.NoError(t, err, i) + + return false + }, + }, + { + name: "gas fee cap less than base fee", + baseFee: big.NewInt(20), + tx: &types.Transaction{ + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(10), + GasTipCap: big.NewInt(0), + }, + wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { + expectedError := fmt.Sprintf("max fee per gas less than block base fee: "+ + "address %s, GasFeeCap: 10, BaseFee: 20", types.ZeroAddress) + assert.EqualError(t, err, expectedError, i) + + return true + }, + }, + { + name: "gas fee cap less than tip cap", + baseFee: big.NewInt(5), + tx: &types.Transaction{ + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(10), + GasTipCap: big.NewInt(15), + }, + wantErr: func(t assert.TestingT, err error, i ...interface{}) bool { + expectedError := fmt.Sprintf("max priority fee per gas higher than max fee per gas: "+ + "address %s, GasTipCap: 15, GasFeeCap: 10", types.ZeroAddress) + assert.EqualError(t, err, expectedError, i) + + return true + }, + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + tr := &Transition{ + ctx: runtime.TxContext{ + BaseFee: tt.baseFee, + }, + } + + err := tr.checkDynamicFees(tt.tx) + tt.wantErr(t, err, fmt.Sprintf("checkDynamicFees(%v)", tt.tx)) + }) + } +} diff --git a/state/immutable-trie/snapshot.go b/state/immutable-trie/snapshot.go index 587145e578..31ba52ae26 100644 --- a/state/immutable-trie/snapshot.go +++ b/state/immutable-trie/snapshot.go @@ -100,11 +100,8 @@ func (s *Snapshot) Commit(objs []*state.Object) (state.Snapshot, *types.Trace, [ tt := s.trie.Txn(s.state.storage) tt.batch = batch - arena := accountArenaPool.Get() - defer accountArenaPool.Put(arena) - - ar1 := stateArenaPool.Get() - defer stateArenaPool.Put(ar1) + arena := stateArenaPool.Get() + defer stateArenaPool.Put(arena) for _, obj := range objs { if obj.Deleted { @@ -131,7 +128,7 @@ func (s *Snapshot) Commit(objs []*state.Object) (state.Snapshot, *types.Trace, [ if entry.Deleted { localTxn.Delete(k) } else { - vv := ar1.NewBytes(bytes.TrimLeft(entry.Val, "\x00")) + vv := arena.NewBytes(bytes.TrimLeft(entry.Val, "\x00")) localTxn.Insert(k, vv.MarshalTo(nil)) } } diff --git a/state/immutable-trie/state.go b/state/immutable-trie/state.go index dd69256a71..e8b9d51989 100644 --- a/state/immutable-trie/state.go +++ b/state/immutable-trie/state.go @@ -47,6 +47,10 @@ func (s *State) SetCode(hash types.Hash, code []byte) { } func (s *State) GetCode(hash types.Hash) ([]byte, bool) { + if hash == types.EmptyCodeHash { + return []byte{}, true + } + return s.storage.GetCode(hash) } diff --git a/state/immutable-trie/state_test.go b/state/immutable-trie/state_test.go index e4e2ce4a98..566a1252d8 100644 --- a/state/immutable-trie/state_test.go +++ b/state/immutable-trie/state_test.go @@ -13,7 +13,6 @@ func TestState(t *testing.T) { func buildPreState(pre state.PreStates) state.Snapshot { storage := NewMemoryStorage() st := NewState(storage) - snap := st.NewSnapshot() - return snap + return st.NewSnapshot() } diff --git a/state/immutable-trie/trie.go b/state/immutable-trie/trie.go index ae01e396ef..f71d8a7cdc 100644 --- a/state/immutable-trie/trie.go +++ b/state/immutable-trie/trie.go @@ -116,12 +116,9 @@ func hashit(k []byte) []byte { return h.Sum(nil) } -var accountArenaPool fastrlp.ArenaPool - -// TODO, Remove once we do update in fastrlp (to be fixed in EVM-528) -// -//nolint:godox -var stateArenaPool fastrlp.ArenaPool +var ( + stateArenaPool fastrlp.ArenaPool +) // Hash returns the root hash of the trie. It does not write to the // database and can be used even if the trie doesn't have one. diff --git a/state/runtime/allowlist/allowlist.go b/state/runtime/addresslist/addresslist.go similarity index 69% rename from state/runtime/allowlist/allowlist.go rename to state/runtime/addresslist/addresslist.go index 6a0d362956..0046c4113d 100644 --- a/state/runtime/allowlist/allowlist.go +++ b/state/runtime/addresslist/addresslist.go @@ -1,4 +1,4 @@ -package allowlist +package addresslist import ( "bytes" @@ -10,34 +10,34 @@ import ( "github.com/umbracle/ethgo/abi" ) -// list of function methods for the allow list functionality +// list of function methods for the address list functionality var ( - SetAdminFunc = abi.MustNewMethod("function setAdmin(address)") - SetEnabledSignatureFunc = abi.MustNewMethod("function setEnabled(address)") - SetNoneFunc = abi.MustNewMethod("function setNone(address)") - ReadAllowListFunc = abi.MustNewMethod("function readAllowList(address) returns (uint256)") + SetAdminFunc = abi.MustNewMethod("function setAdmin(address)") + SetEnabledFunc = abi.MustNewMethod("function setEnabled(address)") + SetNoneFunc = abi.MustNewMethod("function setNone(address)") + ReadAddressListFunc = abi.MustNewMethod("function readAddressList(address) returns (uint256)") ) // list of gas costs for the operations var ( - writeAllowListCost = uint64(20000) - readAllowListCost = uint64(5000) + writeAddressListCost = uint64(20000) + readAddressListCost = uint64(5000) ) -type AllowList struct { +type AddressList struct { state stateRef addr types.Address } -func NewAllowList(state stateRef, addr types.Address) *AllowList { - return &AllowList{state: state, addr: addr} +func NewAddressList(state stateRef, addr types.Address) *AddressList { + return &AddressList{state: state, addr: addr} } -func (a *AllowList) Addr() types.Address { +func (a *AddressList) Addr() types.Address { return a.addr } -func (a *AllowList) Run(c *runtime.Contract, host runtime.Host, _ *chain.ForksInTime) *runtime.ExecutionResult { +func (a *AddressList) Run(c *runtime.Contract, host runtime.Host, _ *chain.ForksInTime) *runtime.ExecutionResult { ret, gasUsed, err := a.runInputCall(c.Caller, c.Input, c.Gas, c.Static) res := &runtime.ExecutionResult{ @@ -55,9 +55,10 @@ var ( errInputTooShort = fmt.Errorf("wrong input size, expected 32") errFunctionNotFound = fmt.Errorf("function not found") errWriteProtection = fmt.Errorf("write protection") + errAdminSelfRemove = fmt.Errorf("cannot remove admin role from caller") ) -func (a *AllowList) runInputCall(caller types.Address, input []byte, +func (a *AddressList) runInputCall(caller types.Address, input []byte, gas uint64, isStatic bool) ([]byte, uint64, error) { // decode the function signature from the input if len(input) < types.SignatureSize { @@ -87,8 +88,8 @@ func (a *AllowList) runInputCall(caller types.Address, input []byte, inputAddr := types.BytesToAddress(inputBytes) - if bytes.Equal(sig, ReadAllowListFunc.ID()) { - if err := consumeGas(readAllowListCost); err != nil { + if bytes.Equal(sig, ReadAddressListFunc.ID()) { + if err := consumeGas(readAddressListCost); err != nil { return nil, 0, err } @@ -102,7 +103,7 @@ func (a *AllowList) runInputCall(caller types.Address, input []byte, var updateRole Role if bytes.Equal(sig, SetAdminFunc.ID()) { updateRole = AdminRole - } else if bytes.Equal(sig, SetEnabledSignatureFunc.ID()) { + } else if bytes.Equal(sig, SetEnabledFunc.ID()) { updateRole = EnabledRole } else if bytes.Equal(sig, SetNoneFunc.ID()) { updateRole = NoRole @@ -110,7 +111,7 @@ func (a *AllowList) runInputCall(caller types.Address, input []byte, return nil, 0, errFunctionNotFound } - if err := consumeGas(writeAllowListCost); err != nil { + if err := consumeGas(writeAddressListCost); err != nil { return nil, gasUsed, err } @@ -125,16 +126,21 @@ func (a *AllowList) runInputCall(caller types.Address, input []byte, return nil, gasUsed, runtime.ErrNotAuth } + // An admin can not remove himself from the list + if addrRole == AdminRole && caller == inputAddr { + return nil, gasUsed, errAdminSelfRemove + } + a.SetRole(inputAddr, updateRole) return nil, gasUsed, nil } -func (a *AllowList) SetRole(addr types.Address, role Role) { +func (a *AddressList) SetRole(addr types.Address, role Role) { a.state.SetState(a.addr, types.BytesToHash(addr.Bytes()), types.Hash(role)) } -func (a *AllowList) GetRole(addr types.Address) Role { +func (a *AddressList) GetRole(addr types.Address) Role { res := a.state.GetStorage(a.addr, types.BytesToHash(addr.Bytes())) return Role(res) diff --git a/state/runtime/allowlist/allowlist_test.go b/state/runtime/addresslist/addresslist_test.go similarity index 71% rename from state/runtime/allowlist/allowlist_test.go rename to state/runtime/addresslist/addresslist_test.go index c8c6ad83aa..ad13e0a527 100644 --- a/state/runtime/allowlist/allowlist_test.go +++ b/state/runtime/addresslist/addresslist_test.go @@ -1,4 +1,4 @@ -package allowlist +package addresslist import ( "testing" @@ -21,16 +21,16 @@ func (m *mockState) GetStorage(addr types.Address, key types.Hash) types.Hash { return m.state[key] } -func newMockAllowList() *AllowList { +func newMockAddressList() *AddressList { state := &mockState{ state: map[types.Hash]types.Hash{}, } - return NewAllowList(state, types.Address{}) + return NewAddressList(state, types.Address{}) } -func TestAllowList_WrongInput(t *testing.T) { - a := newMockAllowList() +func TestAddressList_WrongInput(t *testing.T) { + a := newMockAddressList() input := []byte{} @@ -51,20 +51,20 @@ func TestAllowList_WrongInput(t *testing.T) { require.Equal(t, errFunctionNotFound, err) } -func TestAllowList_ReadOp_NotEnoughGas(t *testing.T) { - a := newMockAllowList() +func TestAddressList_ReadOp_NotEnoughGas(t *testing.T) { + a := newMockAddressList() - input, _ := ReadAllowListFunc.Encode([]interface{}{types.Address{}}) + input, _ := ReadAddressListFunc.Encode([]interface{}{types.Address{}}) _, _, err := a.runInputCall(types.Address{}, input, 0, false) require.Equal(t, runtime.ErrOutOfGas, err) - _, _, err = a.runInputCall(types.Address{}, input, readAllowListCost-1, false) + _, _, err = a.runInputCall(types.Address{}, input, readAddressListCost-1, false) require.Equal(t, runtime.ErrOutOfGas, err) } -func TestAllowList_ReadOp_Full(t *testing.T) { - a := newMockAllowList() +func TestAddressList_ReadOp_Full(t *testing.T) { + a := newMockAddressList() a.SetRole(types.Address{}, AdminRole) cases := []struct { @@ -84,48 +84,48 @@ func TestAllowList_ReadOp_Full(t *testing.T) { } for _, c := range cases { - input, _ := ReadAllowListFunc.Encode([]interface{}{c.addr}) - role, gasUsed, err := a.runInputCall(types.Address{}, input, readAllowListCost, false) + input, _ := ReadAddressListFunc.Encode([]interface{}{c.addr}) + role, gasUsed, err := a.runInputCall(types.Address{}, input, readAddressListCost, false) require.NoError(t, err) - require.Equal(t, gasUsed, readAllowListCost) + require.Equal(t, gasUsed, readAddressListCost) require.Equal(t, c.role.Bytes(), role) } } -func TestAllowList_WriteOp_NotEnoughGas(t *testing.T) { - a := newMockAllowList() +func TestAddressList_WriteOp_NotEnoughGas(t *testing.T) { + a := newMockAddressList() input, _ := SetAdminFunc.Encode([]interface{}{types.Address{}}) _, _, err := a.runInputCall(types.Address{}, input, 0, false) require.Equal(t, runtime.ErrOutOfGas, err) - _, _, err = a.runInputCall(types.Address{}, input, writeAllowListCost-1, false) + _, _, err = a.runInputCall(types.Address{}, input, writeAddressListCost-1, false) require.Equal(t, runtime.ErrOutOfGas, err) } -func TestAllowList_WriteOp_CannotWriteInStaticCall(t *testing.T) { - a := newMockAllowList() +func TestAddressList_WriteOp_CannotWriteInStaticCall(t *testing.T) { + a := newMockAddressList() input, _ := SetAdminFunc.Encode([]interface{}{types.Address{}}) - _, gasCost, err := a.runInputCall(types.Address{}, input, writeAllowListCost, true) - require.Equal(t, writeAllowListCost, gasCost) + _, gasCost, err := a.runInputCall(types.Address{}, input, writeAddressListCost, true) + require.Equal(t, writeAddressListCost, gasCost) require.Equal(t, err, errWriteProtection) } -func TestAllowList_WriteOp_OnlyAdminCanUpdate(t *testing.T) { - a := newMockAllowList() +func TestAddressList_WriteOp_OnlyAdminCanUpdate(t *testing.T) { + a := newMockAddressList() input, _ := SetAdminFunc.Encode([]interface{}{types.Address{}}) - _, gasCost, err := a.runInputCall(types.Address{}, input, writeAllowListCost, false) - require.Equal(t, writeAllowListCost, gasCost) + _, gasCost, err := a.runInputCall(types.Address{}, input, writeAddressListCost, false) + require.Equal(t, writeAddressListCost, gasCost) require.Equal(t, err, runtime.ErrNotAuth) } -func TestAllowList_WriteOp_Full(t *testing.T) { - a := newMockAllowList() +func TestAddressList_WriteOp_Full(t *testing.T) { + a := newMockAddressList() a.SetRole(types.Address{}, AdminRole) targetAddr := types.Address{0x1} @@ -138,15 +138,15 @@ func TestAllowList_WriteOp_Full(t *testing.T) { role Role }{ {SetAdminFunc, AdminRole}, - {SetEnabledSignatureFunc, EnabledRole}, + {SetEnabledFunc, EnabledRole}, {SetNoneFunc, NoRole}, } for _, c := range cases { input, _ := c.method.Encode([]interface{}{targetAddr}) - ret, gasCost, err := a.runInputCall(types.Address{}, input, writeAllowListCost, false) - require.Equal(t, writeAllowListCost, gasCost) + ret, gasCost, err := a.runInputCall(types.Address{}, input, writeAddressListCost, false) + require.Equal(t, writeAddressListCost, gasCost) require.NoError(t, err) require.Empty(t, ret) require.Equal(t, c.role, a.GetRole(targetAddr)) diff --git a/state/runtime/allowlist/genesis.go b/state/runtime/addresslist/genesis.go similarity index 85% rename from state/runtime/allowlist/genesis.go rename to state/runtime/addresslist/genesis.go index 025a33211a..b2b20bb805 100644 --- a/state/runtime/allowlist/genesis.go +++ b/state/runtime/addresslist/genesis.go @@ -1,4 +1,4 @@ -package allowlist +package addresslist import ( "math/big" @@ -7,9 +7,9 @@ import ( "github.com/0xPolygon/polygon-edge/types" ) -func ApplyGenesisAllocs(chain *chain.Genesis, allowListAddr types.Address, config *chain.AllowListConfig) { - allocList := &AllowList{ - addr: allowListAddr, +func ApplyGenesisAllocs(chain *chain.Genesis, addressListAddr types.Address, config *chain.AddressListConfig) { + allocList := &AddressList{ + addr: addressListAddr, state: &genesisState{chain}, } diff --git a/state/runtime/allowlist/genesis_test.go b/state/runtime/addresslist/genesis_test.go similarity index 94% rename from state/runtime/allowlist/genesis_test.go rename to state/runtime/addresslist/genesis_test.go index 64a8e34e9b..86eee51603 100644 --- a/state/runtime/allowlist/genesis_test.go +++ b/state/runtime/addresslist/genesis_test.go @@ -1,4 +1,4 @@ -package allowlist +package addresslist import ( "math/big" @@ -20,7 +20,7 @@ func TestGenesis(t *testing.T) { Alloc: map[types.Address]*chain.GenesisAccount{}, } - config := &chain.AllowListConfig{ + config := &chain.AddressListConfig{ AdminAddresses: []types.Address{ one, }, diff --git a/state/runtime/evm/dispatch_table.go b/state/runtime/evm/dispatch_table.go index 7214a18dcd..e8afeae0f5 100644 --- a/state/runtime/evm/dispatch_table.go +++ b/state/runtime/evm/dispatch_table.go @@ -123,6 +123,7 @@ func init() { register(NUMBER, handler{opNumber, 0, 2}) register(DIFFICULTY, handler{opDifficulty, 0, 2}) register(GASLIMIT, handler{opGasLimit, 0, 2}) + register(BASEFEE, handler{opBaseFee, 0, 2}) register(SELFDESTRUCT, handler{opSelfDestruct, 1, 0}) diff --git a/state/runtime/evm/evm_fuzz_test.go b/state/runtime/evm/evm_fuzz_test.go new file mode 100644 index 0000000000..31a8b66458 --- /dev/null +++ b/state/runtime/evm/evm_fuzz_test.go @@ -0,0 +1,193 @@ +package evm + +import ( + "errors" + "math/big" + "testing" + + "github.com/0xPolygon/polygon-edge/chain" + "github.com/0xPolygon/polygon-edge/state/runtime" + "github.com/0xPolygon/polygon-edge/types" + go_fuzz_utils "github.com/trailofbits/go-fuzz-utils" +) + +var _ runtime.Host = &mockHostF{} + +// mockHostF is a struct which meets the requirements of runtime.Host interface but returns naive data +type mockHostF struct { + // to use + tracer runtime.VMTracer + storage map[types.Address]map[types.Hash]types.Hash + balances map[types.Address]*big.Int + nonces map[types.Address]uint64 + + // to fuzz + refund uint64 + blockHash types.Hash +} + +func (m *mockHostF) AccountExists(addr types.Address) bool { + if _, ok := m.nonces[addr]; ok { + return true + } + + return false +} + +func (m *mockHostF) GetStorage(addr types.Address, key types.Hash) types.Hash { + if val, ok := m.storage[addr][key]; !ok { + return types.Hash{} + } else { + return val + } +} + +func (m *mockHostF) SetStorage( + addr types.Address, + key types.Hash, + value types.Hash, + config *chain.ForksInTime, +) runtime.StorageStatus { + if _, ok := m.storage[addr]; !ok { + m.storage[addr] = make(map[types.Hash]types.Hash) + } + + m.storage[addr][key] = value + + return runtime.StorageModified +} + +func (m *mockHostF) SetState(addr types.Address, key types.Hash, value types.Hash) { + return +} + +func (m *mockHostF) GetBalance(addr types.Address) *big.Int { + if b, ok := m.balances[addr]; !ok { + m.balances[addr] = big.NewInt(0) + + return m.balances[addr] + } else { + return b + } +} + +func (m *mockHostF) GetCodeSize(addr types.Address) int { + return 0 +} + +func (m *mockHostF) GetCodeHash(addr types.Address) types.Hash { + return types.Hash{} +} + +func (m *mockHostF) GetCode(addr types.Address) []byte { + return nil +} + +func (m *mockHostF) Selfdestruct(addr types.Address, beneficiary types.Address) { + return +} +func (m *mockHostF) GetTxContext() runtime.TxContext { + return runtime.TxContext{} +} + +func (m *mockHostF) GetBlockHash(number int64) types.Hash { + return m.blockHash +} + +func (m *mockHostF) EmitLog(addr types.Address, topics []types.Hash, data []byte) { + return +} + +func (m *mockHostF) Callx(c *runtime.Contract, h runtime.Host) *runtime.ExecutionResult { + return &runtime.ExecutionResult{} +} + +func (m *mockHostF) Empty(addr types.Address) bool { + return true +} + +func (m *mockHostF) GetNonce(addr types.Address) uint64 { + if nonce, ok := m.nonces[addr]; !ok { + m.nonces[addr] = 0 + + return 0 + } else { + return nonce + } +} + +func (m *mockHostF) Transfer(from types.Address, to types.Address, amount *big.Int) error { + f := m.GetBalance(from) + t := m.GetBalance(to) + + if f.Cmp(amount) < 0 { + return errors.New("not enough balance") + } + + f.Sub(f, amount) + t.Add(t, amount) + + return nil +} + +func (m *mockHostF) GetTracer() runtime.VMTracer { + return m.tracer +} + +func (m *mockHostF) GetRefund() uint64 { + return m.refund +} + +func FuzzTestEVM(f *testing.F) { + seed := []byte{ + PUSH1, 0x01, PUSH1, 0x02, ADD, + PUSH1, 0x00, MSTORE8, + PUSH1, 0x01, PUSH1, 0x00, RETURN, + } + + f.Add(seed) + + config := &chain.ForksInTime{ + Byzantium: true, + } + + evm := NewEVM() + + f.Fuzz(func(t *testing.T, input []byte) { + tp, err := go_fuzz_utils.NewTypeProvider(input) + if err != nil { + return + } + + err = tp.SetParamsSliceBounds(1, 4*1024) + if err != nil { + return + } + + refund, err := tp.GetUint64() + if err != nil { + return + } + + blockHashI, err := tp.GetNBytes(types.HashLength) + if err != nil { + return + } + + blockHash := types.BytesToHash(blockHashI) + host := &mockHostF{ + refund: refund, blockHash: blockHash, + storage: make(map[types.Address]map[types.Hash]types.Hash), + balances: make(map[types.Address]*big.Int), + nonces: make(map[types.Address]uint64), + } + + code, err := tp.GetBytes() + if err != nil { + return + } + + contract := newMockContract(big.NewInt(0), 10000000, code) + evm.Run(contract, host, config) + }) +} diff --git a/state/runtime/evm/evm_test.go b/state/runtime/evm/evm_test.go index d2e0f95a42..f22900a968 100644 --- a/state/runtime/evm/evm_test.go +++ b/state/runtime/evm/evm_test.go @@ -156,7 +156,7 @@ func TestRun(t *testing.T) { ReturnValue: nil, GasLeft: 0, GasUsed: 5000, - Err: errStackUnderflow, + Err: &runtime.StackUnderflowError{StackLen: 0, Required: 2}, }, }, { @@ -339,7 +339,7 @@ func TestRunWithTracer(t *testing.T) { "cost": uint64(2), "lastReturnData": []byte{}, "depth": 1, - "err": errStackUnderflow, + "err": &runtime.StackUnderflowError{StackLen: 0, Required: 1}, }, }, }, diff --git a/state/runtime/evm/instructions.go b/state/runtime/evm/instructions.go index 9ef721115e..4f9c798e11 100644 --- a/state/runtime/evm/instructions.go +++ b/state/runtime/evm/instructions.go @@ -907,6 +907,16 @@ func opGasLimit(c *state) { c.push1().SetInt64(c.host.GetTxContext().GasLimit) } +func opBaseFee(c *state) { + if !c.config.London { + c.exit(errOpCodeNotFound) + + return + } + + c.push(c.host.GetTxContext().BaseFee) +} + func opSelfDestruct(c *state) { if c.inStaticCall() { c.exit(errWriteProtection) @@ -984,7 +994,7 @@ func opPush(n int) instruction { func opDup(n int) instruction { return func(c *state) { if !c.stackAtLeast(n) { - c.exit(errStackUnderflow) + c.exit(&runtime.StackUnderflowError{StackLen: c.sp, Required: n}) } else { val := c.peekAt(n) c.push1().Set(val) @@ -995,7 +1005,7 @@ func opDup(n int) instruction { func opSwap(n int) instruction { return func(c *state) { if !c.stackAtLeast(n + 1) { - c.exit(errStackUnderflow) + c.exit(&runtime.StackUnderflowError{StackLen: c.sp, Required: n + 1}) } else { c.swap(n) } @@ -1013,7 +1023,7 @@ func opLog(size int) instruction { } if !c.stackAtLeast(2 + size) { - c.exit(errStackUnderflow) + c.exit(&runtime.StackUnderflowError{StackLen: c.sp, Required: 2 + size}) return } @@ -1091,7 +1101,9 @@ func opCreate(op OpCode) instruction { v := c.push1() if op == CREATE && c.config.Homestead && errors.Is(result.Err, runtime.ErrCodeStoreOutOfGas) { v.Set(zero) - } else if result.Failed() && !errors.Is(result.Err, runtime.ErrCodeStoreOutOfGas) { + } else if op == CREATE && result.Failed() && !errors.Is(result.Err, runtime.ErrCodeStoreOutOfGas) { + v.Set(zero) + } else if op == CREATE2 && result.Failed() { v.Set(zero) } else { v.SetBytes(contract.Address.Bytes()) diff --git a/state/runtime/evm/instructions_test.go b/state/runtime/evm/instructions_test.go index 2d29cf2f53..e17f79fdcc 100644 --- a/state/runtime/evm/instructions_test.go +++ b/state/runtime/evm/instructions_test.go @@ -359,6 +359,57 @@ func TestCreate(t *testing.T) { }, }, }, + { + name: "should set zero address if contract call throws any error for CREATE2", + op: CREATE2, + contract: &runtime.Contract{ + Static: false, + Address: addr1, + }, + config: &chain.ForksInTime{ + Homestead: true, + Constantinople: true, + }, + initState: &state{ + gas: 1000, + sp: 4, + stack: []*big.Int{ + big.NewInt(0x01), // salt + big.NewInt(0x01), // length + big.NewInt(0x00), // offset + big.NewInt(0x00), // value + }, + memory: []byte{ + byte(REVERT), + }, + stop: false, + err: nil, + }, + // during creation of code with length 1 for CREATE2 op code, 985 gas units are spent by buildCreateContract() + resultState: &state{ + gas: 15, + sp: 1, + stack: []*big.Int{ + big.NewInt(0x01).SetInt64(0x00), + big.NewInt(0x01), + big.NewInt(0x00), + big.NewInt(0x00), + }, + memory: []byte{ + byte(REVERT), + }, + stop: false, + err: nil, + }, + mockHost: &mockHostForInstructions{ + nonce: 0, + callxResult: &runtime.ExecutionResult{ + // if it is ErrCodeStoreOutOfGas then we set GasLeft to 0 + GasLeft: 0, + Err: runtime.ErrCodeStoreOutOfGas, + }, + }, + }, } for _, tt := range tests { diff --git a/state/runtime/evm/opcodes.go b/state/runtime/evm/opcodes.go index 85bd02d1c5..409180d4dc 100644 --- a/state/runtime/evm/opcodes.go +++ b/state/runtime/evm/opcodes.go @@ -161,6 +161,9 @@ const ( // SELFBALANCE returns the balance of the current account SELFBALANCE = 0x47 + // BASEFEE returns the current base fee value + BASEFEE = 0x48 + // POP pops a (u)int256 off the stack and discards it POP = 0x50 @@ -308,6 +311,7 @@ var opCodeToString = map[OpCode]string{ NUMBER: "NUMBER", DIFFICULTY: "DIFFICULTY", GASLIMIT: "GASLIMIT", + BASEFEE: "BASEFEE", POP: "POP", MLOAD: "MLOAD", MSTORE: "MSTORE", diff --git a/state/runtime/evm/state.go b/state/runtime/evm/state.go index 74199ca4d5..7b5ebd6cd3 100644 --- a/state/runtime/evm/state.go +++ b/state/runtime/evm/state.go @@ -38,8 +38,6 @@ const stackSize = 1024 var ( errOutOfGas = runtime.ErrOutOfGas - errStackUnderflow = runtime.ErrStackUnderflow - errStackOverflow = runtime.ErrStackOverflow errRevert = runtime.ErrExecutionReverted errGasUintOverflow = errors.New("gas uint64 overflow") errWriteProtection = errors.New("write protection") @@ -245,7 +243,7 @@ func (c *state) Run() ([]byte, error) { // check if the depth of the stack is enough for the instruction if c.sp < inst.stack { - c.exit(errStackUnderflow) + c.exit(&runtime.StackUnderflowError{StackLen: c.sp, Required: inst.stack}) c.captureExecutionError(op.String(), c.ip, gasCopy, inst.gas) break @@ -266,7 +264,7 @@ func (c *state) Run() ([]byte, error) { // check if stack size exceeds the max size if c.sp > stackSize { - c.exit(errStackOverflow) + c.exit(&runtime.StackOverflowError{StackLen: c.sp, Limit: stackSize}) break } diff --git a/state/runtime/evm/state_test.go b/state/runtime/evm/state_test.go index 5000ac1381..3bf9d05f72 100644 --- a/state/runtime/evm/state_test.go +++ b/state/runtime/evm/state_test.go @@ -3,6 +3,8 @@ package evm import ( "testing" + "github.com/0xPolygon/polygon-edge/state/runtime" + "github.com/stretchr/testify/assert" ) @@ -68,7 +70,7 @@ func TestStackOverflow(t *testing.T) { s.host = &mockHost{} _, err = s.Run() - assert.Equal(t, errStackOverflow, err) + assert.Equal(t, &runtime.StackOverflowError{StackLen: stackSize + 1, Limit: stackSize}, err) } func TestStackUnderflow(t *testing.T) { @@ -99,7 +101,8 @@ func TestStackUnderflow(t *testing.T) { s.host = &mockHost{} _, err = s.Run() - assert.Equal(t, errStackUnderflow, err) + // need at least one operation on the stack + assert.Equal(t, &runtime.StackUnderflowError{StackLen: 0, Required: 1}, err) } func TestOpcodeNotFound(t *testing.T) { diff --git a/state/runtime/precompiled/precompiled.go b/state/runtime/precompiled/precompiled.go index 2a661bba13..8b33d5eb80 100644 --- a/state/runtime/precompiled/precompiled.go +++ b/state/runtime/precompiled/precompiled.go @@ -161,8 +161,6 @@ func (p *Precompiled) Run(c *runtime.Contract, host runtime.Host, config *chain. var zeroPadding = make([]byte, 64) func (p *Precompiled) leftPad(buf []byte, n int) []byte { - //nolint:godox - // TODO, avoid buffer allocation (to be fixed in EVM-528) l := len(buf) if l > n { return buf diff --git a/state/runtime/runtime.go b/state/runtime/runtime.go index 3ba74d6d27..4ca7c2aa83 100644 --- a/state/runtime/runtime.go +++ b/state/runtime/runtime.go @@ -2,6 +2,7 @@ package runtime import ( "errors" + "fmt" "math/big" "github.com/0xPolygon/polygon-edge/chain" @@ -11,15 +12,17 @@ import ( // TxContext is the context of the transaction type TxContext struct { - GasPrice types.Hash - Origin types.Address - Coinbase types.Address - Number int64 - Timestamp int64 - GasLimit int64 - ChainID int64 - Difficulty types.Hash - Tracer tracer.Tracer + GasPrice types.Hash + Origin types.Address + Coinbase types.Address + Number int64 + Timestamp int64 + GasLimit int64 + ChainID int64 + Difficulty types.Hash + Tracer tracer.Tracer + BaseFee *big.Int + BurnContract types.Address } // StorageStatus is the status of the storage access @@ -128,20 +131,40 @@ func (r *ExecutionResult) UpdateGasUsed(gasLimit uint64, refund uint64) { var ( ErrOutOfGas = errors.New("out of gas") - ErrStackOverflow = errors.New("stack overflow") - ErrStackUnderflow = errors.New("stack underflow") ErrNotEnoughFunds = errors.New("not enough funds") ErrInsufficientBalance = errors.New("insufficient balance for transfer") - ErrMaxCodeSizeExceeded = errors.New("evm: max code size exceeded") + ErrMaxCodeSizeExceeded = errors.New("max code size exceeded") ErrContractAddressCollision = errors.New("contract address collision") ErrDepth = errors.New("max call depth exceeded") - ErrExecutionReverted = errors.New("execution was reverted") + ErrExecutionReverted = errors.New("execution reverted") ErrCodeStoreOutOfGas = errors.New("contract creation code storage out of gas") ErrUnauthorizedCaller = errors.New("unauthorized caller") ErrInvalidInputData = errors.New("invalid input data") ErrNotAuth = errors.New("not in allow list") ) +// StackUnderflowError wraps an evm error when the items on the stack less +// than the minimal requirement. +type StackUnderflowError struct { + StackLen int + Required int +} + +func (e *StackUnderflowError) Error() string { + return fmt.Sprintf("stack underflow (%d <=> %d)", e.StackLen, e.Required) +} + +// StackOverflowError wraps an evm error when the items on the stack exceeds +// the maximum allowance. +type StackOverflowError struct { + StackLen int + Limit int +} + +func (e *StackOverflowError) Error() string { + return fmt.Sprintf("stack limit reached %d (%d)", e.StackLen, e.Limit) +} + type CallType int const ( diff --git a/state/runtime/tracer/structtracer/tracer.go b/state/runtime/tracer/structtracer/tracer.go index 24260abcc7..42278912ab 100644 --- a/state/runtime/tracer/structtracer/tracer.go +++ b/state/runtime/tracer/structtracer/tracer.go @@ -55,17 +55,22 @@ type StructTracer struct { consumedGas uint64 output []byte err error - storage map[types.Address]map[types.Hash]types.Hash - currentMemory []byte - currentStack []*big.Int + storage []map[types.Address]map[types.Hash]types.Hash + currentMemory []([]byte) + currentStack []([]*big.Int) } func NewStructTracer(config Config) *StructTracer { + storage := make([](map[types.Address]map[types.Hash]types.Hash), 1) + storage[0] = make(map[types.Address]map[types.Hash]types.Hash) + return &StructTracer{ - Config: config, - cancelLock: sync.RWMutex{}, - storage: make(map[types.Address]map[types.Hash]types.Hash), + Config: config, + cancelLock: sync.RWMutex{}, + storage: storage, + currentMemory: make([]([]byte), 1), + currentStack: make([]([]*big.Int), 1), } } @@ -92,9 +97,10 @@ func (t *StructTracer) Clear() { t.consumedGas = 0 t.output = t.output[:0] t.err = nil - t.storage = make(map[types.Address]map[types.Hash]types.Hash) - t.currentMemory = t.currentMemory[:0] - t.currentStack = t.currentStack[:0] + t.storage = make([](map[types.Address]map[types.Hash]types.Hash), 1) + t.storage[0] = make(map[types.Address]map[types.Hash]types.Hash) + t.currentMemory = make([]([]byte), 1) + t.currentStack = make([]([]*big.Int), 1) } func (t *StructTracer) TxStart(gasLimit uint64) { @@ -141,9 +147,9 @@ func (t *StructTracer) CaptureState( return } - t.captureMemory(memory) + t.captureMemory(memory, opCode) - t.captureStack(stack, sp) + t.captureStack(stack, sp, opCode) t.captureStorage( stack, @@ -156,33 +162,46 @@ func (t *StructTracer) CaptureState( func (t *StructTracer) captureMemory( memory []byte, + opCode int, ) { if !t.Config.EnableMemory { return } // always allocate new space to get new reference - t.currentMemory = make([]byte, len(memory)) + currentMemory := make([]byte, len(memory)) + copy(currentMemory, memory) - copy(t.currentMemory, memory) + t.currentMemory[len(t.currentMemory)-1] = currentMemory + + if opCode == evm.CALL || opCode == evm.STATICCALL { + t.currentMemory = append(t.currentMemory, make([]byte, len(memory))) + } } func (t *StructTracer) captureStack( stack []*big.Int, sp int, + opCode int, ) { if !t.Config.EnableStack { return } - t.currentStack = make([]*big.Int, sp) + currentStack := make([]*big.Int, sp) for i, v := range stack { if i >= sp { break } - t.currentStack[i] = new(big.Int).Set(v) + currentStack[i] = new(big.Int).Set(v) + } + + t.currentStack[len(t.currentStack)-1] = currentStack + + if opCode == evm.CALL || opCode == evm.STATICCALL { + t.currentStack = append(t.currentStack, make([]*big.Int, sp)) } } @@ -193,11 +212,16 @@ func (t *StructTracer) captureStorage( sp int, host tracer.RuntimeHost, ) { + if opCode == evm.CALL || opCode == evm.STATICCALL { + t.storage = append(t.storage, make(map[types.Address]map[types.Hash]types.Hash)) + } + if !t.Config.EnableStorage || (opCode != evm.SLOAD && opCode != evm.SSTORE) { return } - _, initialized := t.storage[contractAddress] + storage := &t.storage[len(t.storage)-1] + _, initialized := (*storage)[contractAddress] switch opCode { case evm.SLOAD: @@ -206,13 +230,13 @@ func (t *StructTracer) captureStorage( } if !initialized { - t.storage[contractAddress] = make(map[types.Hash]types.Hash) + (*storage)[contractAddress] = make(map[types.Hash]types.Hash) } slot := types.BytesToHash(stack[sp-1].Bytes()) value := host.GetStorage(contractAddress, slot) - t.storage[contractAddress][slot] = value + (*storage)[contractAddress][slot] = value case evm.SSTORE: if sp < 2 { @@ -220,13 +244,13 @@ func (t *StructTracer) captureStorage( } if !initialized { - t.storage[contractAddress] = make(map[types.Hash]types.Hash) + (*storage)[contractAddress] = make(map[types.Hash]types.Hash) } - slot := types.BytesToHash(stack[sp-2].Bytes()) - value := types.BytesToHash(stack[sp-1].Bytes()) + slot := types.BytesToHash(stack[sp-1].Bytes()) + value := types.BytesToHash(stack[sp-2].Bytes()) - t.storage[contractAddress][slot] = value + (*storage)[contractAddress][slot] = value } } @@ -250,16 +274,22 @@ func (t *StructTracer) ExecuteState( ) if t.Config.EnableMemory { - memorySize = len(t.currentMemory) + if opCode == evm.OpCode(evm.CALL).String() || opCode == evm.OpCode(evm.STATICCALL).String() { + t.currentMemory = t.currentMemory[:len(t.currentMemory)-1] + } + memorySize = len(t.currentMemory[len(t.currentMemory)-1]) memory = make([]byte, memorySize) - copy(memory, t.currentMemory) + copy(memory, t.currentMemory[len(t.currentMemory)-1]) } if t.Config.EnableStack { - stack = make([]*big.Int, len(t.currentStack)) + if opCode == evm.OpCode(evm.CALL).String() || opCode == evm.OpCode(evm.STATICCALL).String() { + t.currentStack = t.currentStack[:len(t.currentStack)-1] + } - for i, v := range t.currentStack { + stack = make([]*big.Int, len(t.currentStack[len(t.currentStack)-1])) + for i, v := range t.currentStack[len(t.currentStack)-1] { stack[i] = new(big.Int).Set(v) } } @@ -271,7 +301,12 @@ func (t *StructTracer) ExecuteState( } if t.Config.EnableStorage { - contractStorage, ok := t.storage[contractAddress] + if opCode == evm.OpCode(evm.CALL).String() || opCode == evm.OpCode(evm.STATICCALL).String() { + t.storage = t.storage[:len(t.storage)-1] + } + + contractStorage, ok := t.storage[len(t.storage)-1][contractAddress] + if ok { storage = make(map[types.Hash]types.Hash, len(contractStorage)) diff --git a/state/runtime/tracer/structtracer/tracer_test.go b/state/runtime/tracer/structtracer/tracer_test.go index f2660faedb..abbca4884d 100644 --- a/state/runtime/tracer/structtracer/tracer_test.go +++ b/state/runtime/tracer/structtracer/tracer_test.go @@ -131,16 +131,18 @@ func TestStructTracerClear(t *testing.T) { consumedGas: 512, output: []byte("output example"), err: runtime.ErrInsufficientBalance, - storage: map[types.Address]map[types.Hash]types.Hash{ - types.StringToAddress("1"): { - types.StringToHash("2"): types.StringToHash("3"), + storage: []map[types.Address]map[types.Hash]types.Hash{ + { + types.StringToAddress("1"): { + types.StringToHash("2"): types.StringToHash("3"), + }, }, }, - currentMemory: []byte("memory example"), - currentStack: []*big.Int{ + currentMemory: [][]byte{[]byte("memory example")}, + currentStack: []([]*big.Int){[]*big.Int{ new(big.Int).SetUint64(1), new(big.Int).SetUint64(2), - }, + }}, } tracer.Clear() @@ -154,16 +156,18 @@ func TestStructTracerClear(t *testing.T) { EnableStorage: true, EnableReturnData: true, }, - reason: nil, - interrupt: false, - logs: []StructLog{}, - gasLimit: 0, - consumedGas: 0, - output: []byte{}, - err: nil, - storage: map[types.Address]map[types.Hash]types.Hash{}, - currentMemory: []byte{}, - currentStack: []*big.Int{}, + reason: nil, + interrupt: false, + logs: []StructLog{}, + gasLimit: 0, + consumedGas: 0, + output: []byte{}, + err: nil, + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, + currentMemory: make([]([]byte), 1), + currentStack: make([]([]*big.Int), 1), }, tracer, ) @@ -183,9 +187,13 @@ func TestStructTracerTxStart(t *testing.T) { assert.Equal( t, &StructTracer{ - Config: testEmptyConfig, - storage: make(map[types.Address]map[types.Hash]types.Hash), - gasLimit: gasLimit, + Config: testEmptyConfig, + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, + gasLimit: gasLimit, + currentMemory: make([]([]byte), 1), + currentStack: make([]([]*big.Int), 1), }, tracer, ) @@ -207,10 +215,14 @@ func TestStructTracerTxEnd(t *testing.T) { assert.Equal( t, &StructTracer{ - Config: testEmptyConfig, - storage: make(map[types.Address]map[types.Hash]types.Hash), - gasLimit: gasLimit, - consumedGas: gasLimit - gasLeft, + Config: testEmptyConfig, + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, + gasLimit: gasLimit, + consumedGas: gasLimit - gasLeft, + currentMemory: make([]([]byte), 1), + currentStack: make([]([]*big.Int), 1), }, tracer, ) @@ -260,10 +272,14 @@ func TestStructTracerCallEnd(t *testing.T) { output: output, err: err, expected: &StructTracer{ - Config: testEmptyConfig, - storage: make(map[types.Address]map[types.Hash]types.Hash), - output: output, - err: err, + Config: testEmptyConfig, + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, + output: output, + err: err, + currentMemory: make([]([]byte), 1), + currentStack: make([]([]*big.Int), 1), }, }, { @@ -272,8 +288,12 @@ func TestStructTracerCallEnd(t *testing.T) { output: output, err: err, expected: &StructTracer{ - Config: testEmptyConfig, - storage: make(map[types.Address]map[types.Hash]types.Hash), + Config: testEmptyConfig, + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, + currentMemory: make([]([]byte), 1), + currentStack: make([]([]*big.Int), 1), }, }, } @@ -301,11 +321,11 @@ func TestStructTracerCaptureState(t *testing.T) { t.Parallel() var ( - memory = []byte("memory") - stack = []*big.Int{ - big.NewInt(1), - big.NewInt(2), - } + memory = [][]byte{[]byte("memory")} + stack = []([]*big.Int){[]*big.Int{ + big.NewInt(1), /* value */ + big.NewInt(2), /* key */ + }} contractAddress = types.StringToAddress("3") storageValue = types.StringToHash("4") ) @@ -317,8 +337,8 @@ func TestStructTracerCaptureState(t *testing.T) { tracer *StructTracer // input - memory []byte - stack []*big.Int + memory [][]byte + stack [][]*big.Int opCode int contractAddress types.Address sp int @@ -335,6 +355,7 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableMemory: true, }, + currentMemory: make([]([]byte), 1), }, memory: memory, stack: stack, @@ -359,6 +380,7 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStack: true, }, + currentStack: make([]([]*big.Int), 1), }, memory: memory, stack: stack, @@ -383,7 +405,9 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStorage: true, }, - storage: make(map[types.Address]map[types.Hash]types.Hash), + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, }, memory: memory, stack: stack, @@ -405,9 +429,11 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStorage: true, }, - storage: map[types.Address]map[types.Hash]types.Hash{ - contractAddress: { - types.BytesToHash(big.NewInt(2).Bytes()): storageValue, + storage: [](map[types.Address]map[types.Hash]types.Hash){ + map[types.Address]map[types.Hash]types.Hash{ + contractAddress: { + types.BytesToHash(big.NewInt(2).Bytes()): storageValue, + }, }, }, }, @@ -419,7 +445,9 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStorage: true, }, - storage: make(map[types.Address]map[types.Hash]types.Hash), + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, }, memory: memory, stack: stack, @@ -434,12 +462,13 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStorage: true, }, - storage: map[types.Address]map[types.Hash]types.Hash{ - contractAddress: { - types.BytesToHash(big.NewInt(1).Bytes()): types.BytesToHash(big.NewInt(2).Bytes()), + storage: []map[types.Address]map[types.Hash]types.Hash{ + { + contractAddress: { + types.BytesToHash(big.NewInt(2).Bytes()): types.BytesToHash(big.NewInt(1).Bytes()), + }, }, - }, - }, + }}, expectedVMState: &mockState{}, }, { @@ -471,7 +500,9 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStorage: true, }, - storage: make(map[types.Address]map[types.Hash]types.Hash), + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, }, memory: memory, stack: stack, @@ -486,7 +517,9 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStorage: true, }, - storage: map[types.Address]map[types.Hash]types.Hash{}, + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, }, expectedVMState: &mockState{}, }, @@ -496,7 +529,9 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStorage: true, }, - storage: make(map[types.Address]map[types.Hash]types.Hash), + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, }, memory: memory, stack: stack, @@ -511,7 +546,9 @@ func TestStructTracerCaptureState(t *testing.T) { Config: Config{ EnableStorage: true, }, - storage: map[types.Address]map[types.Hash]types.Hash{}, + storage: []map[types.Address]map[types.Hash]types.Hash{ + make(map[types.Address]map[types.Hash]types.Hash), + }, }, expectedVMState: &mockState{}, }, @@ -524,8 +561,8 @@ func TestStructTracerCaptureState(t *testing.T) { t.Parallel() test.tracer.CaptureState( - test.memory, - test.stack, + test.memory[0], + test.stack[0], test.opCode, test.contractAddress, test.sp, @@ -562,8 +599,8 @@ func TestStructTracerExecuteState(t *testing.T) { err = errors.New("err") refund = uint64(10000) - memory = []byte("memory sample") - storage = map[types.Address]map[types.Hash]types.Hash{ + memory = [][]byte{[]byte("memory sample")} + storage = []map[types.Address]map[types.Hash]types.Hash{{ contractAddress: { types.StringToHash("1"): types.StringToHash("2"), types.StringToHash("3"): types.StringToHash("4"), @@ -572,6 +609,7 @@ func TestStructTracerExecuteState(t *testing.T) { types.StringToHash("5"): types.StringToHash("6"), types.StringToHash("7"): types.StringToHash("8"), }, + }, } ) @@ -657,8 +695,8 @@ func TestStructTracerExecuteState(t *testing.T) { Op: opCode, Gas: availableGas, GasCost: cost, - Memory: memory, - MemorySize: len(memory), + Memory: memory[0], + MemorySize: len(memory[0]), Stack: nil, ReturnData: nil, Storage: nil, @@ -674,10 +712,10 @@ func TestStructTracerExecuteState(t *testing.T) { Config: Config{ EnableStack: true, }, - currentStack: []*big.Int{ + currentStack: [][]*big.Int{{ big.NewInt(1), big.NewInt(2), - }, + }}, }, contractAddress: contractAddress, ip: ip, diff --git a/state/state.go b/state/state.go index e63afaca01..1b45ec24b5 100644 --- a/state/state.go +++ b/state/state.go @@ -8,7 +8,6 @@ import ( iradix "github.com/hashicorp/go-immutable-radix" "github.com/umbracle/fastrlp" - "github.com/0xPolygon/polygon-edge/crypto" "github.com/0xPolygon/polygon-edge/types" ) @@ -102,8 +101,6 @@ func (a *Account) Copy() *Account { return aa } -var emptyCodeHash = crypto.Keccak256(nil) - // StateObject is the internal representation of the account type StateObject struct { Account *Account @@ -112,10 +109,16 @@ type StateObject struct { Deleted bool DirtyCode bool Txn *iradix.Txn + + // withFakeStorage signals whether the state object + // is using the override full state + withFakeStorage bool } func (s *StateObject) Empty() bool { - return s.Account.Nonce == 0 && s.Account.Balance.Sign() == 0 && bytes.Equal(s.Account.CodeHash, emptyCodeHash) + return s.Account.Nonce == 0 && + s.Account.Balance.Sign() == 0 && + bytes.Equal(s.Account.CodeHash, types.EmptyCodeHash.Bytes()) } // Copy makes a copy of the state object @@ -129,6 +132,7 @@ func (s *StateObject) Copy() *StateObject { ss.Deleted = s.Deleted ss.DirtyCode = s.DirtyCode ss.Code = s.Code + ss.withFakeStorage = s.withFakeStorage if s.Txn != nil { ss.Txn = s.Txn.CommitOnly().Txn() diff --git a/state/testing.go b/state/testing.go index 1edd754537..d5c9fcced6 100644 --- a/state/testing.go +++ b/state/testing.go @@ -5,30 +5,34 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/0xPolygon/polygon-edge/types" ) -var addr1 = types.StringToAddress("1") -var addr2 = types.StringToAddress("2") +var ( + addr1 = types.StringToAddress("1") + addr2 = types.StringToAddress("2") -var hash0 = types.StringToHash("0") -var hash1 = types.StringToHash("1") -var hash2 = types.StringToHash("2") + hash0 = types.StringToHash("0") + hash1 = types.StringToHash("1") + hash2 = types.StringToHash("2") -var defaultPreState = map[types.Address]*PreState{ - addr1: { - State: map[types.Hash]types.Hash{ - hash1: hash1, + defaultPreState = map[types.Address]*PreState{ + addr1: { + State: map[types.Hash]types.Hash{ + hash1: hash1, + }, }, - }, -} + } +) // PreState is the account prestate type PreState struct { - Nonce uint64 - Balance uint64 - State map[types.Hash]types.Hash + Nonce uint64 + Balance uint64 + State map[types.Hash]types.Hash + CodeHash []byte } // PreStates is a set of pre states @@ -41,66 +45,81 @@ func TestState(t *testing.T, buildPreState buildPreState) { t.Helper() t.Parallel() - t.Run("", func(t *testing.T) { + t.Run("write state", func(t *testing.T) { t.Parallel() testWriteState(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("write empty state", func(t *testing.T) { t.Parallel() testWriteEmptyState(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("update state with empty - delete empty objects", func(t *testing.T) { t.Parallel() - testUpdateStateWithEmpty(t, buildPreState) + testUpdateStateWithEmpty(t, buildPreState, true) }) - t.Run("", func(t *testing.T) { + t.Run("update state with empty - do not delete empty objects", func(t *testing.T) { + t.Parallel() + + testUpdateStateWithEmpty(t, buildPreState, false) + }) + t.Run("suicide account in pre-state", func(t *testing.T) { t.Parallel() testSuicideAccountInPreState(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("suicide account", func(t *testing.T) { t.Parallel() testSuicideAccount(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("suicide account with data", func(t *testing.T) { t.Parallel() testSuicideAccountWithData(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("suicide coinbase", func(t *testing.T) { t.Parallel() testSuicideCoinbase(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("suicide with intermediate commit", func(t *testing.T) { t.Parallel() testSuicideWithIntermediateCommit(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("restart refunds", func(t *testing.T) { t.Parallel() testRestartRefunds(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("change pre-state account balance to zero", func(t *testing.T) { t.Parallel() testChangePrestateAccountBalanceToZero(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("change account balance to zero", func(t *testing.T) { t.Parallel() testChangeAccountBalanceToZero(t, buildPreState) }) - t.Run("", func(t *testing.T) { + t.Run("delete common state root", func(t *testing.T) { t.Parallel() testDeleteCommonStateRoot(t, buildPreState) }) + t.Run("get code empty code hash", func(t *testing.T) { + t.Parallel() + + testGetCodeEmptyCodeHash(t, buildPreState) + }) + t.Run("set and get code", func(t *testing.T) { + t.Parallel() + + testSetAndGetCode(t, buildPreState) + }) } func testDeleteCommonStateRoot(t *testing.T, buildPreState buildPreState) { @@ -119,13 +138,19 @@ func testDeleteCommonStateRoot(t *testing.T, buildPreState buildPreState) { txn.SetState(addr2, hash1, hash1) txn.SetState(addr2, hash2, hash1) - snap2, _, _ := snap.Commit(txn.Commit(false)) + objs, err := txn.Commit(false) + require.NoError(t, err) + + snap2, _, _ := snap.Commit(objs) txn2 := newTxn(snap2) txn2.SetState(addr1, hash0, hash0) txn2.SetState(addr1, hash1, hash0) - snap3, _, _ := snap2.Commit(txn2.Commit(false)) + objs, err = txn2.Commit(false) + require.NoError(t, err) + + snap3, _, _ := snap2.Commit(objs) txn3 := newTxn(snap3) assert.Equal(t, hash1, txn3.GetState(addr1, hash2)) @@ -146,7 +171,10 @@ func testWriteState(t *testing.T, buildPreState buildPreState) { assert.Equal(t, hash1, txn.GetState(addr1, hash1)) assert.Equal(t, hash2, txn.GetState(addr1, hash2)) - snap, _, _ = snap.Commit(txn.Commit(false)) + objs, err := txn.Commit(false) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) assert.Equal(t, hash1, txn.GetState(addr1, hash1)) @@ -161,7 +189,11 @@ func testWriteEmptyState(t *testing.T, buildPreState buildPreState) { // Without EIP150 the data is added txn.SetState(addr1, hash1, hash0) - snap, _, _ = snap.Commit(txn.Commit(false)) + + objs, err := txn.Commit(false) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) assert.True(t, txn.Exist(addr1)) @@ -171,13 +203,17 @@ func testWriteEmptyState(t *testing.T, buildPreState buildPreState) { // With EIP150 the empty data is removed txn.SetState(addr1, hash1, hash0) - snap, _, _ = snap.Commit(txn.Commit(true)) + + objs, err = txn.Commit(true) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) } -func testUpdateStateWithEmpty(t *testing.T, buildPreState buildPreState) { +func testUpdateStateWithEmpty(t *testing.T, buildPreState buildPreState, deleteEmptyObjects bool) { t.Helper() // If the state (in prestate) is updated to empty it should be removed @@ -186,13 +222,38 @@ func testUpdateStateWithEmpty(t *testing.T, buildPreState buildPreState) { txn := newTxn(snap) txn.SetState(addr1, hash1, hash0) - //nolint:godox - // TODO, test with false (should not be deleted) (to be fixed in EVM-528) - // TODO, test with balance on the account and nonce (to be fixed in EVM-528) - snap, _, _ = snap.Commit(txn.Commit(true)) + objs, err := txn.Commit(deleteEmptyObjects) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) - assert.False(t, txn.Exist(addr1)) + assert.Equal(t, !deleteEmptyObjects, txn.Exist(addr1)) + + // if balance is set, no matter what is passed to deleteEmptyObjects, + // addr1 should exist in state objects of txn + txn.SetBalance(addr1, big.NewInt(100)) + + objs, err = txn.Commit(deleteEmptyObjects) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) + + txn = newTxn(snap) + assert.Equal(t, true, txn.Exist(addr1)) + + // if nonce is set, no matter what is passed to deleteEmptyObjects, + // addr1 should exist in state objects of txn + txn.SetBalance(addr1, big.NewInt(0)) + txn.SetNonce(addr1, 1) + + objs, err = txn.Commit(deleteEmptyObjects) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) + + txn = newTxn(snap) + assert.Equal(t, true, txn.Exist(addr1)) } func testSuicideAccountInPreState(t *testing.T, buildPreState buildPreState) { @@ -203,7 +264,11 @@ func testSuicideAccountInPreState(t *testing.T, buildPreState buildPreState) { txn := newTxn(snap) txn.Suicide(addr1) - snap, _, _ = snap.Commit(txn.Commit(true)) + + objs, err := txn.Commit(true) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) @@ -221,7 +286,10 @@ func testSuicideAccount(t *testing.T, buildPreState buildPreState) { // Note, even if has commit suicide it still exists in the current txn assert.True(t, txn.Exist(addr1)) - snap, _, _ = snap.Commit(txn.Commit(true)) + objs, err := txn.Commit(true) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) @@ -242,7 +310,11 @@ func testSuicideAccountWithData(t *testing.T, buildPreState buildPreState) { txn.SetState(addr1, hash1, hash1) txn.Suicide(addr1) - snap, _, _ = snap.Commit(txn.Commit(true)) + + objs, err := txn.Commit(true) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) @@ -265,7 +337,10 @@ func testSuicideCoinbase(t *testing.T, buildPreState buildPreState) { txn := newTxn(snap) txn.Suicide(addr1) txn.AddSealingReward(addr1, big.NewInt(10)) - snap, _, _ = snap.Commit(txn.Commit(true)) + objs, err := txn.Commit(true) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) assert.Equal(t, big.NewInt(10), txn.GetBalance(addr1)) @@ -282,10 +357,11 @@ func testSuicideWithIntermediateCommit(t *testing.T, buildPreState buildPreState assert.Equal(t, uint64(10), txn.GetNonce(addr1)) - txn.CleanDeleteObjects(true) + assert.NoError(t, txn.CleanDeleteObjects(true)) assert.Equal(t, uint64(0), txn.GetNonce(addr1)) - txn.Commit(true) + _, err := txn.Commit(true) + assert.NoError(t, err) assert.Equal(t, uint64(0), txn.GetNonce(addr1)) } @@ -300,7 +376,8 @@ func testRestartRefunds(t *testing.T, buildPreState buildPreState) { txn.AddRefund(1000) assert.Equal(t, uint64(1000), txn.GetRefund()) - txn.Commit(false) + _, err := txn.Commit(false) + assert.NoError(t, err) // refund should be empty after the commit assert.Equal(t, uint64(0), txn.GetRefund()) @@ -319,7 +396,11 @@ func testChangePrestateAccountBalanceToZero(t *testing.T, buildPreState buildPre txn := newTxn(snap) txn.SetBalance(addr1, big.NewInt(0)) - snap, _, _ = snap.Commit(txn.Commit(true)) + + objs, err := txn.Commit(true) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) @@ -334,8 +415,43 @@ func testChangeAccountBalanceToZero(t *testing.T, buildPreState buildPreState) { txn.SetBalance(addr1, big.NewInt(10)) txn.SetBalance(addr1, big.NewInt(0)) - snap, _, _ = snap.Commit(txn.Commit(true)) + objs, err := txn.Commit(true) + require.NoError(t, err) + + snap, _, _ = snap.Commit(objs) txn = newTxn(snap) assert.False(t, txn.Exist(addr1)) } + +func testGetCodeEmptyCodeHash(t *testing.T, buildPreState buildPreState) { + t.Helper() + + // If empty code hash is passed, it is considered as a valid case, + // and in that case we are not retrieving it from the storage. + snap := buildPreState(nil) + + code, ok := snap.GetCode(types.EmptyCodeHash) + assert.True(t, ok) + assert.Empty(t, code) +} + +func testSetAndGetCode(t *testing.T, buildPreState buildPreState) { + t.Helper() + + testCode := []byte{0x2, 0x4, 0x6, 0x8} + snap := buildPreState(nil) + + txn := newTxn(snap) + txn.SetCode(addr1, testCode) + + affectedObjs, err := txn.Commit(true) + require.NoError(t, err) + + snap, _, _ = snap.Commit(affectedObjs) + assert.Len(t, affectedObjs, 1) + + code, ok := snap.GetCode(affectedObjs[0].CodeHash) + assert.True(t, ok) + assert.Equal(t, testCode, code) +} diff --git a/state/txn.go b/state/txn.go index a8891299f4..ffb74b15f9 100644 --- a/state/txn.go +++ b/state/txn.go @@ -1,6 +1,7 @@ package state import ( + "errors" "fmt" "math/big" @@ -73,13 +74,15 @@ func (txn *Txn) Snapshot() int { } // RevertToSnapshot reverts to a given snapshot -func (txn *Txn) RevertToSnapshot(id int) { - if id > len(txn.snapshots) { - panic("") //nolint:gocritic +func (txn *Txn) RevertToSnapshot(id int) error { + if id > len(txn.snapshots)-1 { + return fmt.Errorf("snapshot id %d out of the range", id) } tree := txn.snapshots[id] txn.txn = tree.Txn() + + return nil } func (txn *Txn) getCompactJournal() map[types.Address]*types.JournalEntry { @@ -194,7 +197,7 @@ func (txn *Txn) upsertAccount(addr types.Address, create bool, f func(object *St object = &StateObject{ Account: &Account{ Balance: big.NewInt(0), - CodeHash: emptyCodeHash, + CodeHash: types.EmptyCodeHash.Bytes(), Root: emptyStateHash, }, } @@ -270,6 +273,7 @@ func (txn *Txn) GetBalance(addr types.Address) *big.Int { return object.Account.Balance } +// EmitLog appends log to logs tree storage func (txn *Txn) EmitLog(addr types.Address, topics []types.Hash, data []byte) { log := &types.Log{ Address: addr, @@ -290,25 +294,9 @@ func (txn *Txn) EmitLog(addr types.Address, topics []types.Hash, data []byte) { txn.txn.Insert(logIndex, logs) } -// AddLog adds a new log -func (txn *Txn) AddLog(log *types.Log) { - var logs []*types.Log - - data, exists := txn.txn.Get(logIndex) - if !exists { - logs = []*types.Log{} - } else { - logs = data.([]*types.Log) //nolint:forcetypeassert - } - - logs = append(logs, log) - txn.txn.Insert(logIndex, logs) -} - // State -var zeroHash types.Hash - +// SetStorage sets the storage of an address func (txn *Txn) SetStorage( addr types.Address, key types.Hash, @@ -328,9 +316,9 @@ func (txn *Txn) SetStorage( legacyGasMetering := !config.Istanbul && (config.Petersburg || !config.Constantinople) if legacyGasMetering { - if oldValue == zeroHash { + if oldValue == types.ZeroHash { return runtime.StorageAdded - } else if value == zeroHash { + } else if value == types.ZeroHash { txn.AddRefund(15000) return runtime.StorageDeleted @@ -340,11 +328,11 @@ func (txn *Txn) SetStorage( } if original == current { - if original == zeroHash { // create slot (2.1.1) + if original == types.ZeroHash { // create slot (2.1.1) return runtime.StorageAdded } - if value == zeroHash { // delete slot (2.1.2b) + if value == types.ZeroHash { // delete slot (2.1.2b) txn.AddRefund(15000) return runtime.StorageDeleted @@ -353,16 +341,16 @@ func (txn *Txn) SetStorage( return runtime.StorageModified } - if original != zeroHash { // Storage slot was populated before this transaction started - if current == zeroHash { // recreate slot (2.2.1.1) + if original != types.ZeroHash { // Storage slot was populated before this transaction started + if current == types.ZeroHash { // recreate slot (2.2.1.1) txn.SubRefund(15000) - } else if value == zeroHash { // delete slot (2.2.1.2) + } else if value == types.ZeroHash { // delete slot (2.2.1.2) txn.AddRefund(15000) } } if original == value { - if original == zeroHash { // reset to original nonexistent slot (2.2.2.1) + if original == types.ZeroHash { // reset to original nonexistent slot (2.2.2.1) // Storage was used as memory (allocation and deallocation occurred within the same contract) if config.Istanbul { txn.AddRefund(19200) @@ -392,7 +380,7 @@ func (txn *Txn) SetState( object.Txn = iradix.New().Txn() } - if value == zeroHash { + if value == types.ZeroHash { object.Txn.Insert(key.Bytes(), nil) } else { object.Txn.Insert(key.Bytes(), value.Bytes()) @@ -434,6 +422,10 @@ func (txn *Txn) GetState(addr types.Address, key types.Hash) types.Hash { } } + if object.withFakeStorage { + return types.Hash{} + } + return txn.snapshot.GetStorage(addr, object.Account.Root, key) } @@ -480,6 +472,7 @@ func (txn *Txn) SetCode(addr types.Address, code []byte) { }) } +// GetCode gets the code on a given address func (txn *Txn) GetCode(addr types.Address) []byte { object, exists := txn.getStateObject(addr) if !exists { @@ -602,6 +595,18 @@ func (txn *Txn) GetCommittedState(addr types.Address, key types.Hash) types.Hash return txn.snapshot.GetStorage(addr, obj.Account.Root, key) } +// SetFullStorage is used to replace the full state of the address. +// Only used for debugging on the override jsonrpc endpoint. +func (txn *Txn) SetFullStorage(addr types.Address, state map[types.Hash]types.Hash) { + for k, v := range state { + txn.SetState(addr, k, v) + } + + txn.upsertAccount(addr, true, func(object *StateObject) { + object.withFakeStorage = true + }) +} + func (txn *Txn) TouchAccount(addr types.Address) { txn.upsertAccount(addr, true, func(obj *StateObject) { txn.addJournalEntry(&types.JournalEntry{ @@ -611,9 +616,6 @@ func (txn *Txn) TouchAccount(addr types.Address) { }) } -//nolint:godox -// TODO, check panics with this ones (to be fixed in EVM-528) - func (txn *Txn) Exist(addr types.Address) bool { _, exists := txn.getStateObject(addr) @@ -633,7 +635,7 @@ func newStateObject() *StateObject { return &StateObject{ Account: &Account{ Balance: big.NewInt(0), - CodeHash: emptyCodeHash, + CodeHash: types.EmptyCodeHash.Bytes(), Root: emptyStateHash, }, } @@ -643,7 +645,7 @@ func (txn *Txn) CreateAccount(addr types.Address) { obj := &StateObject{ Account: &Account{ Balance: big.NewInt(0), - CodeHash: emptyCodeHash, + CodeHash: types.EmptyCodeHash.Bytes(), Root: emptyStateHash, }, } @@ -656,7 +658,7 @@ func (txn *Txn) CreateAccount(addr types.Address) { txn.txn.Insert(addr.Bytes(), obj) } -func (txn *Txn) CleanDeleteObjects(deleteEmptyObjects bool) { +func (txn *Txn) CleanDeleteObjects(deleteEmptyObjects bool) error { remove := [][]byte{} txn.txn.Root().Walk(func(k []byte, v interface{}) bool { @@ -674,13 +676,12 @@ func (txn *Txn) CleanDeleteObjects(deleteEmptyObjects bool) { for _, k := range remove { v, ok := txn.txn.Get(k) if !ok { - panic("it should not happen") //nolint:gocritic + return fmt.Errorf("failed to retrieve value for %s key", string(k)) } obj, ok := v.(*StateObject) - if !ok { - panic("it should not happen") //nolint:gocritic + return errors.New("found object is not of StateObject type") } obj2 := obj.Copy() @@ -690,10 +691,14 @@ func (txn *Txn) CleanDeleteObjects(deleteEmptyObjects bool) { // delete refunds txn.txn.Delete(refundIndex) + + return nil } -func (txn *Txn) Commit(deleteEmptyObjects bool) []*Object { - txn.CleanDeleteObjects(deleteEmptyObjects) +func (txn *Txn) Commit(deleteEmptyObjects bool) ([]*Object, error) { + if err := txn.CleanDeleteObjects(deleteEmptyObjects); err != nil { + return nil, err + } x := txn.txn.Commit() @@ -739,5 +744,5 @@ func (txn *Txn) Commit(deleteEmptyObjects bool) []*Object { return false }) - return objs + return objs, nil } diff --git a/state/txn_test.go b/state/txn_test.go index 2cc9272814..03be318501 100644 --- a/state/txn_test.go +++ b/state/txn_test.go @@ -43,10 +43,14 @@ func (m *mockSnapshot) GetAccount(addr types.Address) (*Account, error) { } func (m *mockSnapshot) GetCode(hash types.Hash) ([]byte, bool) { - return []byte{0x1}, true + return nil, true } -func newStateWithPreState(preState map[types.Address]*PreState) readSnapshot { +func (m *mockSnapshot) Commit(objs []*Object) (Snapshot, *types.Trace, []byte) { + return nil, nil, nil +} + +func newStateWithPreState(preState map[types.Address]*PreState) Snapshot { return &mockSnapshot{state: preState} } @@ -64,7 +68,7 @@ func TestSnapshotUpdateData(t *testing.T) { txn.SetState(addr1, hash1, hash2) assert.Equal(t, hash2, txn.GetState(addr1, hash1)) - txn.RevertToSnapshot(ss) + assert.NoError(t, txn.RevertToSnapshot(ss)) assert.Equal(t, hash1, txn.GetState(addr1, hash1)) } @@ -85,10 +89,11 @@ func TestTxn_TracesCompaction(t *testing.T) { txn.SetState(addr, types.ZeroHash, oneHash) // updates txn.SetState(addr, oneHash, types.ZeroHash) + txn.SetCode(addr, []byte{0x1}) txn.GetCode(addr) txn.TouchAccount(addr) - require.Len(t, txn.journal, 18) + require.Len(t, txn.journal, 20) trace := txn.getCompactJournal() require.Len(t, trace, 1) @@ -102,6 +107,7 @@ func TestTxn_TracesCompaction(t *testing.T) { types.ZeroHash: oneHash, oneHash: types.ZeroHash, }, + Code: []byte{0x1}, CodeRead: []byte{0x1}, Touched: boolTruePtr(), Read: boolTruePtr(), diff --git a/syncer/client.go b/syncer/client.go index 916de61654..3e0c3c6029 100644 --- a/syncer/client.go +++ b/syncer/client.go @@ -14,6 +14,7 @@ import ( "github.com/0xPolygon/polygon-edge/network/event" "github.com/0xPolygon/polygon-edge/syncer/proto" "github.com/0xPolygon/polygon-edge/types" + "github.com/armon/go-metrics" "github.com/hashicorp/go-hclog" "github.com/libp2p/go-libp2p/core/peer" "google.golang.org/protobuf/types/known/emptypb" @@ -38,7 +39,10 @@ type syncPeerClient struct { shouldEmitBlocks bool // flag for emitting blocks in the topic closeCh chan struct{} - closed *uint64 // ACTIVE == 0, CLOSED == non-zero. + closed atomic.Bool + + peerStatusUpdateChLock sync.Mutex + peerStatusUpdateChClosed bool } func NewSyncPeerClient( @@ -55,14 +59,16 @@ func NewSyncPeerClient( peerConnectionUpdateCh: make(chan *event.PeerEvent, 1), shouldEmitBlocks: true, closeCh: make(chan struct{}), - closed: new(uint64), + + peerStatusUpdateChLock: sync.Mutex{}, + peerStatusUpdateChClosed: false, } } // Start processes for SyncPeerClient func (m *syncPeerClient) Start() error { // Mark client active. - atomic.StoreUint64(m.closed, 0) + m.closed.Store(false) go m.startNewBlockProcess() go m.startPeerEventProcess() @@ -76,7 +82,7 @@ func (m *syncPeerClient) Start() error { // Close terminates running processes for SyncPeerClient func (m *syncPeerClient) Close() { - if atomic.SwapUint64(m.closed, 1) > 0 { + if m.closed.Swap(true) { // Already closed. return } @@ -95,7 +101,10 @@ func (m *syncPeerClient) Close() { close(m.closeCh) } + m.peerStatusUpdateChLock.Lock() + m.peerStatusUpdateChClosed = true close(m.peerStatusUpdateCh) + m.peerStatusUpdateChLock.Unlock() } // DisablePublishingPeerStatus disables publishing own status via gossip @@ -210,16 +219,15 @@ func (m *syncPeerClient) handleStatusUpdate(obj interface{}, from peer.ID) { return } - if atomic.LoadUint64(m.closed) > 0 { - m.logger.Debug("received status from peer after client was closed, ignoring", "id", from) - - return - } + m.peerStatusUpdateChLock.Lock() + defer m.peerStatusUpdateChLock.Unlock() - m.peerStatusUpdateCh <- &NoForkPeer{ - ID: from, - Number: status.Number, - Distance: m.network.GetPeerDistance(from), + if !m.peerStatusUpdateChClosed { + m.peerStatusUpdateCh <- &NoForkPeer{ + ID: from, + Number: status.Number, + Distance: m.network.GetPeerDistance(from), + } } } @@ -373,6 +381,7 @@ func blockStreamToChannel(stream proto.SyncPeer_GetBlocksClient) (<-chan *types. } if err != nil { + metrics.IncrCounter([]string{syncerMetrics, "bad_message"}, 1) errorCh <- err break @@ -380,11 +389,14 @@ func blockStreamToChannel(stream proto.SyncPeer_GetBlocksClient) (<-chan *types. block, err := fromProto(protoBlock) if err != nil { + metrics.IncrCounter([]string{syncerMetrics, "bad_block"}, 1) errorCh <- err break } + metrics.SetGauge([]string{syncerMetrics, "ingress_bytes"}, float32(len(protoBlock.Block))) + blockCh <- block } }() diff --git a/syncer/client_test.go b/syncer/client_test.go index 9da920116e..9a35d68998 100644 --- a/syncer/client_test.go +++ b/syncer/client_test.go @@ -45,7 +45,6 @@ func newTestSyncPeerClient(network Network, blockchain Blockchain) *syncPeerClie id: network.AddrInfo().ID.String(), peerStatusUpdateCh: make(chan *NoForkPeer, 1), peerConnectionUpdateCh: make(chan *event.PeerEvent, 1), - closed: new(uint64), } // need to register protocol @@ -231,6 +230,7 @@ func TestStatusPubSub(t *testing.T) { } func TestPeerConnectionUpdateEventCh(t *testing.T) { + t.Skip() t.Parallel() var ( @@ -354,7 +354,7 @@ func TestPeerConnectionUpdateEventCh(t *testing.T) { wgForGossip.Wait() // close to terminate goroutine - close(client.peerStatusUpdateCh) + client.Close() // wait until collecting routine is done wgForConnectingStatus.Wait() @@ -577,10 +577,12 @@ func Test_EmitMultipleBlocks(t *testing.T) { waitForGossip := func(wg *sync.WaitGroup) bool { c := make(chan struct{}) + go func() { defer close(c) wg.Wait() }() + select { case <-c: return true diff --git a/syncer/service.go b/syncer/service.go index 4b88ca4192..1e874f6e85 100644 --- a/syncer/service.go +++ b/syncer/service.go @@ -7,6 +7,7 @@ import ( "github.com/0xPolygon/polygon-edge/network/grpc" "github.com/0xPolygon/polygon-edge/syncer/proto" "github.com/0xPolygon/polygon-edge/types" + "github.com/armon/go-metrics" "github.com/golang/protobuf/ptypes/empty" ) @@ -64,6 +65,7 @@ func (s *syncPeerService) GetBlocks( } resp := toProtoBlock(block) + metrics.SetGauge([]string{syncerMetrics, "egress_bytes"}, float32(len(resp.Block))) // if client closes stream, context.Canceled is given if err := stream.Send(resp); err != nil { diff --git a/syncer/syncer.go b/syncer/syncer.go index 6a3c32ffed..55ec6de554 100644 --- a/syncer/syncer.go +++ b/syncer/syncer.go @@ -8,6 +8,7 @@ import ( "github.com/0xPolygon/polygon-edge/helper/progress" "github.com/0xPolygon/polygon-edge/network/event" "github.com/0xPolygon/polygon-edge/types" + "github.com/armon/go-metrics" "github.com/hashicorp/go-hclog" "github.com/libp2p/go-libp2p/core/peer" ) @@ -240,13 +241,18 @@ func (s *syncer) bulkSyncWithPeer(peerID peer.ID, newBlockCallback func(*types.F fullBlock, err := s.blockchain.VerifyFinalizedBlock(block) if err != nil { + metrics.IncrCounter([]string{syncerMetrics, "bad_block"}, 1) + return lastReceivedNumber, false, fmt.Errorf("unable to verify block, %w", err) } if err := s.blockchain.WriteFullBlock(fullBlock, syncerName); err != nil { + metrics.IncrCounter([]string{syncerMetrics, "bad_block"}, 1) + return lastReceivedNumber, false, fmt.Errorf("failed to write block while bulk syncing: %w", err) } + updateMetrics(fullBlock) shouldTerminate = newBlockCallback(fullBlock) lastReceivedNumber = block.Number() @@ -255,3 +261,9 @@ func (s *syncer) bulkSyncWithPeer(peerID peer.ID, newBlockCallback func(*types.F } } } + +func updateMetrics(fullBlock *types.FullBlock) { + metrics.SetGauge([]string{syncerMetrics, "tx_num"}, float32(len(fullBlock.Block.Transactions))) + metrics.SetGauge([]string{syncerMetrics, "receipts_num"}, float32(len(fullBlock.Receipts))) + metrics.SetGauge([]string{syncerMetrics, "blocks_num"}, 1) +} diff --git a/syncer/types.go b/syncer/types.go index 3b4c6628d6..7fe61522da 100644 --- a/syncer/types.go +++ b/syncer/types.go @@ -16,6 +16,8 @@ import ( "google.golang.org/protobuf/proto" ) +const syncerMetrics = "syncer" + type Blockchain interface { // SubscribeEvents subscribes new blockchain event SubscribeEvents() blockchain.Subscription diff --git a/tests/evm_test.go b/tests/evm_test.go deleted file mode 100644 index eaab30ec1e..0000000000 --- a/tests/evm_test.go +++ /dev/null @@ -1,193 +0,0 @@ -package tests - -import ( - "encoding/json" - "math/big" - "os" - "strings" - "testing" - - "github.com/0xPolygon/polygon-edge/chain" - "github.com/0xPolygon/polygon-edge/crypto" - "github.com/0xPolygon/polygon-edge/helper/hex" - "github.com/0xPolygon/polygon-edge/helper/keccak" - "github.com/0xPolygon/polygon-edge/state" - "github.com/0xPolygon/polygon-edge/state/runtime" - "github.com/0xPolygon/polygon-edge/state/runtime/evm" - "github.com/0xPolygon/polygon-edge/types" - "github.com/hashicorp/go-hclog" - "github.com/umbracle/fastrlp" -) - -var mainnetChainConfig = chain.Params{ - Forks: &chain.Forks{ - Homestead: chain.NewFork(1150000), - EIP150: chain.NewFork(2463000), - EIP158: chain.NewFork(2675000), - Byzantium: chain.NewFork(4370000), - }, -} - -var vmTests = "VMTests" - -type VMCase struct { - Info *info `json:"_info"` - Env *env `json:"env"` - Exec *exec `json:"exec"` - - Gas string `json:"gas"` - Logs string `json:"logs"` - Out string `json:"out"` - - Post map[types.Address]*chain.GenesisAccount `json:"post"` - Pre map[types.Address]*chain.GenesisAccount `json:"pre"` -} - -func testVMCase(t *testing.T, name string, c *VMCase) { - t.Helper() - - env := c.Env.ToEnv(t) - env.GasPrice = types.BytesToHash(c.Exec.GasPrice.Bytes()) - env.Origin = c.Exec.Origin - - s, _, root := buildState(c.Pre) - - config := mainnetChainConfig.Forks.At(uint64(env.Number)) - - executor := state.NewExecutor(&mainnetChainConfig, s, hclog.NewNullLogger()) - executor.GetHash = func(*types.Header) func(i uint64) types.Hash { - return vmTestBlockHash - } - - e, _ := executor.BeginTxn(root, c.Env.ToHeader(t), env.Coinbase) - ctx := e.ContextPtr() - ctx.GasPrice = types.BytesToHash(env.GasPrice.Bytes()) - ctx.Origin = env.Origin - - evmR := evm.NewEVM() - - code := e.GetCode(c.Exec.Address) - contract := runtime.NewContractCall( - 1, - c.Exec.Caller, - c.Exec.Caller, - c.Exec.Address, - c.Exec.Value, - c.Exec.GasLimit, - code, - c.Exec.Data, - ) - - result := evmR.Run(contract, e, &config) - - if c.Gas == "" { - if result.Succeeded() { - t.Fatalf("gas unspecified (indicating an error), but VM returned no error") - } - - if result.GasLeft > 0 { - t.Fatalf("gas unspecified (indicating an error), but VM returned gas remaining > 0") - } - - return - } - - // check return - if c.Out == "" { - c.Out = "0x" - } - - if ret := hex.EncodeToHex(result.ReturnValue); ret != c.Out { - t.Fatalf("return mismatch: got %s, want %s", ret, c.Out) - } - - txn := e.Txn() - - // check logs - if logs := rlpHashLogs(txn.Logs()); logs != types.StringToHash(c.Logs) { - t.Fatalf("logs hash mismatch: got %x, want %x", logs, c.Logs) - } - - // check state - for addr, alloc := range c.Post { - for key, val := range alloc.Storage { - if have := txn.GetState(addr, key); have != val { - t.Fatalf("wrong storage value at %s:\n got %s\n want %s\n at address %s", key, have, val, addr) - } - } - } - - // check remaining gas - if expected := stringToUint64T(t, c.Gas); result.GasLeft != expected { - t.Fatalf("gas left mismatch: got %d want %d", result.GasLeft, expected) - } -} - -func rlpHashLogs(logs []*types.Log) (res types.Hash) { - r := &types.Receipt{ - Logs: logs, - } - - ar := &fastrlp.Arena{} - v := r.MarshalLogsWith(ar) - - keccak.Keccak256Rlp(res[:0], v) - - return -} - -func TestEVM(t *testing.T) { - t.Parallel() - - folders, err := listFolders(vmTests) - if err != nil { - t.Fatal(err) - } - - long := []string{ - "loop-", - "gasprice", - "origin", - } - - for _, folder := range folders { - files, err := listFiles(folder) - if err != nil { - t.Fatal(err) - } - - for _, file := range files { - file := file - t.Run(file, func(t *testing.T) { - t.Parallel() - - if !strings.HasSuffix(file, ".json") { - return - } - - data, err := os.ReadFile(file) - if err != nil { - t.Fatal(err) - } - - var vmcases map[string]*VMCase - if err := json.Unmarshal(data, &vmcases); err != nil { - t.Fatal(err) - } - - for name, cc := range vmcases { - if contains(long, name) && testing.Short() { - t.Skip() - - continue - } - testVMCase(t, name, cc) - } - }) - } - } -} - -func vmTestBlockHash(n uint64) types.Hash { - return types.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String()))) -} diff --git a/tests/state_test.go b/tests/state_test.go index 44d48ba2ae..7be5b1814b 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -13,42 +13,63 @@ import ( "github.com/0xPolygon/polygon-edge/state" "github.com/0xPolygon/polygon-edge/types" "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/require" ) -var ( - stateTests = "GeneralStateTests" - legacyStateTests = "LegacyTests/Constantinople/GeneralStateTests" -) +// Currently used test cases suite version is v10.4. +// It does not include Merge hardfork test cases. -type stateCase struct { - Info *info `json:"_info"` - Env *env `json:"env"` - Pre map[types.Address]*chain.GenesisAccount `json:"pre"` - Post map[string]postState `json:"post"` - Transaction *stTransaction `json:"transaction"` -} +const ( + stateTests = "tests/GeneralStateTests" + legacyStateTests = "tests/LegacyTests/Constantinople/GeneralStateTests" + testGenesisBaseFee = 0x0a +) -var ripemd = types.StringToAddress("0000000000000000000000000000000000000003") +var ( + ripemd = types.StringToAddress("0000000000000000000000000000000000000003") +) -func RunSpecificTest(t *testing.T, file string, c stateCase, name, fork string, index int, p postEntry) { +func RunSpecificTest(t *testing.T, file string, c testCase, name, fork string, index int, p postEntry) { t.Helper() config, ok := Forks[fork] if !ok { - t.Fatalf("config %s not found", fork) + t.Skipf("%s fork is not supported", fork) + + return } env := c.Env.ToEnv(t) - msg, err := c.Transaction.At(p.Indexes) + var baseFee *big.Int + + if config.IsActive(chain.London, 0) { + if c.Env.BaseFee != "" { + baseFee = stringToBigIntT(t, c.Env.BaseFee) + } else { + // Retesteth uses `10` for genesis baseFee. Therefore, it defaults to + // parent - 2 : 0xa as the basefee for 'this' context. + baseFee = big.NewInt(testGenesisBaseFee) + } + } + + msg, err := c.Transaction.At(p.Indexes, baseFee) if err != nil { - t.Fatal(err) + t.Fatalf("failed to create transaction: %v", err) } - s, snapshot, pastRoot := buildState(c.Pre) + s, snapshot, pastRoot, err := buildState(c.Pre) + require.NoError(t, err) + forks := config.At(uint64(env.Number)) - xxx := state.NewExecutor(&chain.Params{Forks: config, ChainID: 1}, s, hclog.NewNullLogger()) + xxx := state.NewExecutor(&chain.Params{ + Forks: config, + ChainID: 1, + BurnContract: map[uint64]types.Address{ + 0: types.ZeroAddress, + }, + }, s, hclog.NewNullLogger()) xxx.PostHook = func(t *state.Transition) { if name == "failed_tx_xcf416c53" { @@ -70,9 +91,12 @@ func RunSpecificTest(t *testing.T, file string, c stateCase, name, fork string, // mining rewards txn.AddSealingReward(env.Coinbase, big.NewInt(0)) - objs := txn.Commit(forks.EIP155) + objs, err := txn.Commit(forks.EIP155) + require.NoError(t, err) + _, _, root := snapshot.Commit(objs) + // Check block root if !bytes.Equal(root, p.Root.Bytes()) { t.Fatalf( "root mismatch (%s %s %s %d): expected %s but found %s", @@ -85,6 +109,7 @@ func RunSpecificTest(t *testing.T, file string, c stateCase, name, fork string, ) } + // Check transaction logs if logs := rlpHashLogs(txn.Logs()); logs != p.Logs { t.Fatalf( "logs mismatch (%s, %s %d): expected %s but found %s", @@ -151,12 +176,12 @@ func TestState(t *testing.T) { t.Fatal(err) } - var c map[string]stateCase - if err := json.Unmarshal(data, &c); err != nil { - t.Fatal(err) + var testCases map[string]testCase + if err = json.Unmarshal(data, &testCases); err != nil { + t.Fatalf("failed to unmarshal %s: %v", file, err) } - for name, i := range c { + for name, i := range testCases { for fork, f := range i.Post { for indx, e := range f { RunSpecificTest(t, file, i, name, fork, indx, e) diff --git a/tests/testing.go b/tests/testing.go index 35edec5650..4031cf12fe 100644 --- a/tests/testing.go +++ b/tests/testing.go @@ -1,35 +1,38 @@ package tests import ( + "embed" "encoding/json" "fmt" + "io/fs" "math/big" "os" "path/filepath" "strings" "testing" + "github.com/umbracle/fastrlp" + "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/crypto" + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/hex" + "github.com/0xPolygon/polygon-edge/helper/keccak" "github.com/0xPolygon/polygon-edge/state" itrie "github.com/0xPolygon/polygon-edge/state/immutable-trie" "github.com/0xPolygon/polygon-edge/state/runtime" "github.com/0xPolygon/polygon-edge/types" ) -// TESTS is the default location of the tests folder -const TESTS = "./tests" - -type info struct { - Comment string `json:"comment"` - FilledWith string `json:"filledwith"` - LllcVersion string `json:"lllcversion"` - Source string `json:"source"` - SourceHash string `json:"sourcehash"` +type testCase struct { + Env *env `json:"env"` + Pre map[types.Address]*chain.GenesisAccount `json:"pre"` + Post map[string]postState `json:"post"` + Transaction *stTransaction `json:"transaction"` } type env struct { + BaseFee string `json:"currentBaseFee"` Coinbase string `json:"currentCoinbase"` Difficulty string `json:"currentDifficulty"` GasLimit string `json:"currentGasLimit"` @@ -81,6 +84,17 @@ func stringToBigInt(str string) (*big.Int, error) { return n, nil } +func stringToBigIntT(t *testing.T, str string) *big.Int { + t.Helper() + + number, err := stringToBigInt(str) + if err != nil { + t.Fatal(err) + } + + return number +} + func stringToAddressT(t *testing.T, str string) types.Address { t.Helper() @@ -137,10 +151,14 @@ func stringToInt64T(t *testing.T, str string) int64 { func (e *env) ToHeader(t *testing.T) *types.Header { t.Helper() - miner := stringToAddressT(t, e.Coinbase) + baseFee := uint64(0) + if e.BaseFee != "" { + baseFee = stringToUint64T(t, e.BaseFee) + } return &types.Header{ - Miner: miner[:], + Miner: stringToAddressT(t, e.Coinbase).Bytes(), + BaseFee: baseFee, Difficulty: stringToUint64T(t, e.Difficulty), GasLimit: stringToUint64T(t, e.GasLimit), Number: stringToUint64T(t, e.Number), @@ -151,8 +169,14 @@ func (e *env) ToHeader(t *testing.T) *types.Header { func (e *env) ToEnv(t *testing.T) runtime.TxContext { t.Helper() + baseFee := new(big.Int) + if e.BaseFee != "" { + baseFee = stringToBigIntT(t, e.BaseFee) + } + return runtime.TxContext{ Coinbase: stringToAddressT(t, e.Coinbase), + BaseFee: baseFee, Difficulty: stringToHashT(t, e.Difficulty), GasLimit: stringToInt64T(t, e.GasLimit), Number: stringToInt64T(t, e.Number), @@ -160,71 +184,9 @@ func (e *env) ToEnv(t *testing.T) runtime.TxContext { } } -type exec struct { - Address types.Address - Caller types.Address - Origin types.Address - Code []byte - Data []byte - Value *big.Int - GasLimit uint64 - GasPrice *big.Int -} - -func (e *exec) UnmarshalJSON(input []byte) error { - type execUnmarshall struct { - Address types.Address `json:"address"` - Caller types.Address `json:"caller"` - Origin types.Address `json:"origin"` - Code string `json:"code"` - Data string `json:"data"` - Value string `json:"value"` - Gas string `json:"gas"` - GasPrice string `json:"gasPrice"` - } - - var dec execUnmarshall - err := json.Unmarshal(input, &dec) - - if err != nil { - return err - } - - e.Address = dec.Address - e.Caller = dec.Caller - e.Origin = dec.Origin - - e.Code, err = types.ParseBytes(&dec.Code) - if err != nil { - return err - } - - e.Data, err = types.ParseBytes(&dec.Data) - if err != nil { - return err - } - - e.Value, err = types.ParseUint256orHex(&dec.Value) - if err != nil { - return err - } - - e.GasLimit, err = types.ParseUint64orHex(&dec.Gas) - if err != nil { - return err - } - - e.GasPrice, err = types.ParseUint256orHex(&dec.GasPrice) - if err != nil { - return err - } - - return nil -} - func buildState( allocs map[types.Address]*chain.GenesisAccount, -) (state.State, state.Snapshot, types.Hash) { +) (state.State, state.Snapshot, types.Hash, error) { s := itrie.NewState(itrie.NewMemoryStorage()) snap := s.NewSnapshot() @@ -244,10 +206,14 @@ func buildState( } } - objs := txn.Commit(false) + objs, err := txn.Commit(false) + if err != nil { + return nil, nil, types.ZeroHash, err + } + snap, _, root := snap.Commit(objs) - return s, snap, types.BytesToHash(root) + return s, snap, types.BytesToHash(root), nil } type indexes struct { @@ -260,6 +226,7 @@ type postEntry struct { Root types.Hash Logs types.Hash Indexes indexes + TxBytes []byte } type postState []postEntry @@ -269,6 +236,7 @@ func (p *postEntry) UnmarshalJSON(input []byte) error { Root string `json:"hash"` Logs string `json:"logs"` Indexes indexes `json:"indexes"` + TxBytes string `json:"txbytes"` } var dec stateUnmarshall @@ -279,21 +247,24 @@ func (p *postEntry) UnmarshalJSON(input []byte) error { p.Root = types.StringToHash(dec.Root) p.Logs = types.StringToHash(dec.Logs) p.Indexes = dec.Indexes + p.TxBytes = types.StringToBytes(dec.TxBytes) return nil } type stTransaction struct { - Data []string `json:"data"` - GasLimit []uint64 `json:"gasLimit"` - Value []*big.Int `json:"value"` - GasPrice *big.Int `json:"gasPrice"` - Nonce uint64 `json:"nonce"` - From types.Address `json:"secretKey"` - To *types.Address `json:"to"` + Data []string `json:"data"` + GasLimit []uint64 `json:"gasLimit"` + Value []*big.Int `json:"value"` + GasPrice *big.Int `json:"gasPrice"` + MaxFeePerGas *big.Int `json:"maxFeePerGas"` + MaxPriorityFeePerGas *big.Int `json:"maxPriorityFeePerGas"` + Nonce uint64 `json:"nonce"` + From types.Address `json:"secretKey"` + To *types.Address `json:"to"` } -func (t *stTransaction) At(i indexes) (*types.Transaction, error) { +func (t *stTransaction) At(i indexes, baseFee *big.Int) (*types.Transaction, error) { if i.Data > len(t.Data) { return nil, fmt.Errorf("data index %d out of bounds (%d)", i.Data, len(t.Data)) } @@ -306,46 +277,65 @@ func (t *stTransaction) At(i indexes) (*types.Transaction, error) { return nil, fmt.Errorf("value index %d out of bounds (%d)", i.Value, len(t.Value)) } - msg := &types.Transaction{ - To: t.To, - Nonce: t.Nonce, - Value: new(big.Int).Set(t.Value[i.Value]), - Gas: t.GasLimit[i.Gas], - GasPrice: new(big.Int).Set(t.GasPrice), - Input: hex.MustDecodeHex(t.Data[i.Data]), - } + gasPrice := t.GasPrice + + // If baseFee provided, set gasPrice to effectiveGasPrice. + if baseFee != nil { + if t.MaxFeePerGas == nil { + t.MaxFeePerGas = gasPrice + } - msg.From = t.From + if t.MaxFeePerGas == nil { + t.MaxFeePerGas = new(big.Int) + } - return msg, nil + if t.MaxPriorityFeePerGas == nil { + t.MaxPriorityFeePerGas = t.MaxFeePerGas + } + + gasPrice = common.BigMin(new(big.Int).Add(t.MaxPriorityFeePerGas, baseFee), t.MaxFeePerGas) + } + + return &types.Transaction{ + From: t.From, + To: t.To, + Nonce: t.Nonce, + Value: new(big.Int).Set(t.Value[i.Value]), + Gas: t.GasLimit[i.Gas], + GasPrice: new(big.Int).Set(gasPrice), + GasFeeCap: t.MaxFeePerGas, + GasTipCap: t.MaxPriorityFeePerGas, + Input: hex.MustDecodeHex(t.Data[i.Data]), + }, nil } func (t *stTransaction) UnmarshalJSON(input []byte) error { type txUnmarshall struct { - Data []string `json:"data"` - GasLimit []string `json:"gasLimit"` - Value []string `json:"value"` - GasPrice string `json:"gasPrice"` - Nonce string `json:"nonce"` - SecretKey string `json:"secretKey"` - To string `json:"to"` + Data []string `json:"data,omitempty"` + GasLimit []string `json:"gasLimit,omitempty"` + Value []string `json:"value,omitempty"` + GasPrice string `json:"gasPrice,omitempty"` + MaxFeePerGas string `json:"maxFeePerGas,omitempty"` + MaxPriorityFeePerGas string `json:"maxPriorityFeePerGas,omitempty"` + Nonce string `json:"nonce,omitempty"` + SecretKey string `json:"secretKey,omitempty"` + To string `json:"to,omitempty"` } var dec txUnmarshall - err := json.Unmarshal(input, &dec) - - if err != nil { - return err + if err := json.Unmarshal(input, &dec); err != nil { + return fmt.Errorf("failed to unmarshal transaction into temporary struct: %w", err) } t.Data = dec.Data for _, i := range dec.GasLimit { - if j, err := stringToUint64(i); err != nil { - return err - } else { - t.GasLimit = append(t.GasLimit, j) + j, err := stringToUint64(i) + if err != nil { + return fmt.Errorf("failed to convert string '%s' to uint64: %w", i, err) } + + t.GasLimit = append(t.GasLimit, j) } for _, i := range dec.Value { @@ -364,14 +354,30 @@ func (t *stTransaction) UnmarshalJSON(input []byte) error { t.Value = append(t.Value, value) } - t.GasPrice, err = stringToBigInt(dec.GasPrice) - if err != nil { - return err + var err error + + if dec.GasPrice != "" { + if t.GasPrice, err = stringToBigInt(dec.GasPrice); err != nil { + return fmt.Errorf("failed to parse gas price: %w", err) + } } - t.Nonce, err = stringToUint64(dec.Nonce) - if err != nil { - return err + if dec.MaxFeePerGas != "" { + if t.MaxFeePerGas, err = stringToBigInt(dec.MaxFeePerGas); err != nil { + return fmt.Errorf("failed to parse max fee per gas: %w", err) + } + } + + if dec.MaxPriorityFeePerGas != "" { + if t.MaxPriorityFeePerGas, err = stringToBigInt(dec.MaxPriorityFeePerGas); err != nil { + return fmt.Errorf("failed to parse max priority fee per gas: %w", err) + } + } + + if dec.Nonce != "" { + if t.Nonce, err = stringToUint64(dec.Nonce); err != nil { + return fmt.Errorf("failed to parse nonce: %w", err) + } } t.From = types.Address{} @@ -379,7 +385,7 @@ func (t *stTransaction) UnmarshalJSON(input []byte) error { if len(dec.SecretKey) > 0 { secretKey, err := types.ParseBytes(&dec.SecretKey) if err != nil { - return err + return fmt.Errorf("failed to parse secret key: %w", err) } key, err := crypto.ParseECDSAPrivateKey(secretKey) @@ -403,83 +409,72 @@ func (t *stTransaction) UnmarshalJSON(input []byte) error { var Forks = map[string]*chain.Forks{ "Frontier": {}, "Homestead": { - Homestead: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), }, "EIP150": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), }, "EIP158": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), }, "Byzantium": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), }, "Constantinople": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(0), - }, - "Istanbul": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(0), - Petersburg: chain.NewFork(0), - Istanbul: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(0), }, - "London": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(0), - Petersburg: chain.NewFork(0), - Istanbul: chain.NewFork(0), - London: chain.NewFork(0), + "Istchain.anbul": { + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(0), + chain.Petersburg: chain.NewFork(0), + chain.Istanbul: chain.NewFork(0), }, "FrontierToHomesteadAt5": { - Homestead: chain.NewFork(5), + chain.Homestead: chain.NewFork(5), }, "HomesteadToEIP150At5": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(5), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(5), }, "HomesteadToDaoAt5": { - Homestead: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), }, "EIP158ToByzantiumAt5": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(5), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(5), }, "ByzantiumToConstantinopleAt5": { - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(5), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(5), }, "ConstantinopleFix": { - Homestead: chain.NewFork(0), - EIP150: chain.NewFork(0), - EIP155: chain.NewFork(0), - EIP158: chain.NewFork(0), - Byzantium: chain.NewFork(0), - Constantinople: chain.NewFork(0), - Petersburg: chain.NewFork(0), + chain.Homestead: chain.NewFork(0), + chain.EIP150: chain.NewFork(0), + chain.EIP155: chain.NewFork(0), + chain.EIP158: chain.NewFork(0), + chain.Byzantium: chain.NewFork(0), + chain.Constantinople: chain.NewFork(0), + chain.Petersburg: chain.NewFork(0), }, } @@ -493,37 +488,42 @@ func contains(l []string, name string) bool { return false } -func listFolders(paths ...string) ([]string, error) { - folders := []string{} +//go:embed tests +var testsFS embed.FS - for _, p := range paths { - path := filepath.Join(TESTS, p) +func listFolders(tests ...string) ([]string, error) { + var folders []string - files, err := os.ReadDir(path) - if err != nil { - return nil, err - } + for _, t := range tests { + if err := fs.WalkDir(testsFS, t, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } - for _, i := range files { - if i.IsDir() { - folders = append(folders, filepath.Join(path, i.Name())) + if d.IsDir() && t != "path" { + folders = append(folders, path) } + + return nil + }); err != nil { + return nil, err } + + // Excluding root dir + folders = folders[1:] } return folders, nil } func listFiles(folder string) ([]string, error) { - if !strings.HasPrefix(folder, filepath.Base(TESTS)) { - folder = filepath.Join(TESTS, folder) - } + var files []string - files := []string{} err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error { if err != nil { return err } + if !info.IsDir() { files = append(files, path) } @@ -533,3 +533,20 @@ func listFiles(folder string) ([]string, error) { return files, err } + +func rlpHashLogs(logs []*types.Log) (res types.Hash) { + r := &types.Receipt{ + Logs: logs, + } + + ar := &fastrlp.Arena{} + v := r.MarshalLogsWith(ar) + + keccak.Keccak256Rlp(res[:0], v) + + return +} + +func vmTestBlockHash(n uint64) types.Hash { + return types.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String()))) +} diff --git a/tracker/event_tracker.go b/tracker/event_tracker.go index 882e7bab6e..6ecca5c926 100644 --- a/tracker/event_tracker.go +++ b/tracker/event_tracker.go @@ -2,7 +2,9 @@ package tracker import ( "context" + "time" + "github.com/0xPolygon/polygon-edge/helper/common" hcf "github.com/hashicorp/go-hclog" "github.com/umbracle/ethgo" "github.com/umbracle/ethgo/blocktracker" @@ -10,6 +12,8 @@ import ( "github.com/umbracle/ethgo/tracker" ) +const minBlockMaxBacklog = 96 + type eventSubscription interface { AddLog(log *ethgo.Log) } @@ -61,9 +65,42 @@ func (e *EventTracker) Start(ctx context.Context) error { return err } - blockMaxBacklog := e.numBlockConfirmations*2 + 1 + blockMaxBacklog := e.numBlockConfirmations * 2 + if blockMaxBacklog < minBlockMaxBacklog { + blockMaxBacklog = minBlockMaxBacklog + } + blockTracker := blocktracker.NewBlockTracker(provider.Eth(), blocktracker.WithBlockMaxBacklog(blockMaxBacklog)) + go func() { + <-ctx.Done() + blockTracker.Close() + store.Close() + }() + + // Init and start block tracker concurrently, retrying indefinitely + go common.RetryForever(ctx, time.Second, func(context.Context) error { + start := time.Now().UTC() + + if err := blockTracker.Init(); err != nil { + e.logger.Error("failed to init blocktracker", "error", err) + + return err + } + + elapsed := time.Now().UTC().Sub(start) // Calculate the elapsed time + + if err := blockTracker.Start(); err != nil { + e.logger.Error("failed to start blocktracker", "error", err) + + return err + } + + e.logger.Info("Block tracker has been started", "max backlog", blockMaxBacklog, "init time", elapsed) + + return nil + }) + tt, err := tracker.NewTracker(provider.Eth(), tracker.WithBatchSize(10), tracker.WithBlockTracker(blockTracker), @@ -79,30 +116,16 @@ func (e *EventTracker) Start(ctx context.Context) error { if err != nil { return err } - - go func() { - if err := blockTracker.Init(); err != nil { - e.logger.Error("failed to init blocktracker", "error", err) - - return - } - - if err := blockTracker.Start(); err != nil { - e.logger.Error("failed to start blocktracker", "error", err) - } - }() - - go func() { - <-ctx.Done() - blockTracker.Close() - store.Close() - }() - - go func() { + // Sync concurrently, retrying indefinitely + go common.RetryForever(ctx, time.Second, func(context.Context) error { if err := tt.Sync(ctx); err != nil { e.logger.Error("failed to sync", "error", err) + + return err } - }() + + return nil + }) return nil } diff --git a/txpool/query.go b/txpool/query.go index 7ffc45e761..8e4c9ba91f 100644 --- a/txpool/query.go +++ b/txpool/query.go @@ -1,6 +1,10 @@ package txpool -import "github.com/0xPolygon/polygon-edge/types" +import ( + "sync/atomic" + + "github.com/0xPolygon/polygon-edge/types" +) /* QUERY methods */ // Used to query the pool for specific state info. @@ -46,3 +50,8 @@ func (p *TxPool) GetTxs(inclQueued bool) ( return } + +// GetBaseFee returns current base fee +func (p *TxPool) GetBaseFee() uint64 { + return atomic.LoadUint64(&p.baseFee) +} diff --git a/txpool/queue.go b/txpool/queue_account.go similarity index 60% rename from txpool/queue.go rename to txpool/queue_account.go index 4cff31222f..63340b0b2d 100644 --- a/txpool/queue.go +++ b/txpool/queue_account.go @@ -12,7 +12,7 @@ import ( // All methods assume the (correct) lock is held. type accountQueue struct { sync.RWMutex - wLock uint32 + wLock atomic.Bool queue minNonceQueue } @@ -27,18 +27,17 @@ func newAccountQueue() *accountQueue { } func (q *accountQueue) lock(write bool) { - switch write { - case true: + if write { q.Lock() - atomic.StoreUint32(&q.wLock, 1) - case false: + } else { q.RLock() - atomic.StoreUint32(&q.wLock, 0) } + + q.wLock.Store(write) } func (q *accountQueue) unlock() { - if atomic.SwapUint32(&q.wLock, 0) == 1 { + if q.wLock.Swap(false) { q.Unlock() } else { q.RUnlock() @@ -152,90 +151,3 @@ func (q *minNonceQueue) Pop() interface{} { return x } - -type pricedQueue struct { - queue maxPriceQueue -} - -func newPricedQueue() *pricedQueue { - q := pricedQueue{ - queue: make(maxPriceQueue, 0), - } - - heap.Init(&q.queue) - - return &q -} - -// clear empties the underlying queue. -func (q *pricedQueue) clear() { - q.queue = q.queue[:0] -} - -// Pushes the given transactions onto the queue. -func (q *pricedQueue) push(tx *types.Transaction) { - heap.Push(&q.queue, tx) -} - -// Pop removes the first transaction from the queue -// or nil if the queue is empty. -func (q *pricedQueue) pop() *types.Transaction { - if q.length() == 0 { - return nil - } - - transaction, ok := heap.Pop(&q.queue).(*types.Transaction) - if !ok { - return nil - } - - return transaction -} - -// length returns the number of transactions in the queue. -func (q *pricedQueue) length() uint64 { - return uint64(q.queue.Len()) -} - -// transactions sorted by gas price (descending) -type maxPriceQueue []*types.Transaction - -/* Queue methods required by the heap interface */ - -func (q *maxPriceQueue) Peek() *types.Transaction { - if q.Len() == 0 { - return nil - } - - return (*q)[0] -} - -func (q *maxPriceQueue) Len() int { - return len(*q) -} - -func (q *maxPriceQueue) Swap(i, j int) { - (*q)[i], (*q)[j] = (*q)[j], (*q)[i] -} - -func (q *maxPriceQueue) Less(i, j int) bool { - return (*q)[i].GasPrice.Uint64() > (*q)[j].GasPrice.Uint64() -} - -func (q *maxPriceQueue) Push(x interface{}) { - transaction, ok := x.(*types.Transaction) - if !ok { - return - } - - *q = append(*q, transaction) -} - -func (q *maxPriceQueue) Pop() interface{} { - old := q - n := len(*old) - x := (*old)[n-1] - *q = (*old)[0 : n-1] - - return x -} diff --git a/txpool/queue_priced.go b/txpool/queue_priced.go new file mode 100644 index 0000000000..88390a11fd --- /dev/null +++ b/txpool/queue_priced.go @@ -0,0 +1,149 @@ +package txpool + +import ( + "container/heap" + "math/big" + "sync/atomic" + + "github.com/0xPolygon/polygon-edge/types" +) + +type pricedQueue struct { + queue *maxPriceQueue +} + +func newPricedQueue() *pricedQueue { + q := pricedQueue{ + queue: &maxPriceQueue{}, + } + + heap.Init(q.queue) + + return &q +} + +// clear empties the underlying queue. +func (q *pricedQueue) clear() { + q.queue.txs = q.queue.txs[:0] +} + +// Pushes the given transactions onto the queue. +func (q *pricedQueue) push(tx *types.Transaction) { + heap.Push(q.queue, tx) +} + +// Pop removes the first transaction from the queue +// or nil if the queue is empty. +func (q *pricedQueue) pop() *types.Transaction { + if q.length() == 0 { + return nil + } + + transaction, ok := heap.Pop(q.queue).(*types.Transaction) + if !ok { + return nil + } + + return transaction +} + +// length returns the number of transactions in the queue. +func (q *pricedQueue) length() uint64 { + return uint64(q.queue.Len()) +} + +// transactions sorted by gas price (descending) +type maxPriceQueue struct { + baseFee uint64 + txs []*types.Transaction +} + +/* Queue methods required by the heap interface */ + +func (q *maxPriceQueue) Peek() *types.Transaction { + if q.Len() == 0 { + return nil + } + + return q.txs[0] +} + +func (q *maxPriceQueue) Len() int { + return len(q.txs) +} + +func (q *maxPriceQueue) Swap(i, j int) { + q.txs[i], q.txs[j] = q.txs[j], q.txs[i] +} + +func (q *maxPriceQueue) Less(i, j int) bool { + switch q.cmp(q.txs[i], q.txs[j]) { + case -1: + return true + case 1: + return false + default: + return q.txs[i].Nonce > q.txs[j].Nonce + } +} + +func (q *maxPriceQueue) Push(x interface{}) { + transaction, ok := x.(*types.Transaction) + if !ok { + return + } + + q.txs = append(q.txs, transaction) +} + +func (q *maxPriceQueue) Pop() interface{} { + old := q.txs + n := len(old) + x := old[n-1] + q.txs = old[0 : n-1] + + return x +} + +// cmp compares the given transactions by their fees and returns: +// - 0 if they have same fees +// - 1 if a has higher fees than b +// - -1 if b has higher fees than a +func (q *maxPriceQueue) cmp(a, b *types.Transaction) int { + baseFee := atomic.LoadUint64(&q.baseFee) + effectiveTipA := a.EffectiveTip(baseFee) + effectiveTipB := b.EffectiveTip(baseFee) + + // Compare effective tips if baseFee is specified + if c := effectiveTipA.Cmp(effectiveTipB); c != 0 { + return c + } + + aGasFeeCap, bGasFeeCap := new(big.Int), new(big.Int) + + if a.GasFeeCap != nil { + aGasFeeCap = aGasFeeCap.Set(a.GasFeeCap) + } + + if b.GasFeeCap != nil { + bGasFeeCap = bGasFeeCap.Set(b.GasFeeCap) + } + + // Compare fee caps if baseFee is not specified or effective tips are equal + if c := aGasFeeCap.Cmp(bGasFeeCap); c != 0 { + return c + } + + aGasTipCap, bGasTipCap := new(big.Int), new(big.Int) + + if a.GasTipCap != nil { + aGasTipCap = aGasTipCap.Set(a.GasTipCap) + } + + if b.GasTipCap != nil { + bGasTipCap = bGasTipCap.Set(b.GasTipCap) + } + + // Compare tips if effective tips and fee caps are equal + return aGasTipCap.Cmp(bGasTipCap) +} diff --git a/txpool/queue_priced_test.go b/txpool/queue_priced_test.go new file mode 100644 index 0000000000..7e8aea3695 --- /dev/null +++ b/txpool/queue_priced_test.go @@ -0,0 +1,326 @@ +package txpool + +import ( + "math/big" + "math/rand" + "sort" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/0xPolygon/polygon-edge/types" +) + +func Test_maxPriceQueue(t *testing.T) { + t.Parallel() + + testTable := []struct { + name string + baseFee uint64 + unsorted []*types.Transaction + sorted []*types.Transaction + }{ + { + name: "sort txs by tips with base fee", + baseFee: 1000, + unsorted: []*types.Transaction{ + // Highest tx fee + { + Type: types.DynamicFeeTx, + GasPrice: big.NewInt(0), + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(500), + }, + // Lowest tx fee + { + Type: types.LegacyTx, + GasPrice: big.NewInt(100), + }, + // Middle tx fee + { + Type: types.DynamicFeeTx, + GasPrice: big.NewInt(0), + GasFeeCap: big.NewInt(1500), + GasTipCap: big.NewInt(200), + }, + }, + sorted: []*types.Transaction{ + // Highest tx fee + { + Type: types.DynamicFeeTx, + GasPrice: big.NewInt(0), + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(500), + }, + // Middle tx fee + { + Type: types.DynamicFeeTx, + GasPrice: big.NewInt(0), + GasFeeCap: big.NewInt(1500), + GasTipCap: big.NewInt(200), + }, + // Lowest tx fee + { + Type: types.LegacyTx, + GasPrice: big.NewInt(100), + }, + }, + }, + { + name: "sort txs by nonce with base fee", + baseFee: 1000, + unsorted: []*types.Transaction{ + // Highest tx fee + { + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(500), + Nonce: 3, + }, + // Lowest tx fee + { + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(500), + Nonce: 1, + }, + // Middle tx fee + { + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(500), + Nonce: 2, + }, + }, + sorted: []*types.Transaction{ + // Highest tx fee + { + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(500), + Nonce: 1, + }, + // Middle tx fee + { + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(500), + Nonce: 2, + }, + // Lowest tx fee + { + Type: types.DynamicFeeTx, + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(500), + Nonce: 3, + }, + }, + }, + { + name: "sort txs without base fee by fee cap", + baseFee: 0, + unsorted: []*types.Transaction{ + // Highest tx fee + { + GasFeeCap: big.NewInt(3000), + GasTipCap: big.NewInt(100), + }, + // Lowest tx fee + { + GasFeeCap: big.NewInt(1000), + GasTipCap: big.NewInt(100), + }, + // Middle tx fee + { + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(100), + }, + }, + sorted: []*types.Transaction{ + // Highest tx fee + { + GasFeeCap: big.NewInt(3000), + GasTipCap: big.NewInt(100), + }, + // Middle tx fee + { + GasFeeCap: big.NewInt(2000), + GasTipCap: big.NewInt(100), + }, + // Lowest tx fee + { + GasFeeCap: big.NewInt(1000), + GasTipCap: big.NewInt(100), + }, + }, + }, + { + name: "sort txs without base fee by tip cap", + baseFee: 0, + unsorted: []*types.Transaction{ + // Highest tx fee + { + GasFeeCap: big.NewInt(1000), + GasTipCap: big.NewInt(300), + }, + // Lowest tx fee + { + GasFeeCap: big.NewInt(1000), + GasTipCap: big.NewInt(100), + }, + // Middle tx fee + { + GasFeeCap: big.NewInt(1000), + GasTipCap: big.NewInt(200), + }, + }, + sorted: []*types.Transaction{ + // Highest tx fee + { + GasFeeCap: big.NewInt(1000), + GasTipCap: big.NewInt(300), + }, + // Middle tx fee + { + GasFeeCap: big.NewInt(1000), + GasTipCap: big.NewInt(200), + }, + // Lowest tx fee + { + GasFeeCap: big.NewInt(1000), + GasTipCap: big.NewInt(100), + }, + }, + }, + { + name: "sort txs without base fee by gas price", + baseFee: 0, + unsorted: []*types.Transaction{ + // Highest tx fee + { + GasPrice: big.NewInt(1000), + }, + // Lowest tx fee + { + GasPrice: big.NewInt(100), + }, + // Middle tx fee + { + GasPrice: big.NewInt(500), + }, + }, + sorted: []*types.Transaction{ + // Highest tx fee + { + GasPrice: big.NewInt(1000), + }, + // Middle tx fee + { + GasPrice: big.NewInt(500), + }, + // Lowest tx fee + { + GasPrice: big.NewInt(100), + }, + }, + }, + } + + for _, tt := range testTable { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + queue := &maxPriceQueue{ + baseFee: tt.baseFee, + txs: tt.unsorted, + } + + sort.Sort(queue) + + for _, tx := range tt.sorted { + actual := queue.Pop() + assert.Equal(t, tx, actual) + } + }) + } +} + +func Benchmark_pricedQueue(t *testing.B) { + testTable := []struct { + name string + unsortedTxs []*types.Transaction + }{ + { + name: "1000 transactions", + unsortedTxs: generateTxs(1000), + }, + { + name: "10000 transactions", + unsortedTxs: generateTxs(10000), + }, + { + name: "100000 transactions", + unsortedTxs: generateTxs(100000), + }, + } + + for _, tt := range testTable { + t.Run(tt.name, func(b *testing.B) { + for i := 0; i < t.N; i++ { + q := newPricedQueue() + q.queue.baseFee = uint64(i) + + for _, tx := range tt.unsortedTxs { + q.push(tx) + } + + for q.length() > 0 { + _ = q.pop() + } + } + }) + } +} + +func generateTxs(num int) []*types.Transaction { + txs := make([]*types.Transaction, num) + + for i := 0; i < num; i++ { + txs[i] = generateTx(i + 1) + } + + return txs +} + +func generateTx(i int) *types.Transaction { + s := rand.NewSource(int64(i)) + r := rand.New(s) + + txTypes := []types.TxType{ + types.LegacyTx, + types.DynamicFeeTx, + } + + tx := &types.Transaction{ + Type: txTypes[r.Intn(len(txTypes))], + } + + switch tx.Type { + case types.LegacyTx: + minGasPrice := 1000 * i + maxGasPrice := 100000 * i + tx.GasPrice = new(big.Int).SetInt64(int64(rand.Intn(maxGasPrice-minGasPrice) + minGasPrice)) + case types.DynamicFeeTx: + minGasFeeCap := 1000 * i + maxGasFeeCap := 100000 * i + tx.GasFeeCap = new(big.Int).SetInt64(int64(rand.Intn(maxGasFeeCap-minGasFeeCap) + minGasFeeCap)) + + minGasTipCap := 100 * i + maxGasTipCap := 10000 * i + tx.GasTipCap = new(big.Int).SetInt64(int64(rand.Intn(maxGasTipCap-minGasTipCap) + minGasTipCap)) + } + + return tx +} diff --git a/txpool/slot_gauge.go b/txpool/slot_gauge.go index 4642ede4d4..2df18c6df0 100644 --- a/txpool/slot_gauge.go +++ b/txpool/slot_gauge.go @@ -4,6 +4,7 @@ import ( "sync/atomic" "github.com/0xPolygon/polygon-edge/types" + "github.com/armon/go-metrics" ) const ( @@ -23,12 +24,14 @@ func (g *slotGauge) read() uint64 { // increase increases the height of the gauge by the specified slots amount. func (g *slotGauge) increase(slots uint64) { - atomic.AddUint64(&g.height, slots) + newHeight := atomic.AddUint64(&g.height, slots) + metrics.SetGauge([]string{txPoolMetrics, "slots_used"}, float32(newHeight)) } // decrease decreases the height of the gauge by the specified slots amount. func (g *slotGauge) decrease(slots uint64) { - atomic.AddUint64(&g.height, ^(slots - 1)) + newHeight := atomic.AddUint64(&g.height, ^(slots - 1)) + metrics.SetGauge([]string{txPoolMetrics, "slots_used"}, float32(newHeight)) } // highPressure checks if the gauge level diff --git a/txpool/txpool.go b/txpool/txpool.go index d9d3b13102..57f2187edc 100644 --- a/txpool/txpool.go +++ b/txpool/txpool.go @@ -55,8 +55,10 @@ var ( ErrOversizedData = errors.New("oversized data") ErrMaxEnqueuedLimitReached = errors.New("maximum number of enqueued transactions reached") ErrRejectFutureTx = errors.New("rejected future tx due to low slots") - ErrSmartContractRestricted = errors.New("smart contract deployment restricted") ErrInvalidTxType = errors.New("invalid tx type") + ErrTipAboveFeeCap = errors.New("max priority fee per gas higher than max fee per gas") + ErrTipVeryHigh = errors.New("max priority fee per gas higher than 2^256-1") + ErrFeeCapVeryHigh = errors.New("max fee per gas higher than 2^256-1") ) // indicates origin of a transaction @@ -91,10 +93,9 @@ type signer interface { } type Config struct { - PriceLimit uint64 - MaxSlots uint64 - MaxAccountEnqueued uint64 - DeploymentWhitelist []types.Address + PriceLimit uint64 + MaxSlots uint64 + MaxAccountEnqueued uint64 } /* All requests are passed to the main loop @@ -170,14 +171,15 @@ type TxPool struct { // flag indicating if the current node is a sealer, // and should therefore gossip transactions - sealing uint32 + sealing atomic.Bool + + // baseFee is the base fee of the current head. + // This is needed to sort transactions by price + baseFee uint64 // Event manager for txpool events eventManager *eventManager - // deploymentWhitelist map - deploymentWhitelist deploymentWhitelist - // indicates which txpool operator commands should be implemented proto.UnimplementedTxnPoolOperatorServer @@ -186,41 +188,6 @@ type TxPool struct { pending int64 } -// deploymentWhitelist map which contains all addresses which can deploy contracts -// if empty anyone can -type deploymentWhitelist struct { - // Contract deployment whitelist - addresses map[string]bool -} - -// add an address to deploymentWhitelist map -func (w *deploymentWhitelist) add(addr types.Address) { - w.addresses[addr.String()] = true -} - -// allowed checks if address can deploy smart contract -func (w *deploymentWhitelist) allowed(addr types.Address) bool { - if len(w.addresses) == 0 { - return true - } - - _, ok := w.addresses[addr.String()] - - return ok -} - -func newDeploymentWhitelist(deploymentWhitelistRaw []types.Address) deploymentWhitelist { - deploymentWhitelist := deploymentWhitelist{ - addresses: map[string]bool{}, - } - - for _, addr := range deploymentWhitelistRaw { - deploymentWhitelist.add(addr) - } - - return deploymentWhitelist -} - // NewTxPool returns a new pool for processing incoming transactions. func NewTxPool( logger hclog.Logger, @@ -264,9 +231,6 @@ func NewTxPool( pool.topic = topic } - // initialize deployment whitelist - pool.deploymentWhitelist = newDeploymentWhitelist(config.DeploymentWhitelist) - if grpcServer != nil { proto.RegisterTxnPoolOperatorServer(grpcServer, pool) } @@ -331,21 +295,7 @@ func (p *TxPool) SetSigner(s signer) { // SetSealing sets the sealing flag func (p *TxPool) SetSealing(sealing bool) { - newValue := uint32(0) - if sealing { - newValue = 1 - } - - atomic.CompareAndSwapUint32( - &p.sealing, - p.sealing, - newValue, - ) -} - -// sealing returns the current set sealing flag -func (p *TxPool) getSealing() bool { - return atomic.LoadUint32(&p.sealing) == 1 + p.sealing.CompareAndSwap(p.sealing.Load(), sealing) } // AddTx adds a new transaction to the pool (sent from json-RPC/gRPC endpoints) @@ -376,12 +326,15 @@ func (p *TxPool) AddTx(tx *types.Transaction) error { // Prepare generates all the transactions // ready for execution. (primaries) -func (p *TxPool) Prepare() { +func (p *TxPool) Prepare(baseFee uint64) { // clear from previous round if p.executables.length() != 0 { p.executables.clear() } + // set base fee + p.updateBaseFee(baseFee) + // fetch primary from each account primaries := p.accounts.getPrimaries() @@ -474,11 +427,14 @@ func (p *TxPool) Drop(tx *types.Transaction) { clearAccountQueue(dropped) p.eventManager.signalEvent(proto.EventType_DROPPED, tx.Hash) - p.logger.Debug("dropped account txs", - "num", droppedCount, - "next_nonce", nextNonce, - "address", tx.From.String(), - ) + + if p.logger.IsDebug() { + p.logger.Debug("dropped account txs", + "num", droppedCount, + "next_nonce", nextNonce, + "address", tx.From.String(), + ) + } } // Demote excludes an account from being further processed during block building @@ -487,10 +443,12 @@ func (p *TxPool) Drop(tx *types.Transaction) { func (p *TxPool) Demote(tx *types.Transaction) { account := p.accounts.get(tx.From) if account.Demotions() >= maxAccountDemotions { - p.logger.Debug( - "Demote: threshold reached - dropping account", - "addr", tx.From.String(), - ) + if p.logger.IsDebug() { + p.logger.Debug( + "Demote: threshold reached - dropping account", + "addr", tx.From.String(), + ) + } p.Drop(tx) @@ -566,7 +524,7 @@ func (p *TxPool) processEvent(event *blockchain.Event) { // reset accounts with the new state p.resetAccounts(stateNonces) - if !p.getSealing() { + if !p.sealing.Load() { // only non-validator cleanup inactive accounts p.updateAccountSkipsCounts(stateNonces) } @@ -577,16 +535,22 @@ func (p *TxPool) processEvent(event *blockchain.Event) { func (p *TxPool) validateTx(tx *types.Transaction) error { // Check the transaction type. State transactions are not expected to be added to the pool if tx.Type == types.StateTx { + metrics.IncrCounter([]string{txPoolMetrics, "invalid_tx_type"}, 1) + return ErrInvalidTxType } // Check the transaction size to overcome DOS Attacks if uint64(len(tx.MarshalRLP())) > txMaxSize { + metrics.IncrCounter([]string{txPoolMetrics, "oversized_data_txs"}, 1) + return ErrOversizedData } // Check if the transaction has a strictly positive value if tx.Value.Sign() < 0 { + metrics.IncrCounter([]string{txPoolMetrics, "negative_value_tx"}, 1) + return ErrNegativeValue } @@ -595,6 +559,8 @@ func (p *TxPool) validateTx(tx *types.Transaction) error { // Extract the sender from, signerErr := p.signer.Sender(tx) if signerErr != nil { + metrics.IncrCounter([]string{txPoolMetrics, "invalid_signature_txs"}, 1) + return ErrExtractSignature } @@ -602,6 +568,8 @@ func (p *TxPool) validateTx(tx *types.Transaction) error { // it matches the signer if tx.From != types.ZeroAddress && tx.From != from { + metrics.IncrCounter([]string{txPoolMetrics, "invalid_sender_txs"}, 1) + return ErrInvalidSender } @@ -611,19 +579,58 @@ func (p *TxPool) validateTx(tx *types.Transaction) error { } // Check if transaction can deploy smart contract - if tx.IsContractCreation() { - if !p.deploymentWhitelist.allowed(tx.From) { - return ErrSmartContractRestricted + if tx.IsContractCreation() && p.forks.EIP158 && len(tx.Input) > state.TxPoolMaxInitCodeSize { + metrics.IncrCounter([]string{txPoolMetrics, "contract_deploy_too_large_txs"}, 1) + + return runtime.ErrMaxCodeSizeExceeded + } + + if tx.Type == types.DynamicFeeTx { + // Reject dynamic fee tx if london hardfork is not enabled + if !p.forks.London { + metrics.IncrCounter([]string{txPoolMetrics, "invalid_tx_type"}, 1) + + return ErrInvalidTxType } - if p.forks.EIP158 && len(tx.Input) > state.TxPoolMaxInitCodeSize { - return runtime.ErrMaxCodeSizeExceeded + // Check EIP-1559-related fields and make sure they are correct + if tx.GasFeeCap == nil || tx.GasTipCap == nil { + metrics.IncrCounter([]string{txPoolMetrics, "underpriced_tx"}, 1) + + return ErrUnderpriced } - } - // Reject underpriced transactions - if tx.IsUnderpriced(p.priceLimit) { - return ErrUnderpriced + if tx.GasFeeCap.BitLen() > 256 { + metrics.IncrCounter([]string{txPoolMetrics, "fee_cap_too_high_dynamic_tx"}, 1) + + return ErrFeeCapVeryHigh + } + + if tx.GasTipCap.BitLen() > 256 { + metrics.IncrCounter([]string{txPoolMetrics, "tip_too_high_dynamic_tx"}, 1) + + return ErrTipVeryHigh + } + + if tx.GasFeeCap.Cmp(tx.GasTipCap) < 0 { + metrics.IncrCounter([]string{txPoolMetrics, "tip_above_fee_cap_dynamic_tx"}, 1) + + return ErrTipAboveFeeCap + } + + // Reject underpriced transactions + if tx.GasFeeCap.Cmp(new(big.Int).SetUint64(p.GetBaseFee())) < 0 { + metrics.IncrCounter([]string{txPoolMetrics, "underpriced_tx"}, 1) + + return ErrUnderpriced + } + } else { + // Legacy approach to check if the given tx is not underpriced + if tx.GetGasPrice(p.GetBaseFee()).Cmp(big.NewInt(0).SetUint64(p.priceLimit)) < 0 { + metrics.IncrCounter([]string{txPoolMetrics, "underpriced_tx"}, 1) + + return ErrUnderpriced + } } // Grab the state root for the latest block @@ -631,26 +638,36 @@ func (p *TxPool) validateTx(tx *types.Transaction) error { // Check nonce ordering if p.store.GetNonce(stateRoot, tx.From) > tx.Nonce { + metrics.IncrCounter([]string{txPoolMetrics, "nonce_too_low_tx"}, 1) + return ErrNonceTooLow } accountBalance, balanceErr := p.store.GetBalance(stateRoot, tx.From) if balanceErr != nil { + metrics.IncrCounter([]string{txPoolMetrics, "invalid_account_state_tx"}, 1) + return ErrInvalidAccountState } // Check if the sender has enough funds to execute the transaction if accountBalance.Cmp(tx.Cost()) < 0 { + metrics.IncrCounter([]string{txPoolMetrics, "insufficient_funds_tx"}, 1) + return ErrInsufficientFunds } // Make sure the transaction has more gas than the basic transaction fee intrinsicGas, err := state.TransactionGasCost(tx, p.forks.Homestead, p.forks.Istanbul) if err != nil { + metrics.IncrCounter([]string{txPoolMetrics, "invalid_intrinsic_gas_tx"}, 1) + return err } if tx.Gas < intrinsicGas { + metrics.IncrCounter([]string{txPoolMetrics, "intrinsic_gas_low_tx"}, 1) + return ErrIntrinsicGas } @@ -658,6 +675,8 @@ func (p *TxPool) validateTx(tx *types.Transaction) error { latestBlockGasLimit := p.store.Header().GasLimit if tx.Gas > latestBlockGasLimit { + metrics.IncrCounter([]string{txPoolMetrics, "block_gas_limit_exceeded_tx"}, 1) + return ErrBlockLimitExceeded } @@ -704,10 +723,12 @@ func (p *TxPool) pruneAccountsWithNonceHoles() { // successful, an account is created for this address // (only once) and an enqueueRequest is signaled. func (p *TxPool) addTx(origin txOrigin, tx *types.Transaction) error { - p.logger.Debug("add tx", - "origin", origin.String(), - "hash", tx.Hash.String(), - ) + if p.logger.IsDebug() { + p.logger.Debug("add tx", + "origin", origin.String(), + "hash", tx.Hash.String(), + ) + } // validate incoming tx if err := p.validateTx(tx); err != nil { @@ -720,6 +741,8 @@ func (p *TxPool) addTx(origin txOrigin, tx *types.Transaction) error { // only accept transactions with expected nonce if account := p.accounts.get(tx.From); account != nil && tx.Nonce > account.getNonce() { + metrics.IncrCounter([]string{txPoolMetrics, "rejected_future_tx"}, 1) + return ErrRejectFutureTx } } @@ -733,6 +756,8 @@ func (p *TxPool) addTx(origin txOrigin, tx *types.Transaction) error { // add to index if ok := p.index.add(tx); !ok { + metrics.IncrCounter([]string{txPoolMetrics, "already_known_tx"}, 1) + return ErrAlreadyKnown } @@ -743,6 +768,8 @@ func (p *TxPool) addTx(origin txOrigin, tx *types.Transaction) error { p.enqueueReqCh <- enqueueRequest{tx: tx} p.eventManager.signalEvent(proto.EventType_ADDED, tx.Hash) + metrics.SetGauge([]string{txPoolMetrics, "added_tx"}, 1) + return nil } @@ -766,7 +793,9 @@ func (p *TxPool) handleEnqueueRequest(req enqueueRequest) { return } - p.logger.Debug("enqueue request", "hash", tx.Hash.String()) + if p.logger.IsDebug() { + p.logger.Debug("enqueue request", "hash", tx.Hash.String()) + } p.gauge.increase(slotsRequired(tx)) @@ -790,7 +819,9 @@ func (p *TxPool) handlePromoteRequest(req promoteRequest) { // promote enqueued txs promoted, pruned := account.promote() - p.logger.Debug("promote request", "promoted", promoted, "addr", addr.String()) + if p.logger.IsDebug() { + p.logger.Debug("promote request", "promoted", promoted, "addr", addr.String()) + } p.index.remove(pruned...) p.gauge.decrease(slotsRequired(pruned...)) @@ -804,7 +835,7 @@ func (p *TxPool) handlePromoteRequest(req promoteRequest) { // addGossipTx handles receiving transactions // gossiped by the network. func (p *TxPool) addGossipTx(obj interface{}, _ peer.ID) { - if !p.getSealing() { + if !p.sealing.Load() { return } @@ -834,7 +865,9 @@ func (p *TxPool) addGossipTx(obj interface{}, _ peer.ID) { // add tx if err := p.addTx(gossip, tx); err != nil { if errors.Is(err, ErrAlreadyKnown) { - p.logger.Debug("rejecting known tx (gossip)", "hash", tx.Hash.String()) + if p.logger.IsDebug() { + p.logger.Debug("rejecting known tx (gossip)", "hash", tx.Hash.String()) + } return } @@ -958,6 +991,12 @@ func (p *TxPool) Length() uint64 { return p.accounts.promoted() } +// updateBaseFee updates base fee in the tx pool and priced queue +func (p *TxPool) updateBaseFee(baseFee uint64) { + atomic.StoreUint64(&p.baseFee, baseFee) + atomic.StoreUint64(&p.executables.queue.baseFee, baseFee) +} + // toHash returns the hash(es) of given transaction(s) func toHash(txs ...*types.Transaction) (hashes []types.Hash) { for _, tx := range txs { diff --git a/txpool/txpool_test.go b/txpool/txpool_test.go index 2e203621c7..c19647bc23 100644 --- a/txpool/txpool_test.go +++ b/txpool/txpool_test.go @@ -31,10 +31,11 @@ const ( ) var ( - forks = &chain.Forks{ - Homestead: chain.NewFork(0), - Istanbul: chain.NewFork(0), - } + forks = (&chain.Forks{ + chain.Homestead: chain.NewFork(0), + chain.Istanbul: chain.NewFork(0), + chain.London: chain.NewFork(0), + }) ) // addresses used in tests @@ -91,10 +92,9 @@ func newTestPoolWithSlots(maxSlots uint64, mockStore ...store) (*TxPool, error) nil, nil, &Config{ - PriceLimit: defaultPriceLimit, - MaxSlots: maxSlots, - MaxAccountEnqueued: defaultMaxAccountEnqueued, - DeploymentWhitelist: []types.Address{}, + PriceLimit: defaultPriceLimit, + MaxSlots: maxSlots, + MaxAccountEnqueued: defaultMaxAccountEnqueued, }, ) } @@ -115,7 +115,7 @@ type result struct { func TestAddTxErrors(t *testing.T) { t.Parallel() - poolSigner := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) + poolSigner := crypto.NewEIP155Signer(100, true) // Generate a private key and address defaultKey, defaultAddr := tests.GenerateKeyAndAddr(t) @@ -546,7 +546,7 @@ func TestAddGossipTx(t *testing.T) { t.Parallel() key, sender := tests.GenerateKeyAndAddr(t) - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), uint64(100)) + signer := crypto.NewEIP155Signer(100, true) tx := newTx(types.ZeroAddress, 1, 1) t.Run("node is a validator", func(t *testing.T) { @@ -1435,7 +1435,7 @@ func TestPop(t *testing.T) { assert.Equal(t, uint64(1), pool.accounts.get(addr1).promoted.length()) // pop the tx - pool.Prepare() + pool.Prepare(0) tx := pool.Peek() pool.Pop(tx) @@ -1463,7 +1463,7 @@ func TestDrop(t *testing.T) { assert.Equal(t, uint64(1), pool.accounts.get(addr1).promoted.length()) // pop the tx - pool.Prepare() + pool.Prepare(0) tx := pool.Peek() pool.Drop(tx) @@ -1496,7 +1496,7 @@ func TestDemote(t *testing.T) { assert.Equal(t, uint64(0), pool.accounts.get(addr1).Demotions()) // call demote - pool.Prepare() + pool.Prepare(0) tx := pool.Peek() pool.Demote(tx) @@ -1532,7 +1532,7 @@ func TestDemote(t *testing.T) { pool.accounts.get(addr1).demotions = maxAccountDemotions // call demote - pool.Prepare() + pool.Prepare(0) tx := pool.Peek() pool.Demote(tx) @@ -1684,14 +1684,10 @@ func Test_updateAccountSkipsCounts(t *testing.T) { }) } -// TestPermissionSmartContractDeployment tests sending deployment tx with deployment whitelist -func TestPermissionSmartContractDeployment(t *testing.T) { +func Test_TxPool_validateTx(t *testing.T) { t.Parallel() - signer := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), uint64(100)) - - poolSigner := crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) - + signer := crypto.NewEIP155Signer(100, true) // Generate a private key and address defaultKey, defaultAddr := tests.GenerateKeyAndAddr(t) @@ -1707,7 +1703,7 @@ func TestPermissionSmartContractDeployment(t *testing.T) { } signTx := func(transaction *types.Transaction) *types.Transaction { - signedTx, signErr := poolSigner.SignTx(transaction, defaultKey) + signedTx, signErr := signer.SignTx(transaction, defaultKey) if signErr != nil { t.Fatalf("Unable to sign transaction, %v", signErr) } @@ -1715,76 +1711,166 @@ func TestPermissionSmartContractDeployment(t *testing.T) { return signedTx } - t.Run("contract deployment whitelist empty, anyone can deploy", func(t *testing.T) { + t.Run("tx input larger than the TxPoolMaxInitCodeSize", func(t *testing.T) { t.Parallel() pool := setupPool() + pool.forks.EIP158 = true + + input := make([]byte, state.TxPoolMaxInitCodeSize+1) + _, err := rand.Read(input) + require.NoError(t, err) tx := newTx(defaultAddr, 0, 1) tx.To = nil + tx.Input = input - assert.NoError(t, pool.validateTx(signTx(tx))) + assert.ErrorIs(t, + pool.validateTx(signTx(tx)), + runtime.ErrMaxCodeSizeExceeded, + ) }) - t.Run("Addresses inside whitelist can deploy smart contract", func(t *testing.T) { + + t.Run("tx input the same as TxPoolMaxInitCodeSize", func(t *testing.T) { t.Parallel() pool := setupPool() - pool.deploymentWhitelist.add(addr1) - pool.deploymentWhitelist.add(defaultAddr) + pool.forks.EIP158 = true + + input := make([]byte, state.TxPoolMaxInitCodeSize) + _, err := rand.Read(input) + require.NoError(t, err) tx := newTx(defaultAddr, 0, 1) tx.To = nil + tx.Input = input + + assert.NoError(t, + pool.validateTx(signTx(tx)), + runtime.ErrMaxCodeSizeExceeded, + ) + }) + + t.Run("transaction with eip-1559 fields can pass", func(t *testing.T) { + t.Parallel() + + pool := setupPool() + pool.baseFee = 1000 + + tx := newTx(defaultAddr, 0, 1) + tx.Type = types.DynamicFeeTx + tx.GasFeeCap = big.NewInt(1100) + tx.GasTipCap = big.NewInt(10) assert.NoError(t, pool.validateTx(signTx(tx))) }) - t.Run("Addresses outside whitelist can not deploy smart contract", func(t *testing.T) { + + t.Run("eip-1559 tx (gas fee cap less than base fee)", func(t *testing.T) { t.Parallel() + pool := setupPool() - pool.deploymentWhitelist.add(addr1) - pool.deploymentWhitelist.add(addr2) + pool.baseFee = 1000 tx := newTx(defaultAddr, 0, 1) - tx.To = nil + tx.Type = types.DynamicFeeTx + tx.GasFeeCap = big.NewInt(100) + tx.GasTipCap = big.NewInt(10) assert.ErrorIs(t, pool.validateTx(signTx(tx)), - ErrSmartContractRestricted, + ErrUnderpriced, ) }) - t.Run("Input larger than the TxPoolMaxInitCodeSize", func(t *testing.T) { + t.Run("eip-1559 tx (gas fee cap less than tip cap)", func(t *testing.T) { t.Parallel() - pool := setupPool() - pool.forks.EIP158 = true - input := make([]byte, state.TxPoolMaxInitCodeSize+1) - _, err := rand.Read(input) - require.NoError(t, err) + pool := setupPool() + pool.baseFee = 1000 tx := newTx(defaultAddr, 0, 1) - tx.To = nil - tx.Input = input + tx.Type = types.DynamicFeeTx + tx.GasFeeCap = big.NewInt(10000) + tx.GasTipCap = big.NewInt(100000) assert.ErrorIs(t, pool.validateTx(signTx(tx)), - runtime.ErrMaxCodeSizeExceeded, + ErrTipAboveFeeCap, ) }) - t.Run("Input the same as TxPoolMaxInitCodeSize", func(t *testing.T) { + t.Run("eip-1559 tx (gas fee cap and/or gas tip cap undefined)", func(t *testing.T) { t.Parallel() + pool := setupPool() - pool.forks.EIP158 = true + pool.baseFee = 1000 - input := make([]byte, state.TxPoolMaxInitCodeSize) - _, err := rand.Read(input) - require.NoError(t, err) + // undefined gas tip cap + tx := newTx(defaultAddr, 0, 1) + tx.Type = types.DynamicFeeTx + tx.GasFeeCap = big.NewInt(10000) + + signedTx := signTx(tx) + signedTx.GasTipCap = nil + assert.ErrorIs(t, + pool.validateTx(signedTx), + ErrUnderpriced, + ) + + // undefined gas fee cap + tx = newTx(defaultAddr, 1, 1) + tx.Type = types.DynamicFeeTx + tx.GasTipCap = big.NewInt(1000) + signedTx = signTx(tx) + signedTx.GasFeeCap = nil + + assert.ErrorIs(t, + pool.validateTx(signedTx), + ErrUnderpriced, + ) + }) + + t.Run("eip-1559 tx (gas fee cap and gas tip cap very high)", func(t *testing.T) { + t.Parallel() + + bitLength := 512 + + pool := setupPool() + pool.baseFee = 1000 + + // very high gas fee cap tx := newTx(defaultAddr, 0, 1) - tx.To = nil - tx.Input = input + tx.Type = types.DynamicFeeTx + tx.GasFeeCap = new(big.Int).SetBit(new(big.Int), bitLength, 1) - assert.NoError(t, + assert.ErrorIs(t, pool.validateTx(signTx(tx)), - runtime.ErrMaxCodeSizeExceeded, + ErrFeeCapVeryHigh, + ) + + // very high gas tip cap + tx = newTx(defaultAddr, 1, 1) + tx.Type = types.DynamicFeeTx + tx.GasTipCap = new(big.Int).SetBit(new(big.Int), bitLength, 1) + + assert.ErrorIs(t, + pool.validateTx(signTx(tx)), + ErrTipVeryHigh, + ) + }) + + t.Run("eip-1559 tx placed without eip-1559 fork enabled", func(t *testing.T) { + t.Parallel() + pool := setupPool() + pool.forks.London = false + + tx := newTx(defaultAddr, 0, 1) + tx.Type = types.DynamicFeeTx + tx.GasFeeCap = big.NewInt(10000) + tx.GasTipCap = big.NewInt(100000) + + assert.ErrorIs(t, + pool.validateTx(signTx(tx)), + ErrInvalidTxType, ) }) } @@ -1842,7 +1928,7 @@ func (e *eoa) signTx(t *testing.T, tx *types.Transaction, signer crypto.TxSigner return signedTx } -var signerEIP155 = crypto.NewEIP155Signer(chain.AllForksEnabled.At(0), 100) +var signerEIP155 = crypto.NewEIP155Signer(100, true) func TestResetAccounts_Promoted(t *testing.T) { t.Parallel() @@ -2493,7 +2579,7 @@ func TestRecovery(t *testing.T) { assert.Len(t, waitForEvents(ctx, promoteSubscription, totalTx), totalTx) func() { - pool.Prepare() + pool.Prepare(0) for { tx := pool.Peek() if tx == nil { @@ -2788,9 +2874,9 @@ func TestSetSealing(t *testing.T) { assert.NoError(t, err) // Set initial value - pool.sealing = 0 + pool.sealing.Store(false) if test.initialValue { - pool.sealing = 1 + pool.sealing.Store(true) } // call the target @@ -2800,7 +2886,7 @@ func TestSetSealing(t *testing.T) { assert.Equal( t, test.expectedValue, - pool.getSealing(), + pool.sealing.Load(), ) }) } diff --git a/txrelayer/txrelayer.go b/txrelayer/txrelayer.go index e812dae19d..aa4fe1983f 100644 --- a/txrelayer/txrelayer.go +++ b/txrelayer/txrelayer.go @@ -3,6 +3,8 @@ package txrelayer import ( "errors" "fmt" + "io" + "math/big" "sync" "time" @@ -12,7 +14,7 @@ import ( ) const ( - DefaultGasPrice = 1879048192 // 0x70000000 + defaultGasPrice = 1879048192 // 0x70000000 DefaultGasLimit = 5242880 // 0x500000 DefaultRPCAddress = "http://127.0.0.1:8545" numRetries = 1000 @@ -30,6 +32,8 @@ type TxRelayer interface { // SendTransactionLocal sends non-signed transaction // (this function is meant only for testing purposes and is about to be removed at some point) SendTransactionLocal(txn *ethgo.Transaction) (*ethgo.Receipt, error) + // Client returns jsonrpc client + Client() *jsonrpc.Client } var _ TxRelayer = (*TxRelayerImpl)(nil) @@ -40,11 +44,13 @@ type TxRelayerImpl struct { receiptTimeout time.Duration lock sync.Mutex + + writer io.Writer } func NewTxRelayer(opts ...TxRelayerOption) (TxRelayer, error) { t := &TxRelayerImpl{ - ipAddress: "http://127.0.0.1:8545", + ipAddress: DefaultRPCAddress, receiptTimeout: 50 * time.Millisecond, } for _, opt := range opts { @@ -84,10 +90,17 @@ func (t *TxRelayerImpl) SendTransaction(txn *ethgo.Transaction, key ethgo.Key) ( return t.waitForReceipt(txnHash) } +// Client returns jsonrpc client +func (t *TxRelayerImpl) Client() *jsonrpc.Client { + return t.client +} + func (t *TxRelayerImpl) sendTransactionLocked(txn *ethgo.Transaction, key ethgo.Key) (ethgo.Hash, error) { t.lock.Lock() defer t.lock.Unlock() + txn.From = key.Address() + nonce, err := t.client.Eth().GetNonce(key.Address(), ethgo.Pending) if err != nil { return ethgo.ZeroHash, err @@ -95,12 +108,24 @@ func (t *TxRelayerImpl) sendTransactionLocked(txn *ethgo.Transaction, key ethgo. txn.Nonce = nonce + txn.From = key.Address() + if txn.GasPrice == 0 { - txn.GasPrice = DefaultGasPrice + gasPrice, err := t.Client().Eth().GasPrice() + if err != nil { + return ethgo.ZeroHash, err + } + + txn.GasPrice = gasPrice } if txn.Gas == 0 { - txn.Gas = DefaultGasLimit + gasLimit, err := t.client.Eth().EstimateGas(ConvertTxnToCallMsg(txn)) + if err != nil { + return ethgo.ZeroHash, err + } + + txn.Gas = gasLimit } chainID, err := t.client.Eth().ChainID() @@ -118,6 +143,12 @@ func (t *TxRelayerImpl) sendTransactionLocked(txn *ethgo.Transaction, key ethgo. return ethgo.ZeroHash, err } + if t.writer != nil { + _, _ = t.writer.Write([]byte( + fmt.Sprintf("[TxRelayer.SendTransaction]\nFrom = %s \nGas = %d \nGas Price = %d\n", + txn.From, txn.Gas, txn.GasPrice))) + } + return t.client.Eth().SendRawTransaction(data) } @@ -134,8 +165,14 @@ func (t *TxRelayerImpl) SendTransactionLocal(txn *ethgo.Transaction) (*ethgo.Rec } txn.From = accounts[0] - txn.Gas = DefaultGasLimit - txn.GasPrice = DefaultGasPrice + + gasLimit, err := t.client.Eth().EstimateGas(ConvertTxnToCallMsg(txn)) + if err != nil { + return nil, err + } + + txn.Gas = gasLimit + txn.GasPrice = defaultGasPrice txnHash, err := t.client.Eth().SendTransaction(txn) if err != nil { @@ -169,6 +206,18 @@ func (t *TxRelayerImpl) waitForReceipt(hash ethgo.Hash) (*ethgo.Receipt, error) } } +// ConvertTxnToCallMsg converts txn instance to call message +func ConvertTxnToCallMsg(txn *ethgo.Transaction) *ethgo.CallMsg { + return ðgo.CallMsg{ + From: txn.From, + To: txn.To, + Data: txn.Input, + GasPrice: txn.GasPrice, + Value: txn.Value, + Gas: new(big.Int).SetUint64(txn.Gas), + } +} + type TxRelayerOption func(*TxRelayerImpl) func WithClient(client *jsonrpc.Client) TxRelayerOption { @@ -188,3 +237,9 @@ func WithReceiptTimeout(receiptTimeout time.Duration) TxRelayerOption { t.receiptTimeout = receiptTimeout } } + +func WithWriter(writer io.Writer) TxRelayerOption { + return func(t *TxRelayerImpl) { + t.writer = writer + } +} diff --git a/types/encoding.go b/types/encoding.go index 3f3dce4330..58dfe6618b 100644 --- a/types/encoding.go +++ b/types/encoding.go @@ -9,6 +9,10 @@ import ( "github.com/0xPolygon/polygon-edge/helper/hex" ) +// ParseUint64orHex parses the given string as uint64 in hex +// It should go to the common package from the logical perspective +// as well as avoiding cycle imports. +// DEPRECATED. Use common.ParseUint64orHex. func ParseUint64orHex(val *string) (uint64, error) { if val == nil { return 0, nil @@ -46,12 +50,6 @@ func ParseUint256orHex(val *string) (*big.Int, error) { return b, nil } -func ParseInt64orHex(val *string) (int64, error) { - i, err := ParseUint64orHex(val) - - return int64(i), err -} - func ParseBytes(val *string) ([]byte, error) { if val == nil { return []byte{}, nil diff --git a/types/header.go b/types/header.go index 5406bee8d4..12e40feabc 100644 --- a/types/header.go +++ b/types/header.go @@ -26,6 +26,9 @@ type Header struct { MixHash Hash Nonce Nonce Hash Hash + + // BaseFee was added by EIP-1559 and is ignored in legacy headers. + BaseFee uint64 `json:"baseFeePerGas"` } func (h *Header) Equal(hh *Header) bool { @@ -75,6 +78,7 @@ func (h *Header) Copy() *Header { GasLimit: h.GasLimit, GasUsed: h.GasUsed, Timestamp: h.Timestamp, + BaseFee: h.BaseFee, } newHeader.Miner = make([]byte, len(h.Miner)) @@ -103,7 +107,7 @@ type Block struct { Uncles []*Header // Cache - size atomic.Value // *uint64 + size atomic.Pointer[uint64] } func (b *Block) Hash() Hash { @@ -135,12 +139,7 @@ func (b *Block) Size() uint64 { return size } - sizeVal, ok := sizePtr.(*uint64) - if !ok { - return 0 - } - - return *sizeVal + return *sizePtr } func (b *Block) String() string { diff --git a/types/receipt.go b/types/receipt.go index 21ecd0a897..93830506a7 100644 --- a/types/receipt.go +++ b/types/receipt.go @@ -76,6 +76,7 @@ func (b Bloom) MarshalText() ([]byte, error) { // CreateBloom creates a new bloom filter from a set of receipts func CreateBloom(receipts []*Receipt) (b Bloom) { h := keccak.DefaultKeccakPool.Get() + defer keccak.DefaultKeccakPool.Put(h) for _, receipt := range receipts { for _, log := range receipt.Logs { @@ -87,8 +88,6 @@ func CreateBloom(receipts []*Receipt) (b Bloom) { } } - keccak.DefaultKeccakPool.Put(h) - return } @@ -99,36 +98,32 @@ func (b *Bloom) setEncode(hasher *keccak.Keccak, h []byte) { for i := 0; i < 6; i += 2 { // Find the global bit location - bit := (uint(buf[i+1]) + (uint(buf[i]) << 8)) & 2047 + bit := (uint(buf[i+1]) + (uint(buf[i]) << 8)) & (BloomByteLength*8 - 1) - // Find where the bit maps in the [0..255] byte array - byteLocation := 256 - 1 - bit/8 + // Find where the bit maps in the [0..BloomByteLength-1] byte array + byteLocation := BloomByteLength - 1 - bit/8 bitLocation := bit % 8 - b[byteLocation] = b[byteLocation] | (1 << bitLocation) + b[byteLocation] |= 1 << bitLocation } } // IsLogInBloom checks if the log has a possible presence in the bloom filter func (b *Bloom) IsLogInBloom(log *Log) bool { hasher := keccak.DefaultKeccakPool.Get() + defer keccak.DefaultKeccakPool.Put(hasher) // Check if the log address is present - addressPresent := b.isByteArrPresent(hasher, log.Address.Bytes()) - if !addressPresent { + if !b.isByteArrPresent(hasher, log.Address.Bytes()) { return false } // Check if all the topics are present for _, topic := range log.Topics { - topicsPresent := b.isByteArrPresent(hasher, topic.Bytes()) - - if !topicsPresent { + if !b.isByteArrPresent(hasher, topic.Bytes()) { return false } } - keccak.DefaultKeccakPool.Put(hasher) - return true } @@ -140,15 +135,12 @@ func (b *Bloom) isByteArrPresent(hasher *keccak.Keccak, data []byte) bool { for i := 0; i < 6; i += 2 { // Find the global bit location - bit := (uint(buf[i+1]) + (uint(buf[i]) << 8)) & 2047 + bit := (uint(buf[i+1]) + (uint(buf[i]) << 8)) & (BloomByteLength*8 - 1) - // Find where the bit maps in the [0..255] byte array - byteLocation := 256 - 1 - bit/8 + // Find where the bit maps in the [0..BloomByteLength-1] byte array + byteLocation := BloomByteLength - 1 - bit/8 bitLocation := bit % 8 - - referenceByte := b[byteLocation] - - isSet := uint(referenceByte & (1 << (bitLocation - 1))) + isSet := b[byteLocation] & (1 << bitLocation) if isSet == 0 { return false diff --git a/types/rlp_encoding_test.go b/types/rlp_encoding_test.go index 7e2e00c3c9..52b0170b98 100644 --- a/types/rlp_encoding_test.go +++ b/types/rlp_encoding_test.go @@ -1,6 +1,7 @@ package types import ( + "fmt" "math/big" "reflect" "testing" @@ -8,6 +9,7 @@ import ( "github.com/umbracle/fastrlp" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type codec interface { @@ -134,35 +136,40 @@ func TestRLPMarshall_And_Unmarshall_TypedTransaction(t *testing.T) { addrTo := StringToAddress("11") addrFrom := StringToAddress("22") originalTx := &Transaction{ - Nonce: 0, - GasPrice: big.NewInt(11), - Gas: 11, - To: &addrTo, - From: addrFrom, - Value: big.NewInt(1), - Input: []byte{1, 2}, - V: big.NewInt(25), - S: big.NewInt(26), - R: big.NewInt(27), + Nonce: 0, + GasPrice: big.NewInt(11), + GasFeeCap: big.NewInt(12), + GasTipCap: big.NewInt(13), + Gas: 11, + To: &addrTo, + From: addrFrom, + Value: big.NewInt(1), + Input: []byte{1, 2}, + V: big.NewInt(25), + S: big.NewInt(26), + R: big.NewInt(27), } txTypes := []TxType{ StateTx, LegacyTx, + DynamicFeeTx, } for _, v := range txTypes { - originalTx.Type = v - originalTx.ComputeHash() + t.Run(v.String(), func(t *testing.T) { + originalTx.Type = v + originalTx.ComputeHash() - txRLP := originalTx.MarshalRLP() + txRLP := originalTx.MarshalRLP() - unmarshalledTx := new(Transaction) - assert.NoError(t, unmarshalledTx.UnmarshalRLP(txRLP)) + unmarshalledTx := new(Transaction) + assert.NoError(t, unmarshalledTx.UnmarshalRLP(txRLP)) - unmarshalledTx.ComputeHash() - assert.Equal(t, originalTx.Type, unmarshalledTx.Type) - assert.Equal(t, originalTx.Hash, unmarshalledTx.Hash) + unmarshalledTx.ComputeHash() + assert.Equal(t, originalTx.Type, unmarshalledTx.Type) + assert.Equal(t, originalTx.Hash, unmarshalledTx.Hash) + }) } } @@ -172,6 +179,7 @@ func TestRLPMarshall_Unmarshall_Missing_Data(t *testing.T) { txTypes := []TxType{ StateTx, LegacyTx, + DynamicFeeTx, } for _, txType := range txTypes { @@ -179,41 +187,54 @@ func TestRLPMarshall_Unmarshall_Missing_Data(t *testing.T) { testTable := []struct { name string expectedErr bool - ommitedValues map[string]bool + omittedValues map[string]bool fromAddrSet bool }{ { - name: "Insuficient params", + name: fmt.Sprintf("[%s] Insuficient params", txType), expectedErr: true, - ommitedValues: map[string]bool{ + omittedValues: map[string]bool{ "Nonce": true, "GasPrice": true, }, }, { - name: "Missing From", + name: fmt.Sprintf("[%s] Missing From", txType), expectedErr: false, - ommitedValues: map[string]bool{ - "From": true, + omittedValues: map[string]bool{ + "ChainID": txType != DynamicFeeTx, + "GasTipCap": txType != DynamicFeeTx, + "GasFeeCap": txType != DynamicFeeTx, + "GasPrice": txType == DynamicFeeTx, + "AccessList": txType != DynamicFeeTx, + "From": txType != StateTx, }, - fromAddrSet: false, + fromAddrSet: txType == StateTx, }, { - name: "Address set for state tx only", - expectedErr: false, - ommitedValues: map[string]bool{}, - fromAddrSet: txType == StateTx, + name: fmt.Sprintf("[%s] Address set for state tx only", txType), + expectedErr: false, + omittedValues: map[string]bool{ + "ChainID": txType != DynamicFeeTx, + "GasTipCap": txType != DynamicFeeTx, + "GasFeeCap": txType != DynamicFeeTx, + "GasPrice": txType == DynamicFeeTx, + "AccessList": txType != DynamicFeeTx, + "From": txType != StateTx, + }, + fromAddrSet: txType == StateTx, }, } for _, tt := range testTable { tt := tt + t.Run(tt.name, func(t *testing.T) { t.Parallel() arena := fastrlp.DefaultArenaPool.Get() parser := fastrlp.DefaultParserPool.Get() - testData := testRLPData(arena, tt.ommitedValues) + testData := testRLPData(arena, tt.omittedValues) v, err := parser.Parse(testData) assert.Nil(t, err) @@ -247,6 +268,10 @@ func TestRLPMarshall_And_Unmarshall_TxType(t *testing.T) { name: "LegacyTx", txType: LegacyTx, }, + { + name: "DynamicFeeTx", + txType: DynamicFeeTx, + }, { name: "undefined type", txType: TxType(0x09), @@ -269,56 +294,62 @@ func TestRLPMarshall_And_Unmarshall_TxType(t *testing.T) { } } -func testRLPData(arena *fastrlp.Arena, ommitValues map[string]bool) []byte { +func testRLPData(arena *fastrlp.Arena, omitValues map[string]bool) []byte { vv := arena.NewArray() - _, ommit := ommitValues["Nonce"] - if !ommit { + if omit, _ := omitValues["ChainID"]; !omit { + vv.Set(arena.NewBigInt(big.NewInt(0))) + } + + if omit, _ := omitValues["Nonce"]; !omit { vv.Set(arena.NewUint(10)) } - _, ommit = ommitValues["GasPrice"] - if !ommit { + if omit, _ := omitValues["GasTipCap"]; !omit { + vv.Set(arena.NewBigInt(big.NewInt(11))) + } + + if omit, _ := omitValues["GasFeeCap"]; !omit { vv.Set(arena.NewBigInt(big.NewInt(11))) } - _, ommit = ommitValues["Gas"] - if !ommit { + if omit, _ := omitValues["GasPrice"]; !omit { + vv.Set(arena.NewBigInt(big.NewInt(11))) + } + + if omit, _ := omitValues["Gas"]; !omit { vv.Set(arena.NewUint(12)) } - _, ommit = ommitValues["To"] - if !ommit { + if omit, _ := omitValues["To"]; !omit { vv.Set(arena.NewBytes((StringToAddress("13")).Bytes())) } - _, ommit = ommitValues["Value"] - if !ommit { + if omit, _ := omitValues["Value"]; !omit { vv.Set(arena.NewBigInt(big.NewInt(14))) } - _, ommit = ommitValues["Input"] - if !ommit { + if omit, _ := omitValues["Input"]; !omit { vv.Set(arena.NewCopyBytes([]byte{1, 2})) } - _, ommit = ommitValues["V"] - if !ommit { + if omit, _ := omitValues["AccessList"]; !omit { + vv.Set(arena.NewArray()) + } + + if omit, _ := omitValues["V"]; !omit { vv.Set(arena.NewBigInt(big.NewInt(15))) } - _, ommit = ommitValues["R"] - if !ommit { + if omit, _ := omitValues["R"]; !omit { vv.Set(arena.NewBigInt(big.NewInt(16))) } - _, ommit = ommitValues["S"] - if !ommit { + if omit, _ := omitValues["S"]; !omit { vv.Set(arena.NewBigInt(big.NewInt(17))) } - _, ommit = ommitValues["From"] - if !ommit { + if omit, _ := omitValues["From"]; !omit { vv.Set(arena.NewBytes((StringToAddress("18")).Bytes())) } @@ -327,3 +358,35 @@ func testRLPData(arena *fastrlp.Arena, ommitValues map[string]bool) []byte { return testData } + +func Test_MarshalCorruptedBytesArray(t *testing.T) { + t.Parallel() + + marshal := func(obj func(*fastrlp.Arena) *fastrlp.Value) []byte { + ar := fastrlp.DefaultArenaPool.Get() + defer fastrlp.DefaultArenaPool.Put(ar) + + return obj(ar).MarshalTo(nil) + } + + emptyArray := [8]byte{} + corruptedSlice := make([]byte, 32) + corruptedSlice[29], corruptedSlice[30], corruptedSlice[31] = 5, 126, 64 + intOfCorruption := uint64(18_446_744_073_709_551_615) // 2^64-1 + + marshalOne := func(ar *fastrlp.Arena) *fastrlp.Value { + return ar.NewBytes(corruptedSlice) + } + + marshalTwo := func(ar *fastrlp.Arena) *fastrlp.Value { + return ar.NewUint(intOfCorruption) + } + + marshal(marshalOne) + + require.Equal(t, emptyArray[:], corruptedSlice[:len(emptyArray)]) + + marshal(marshalTwo) // without fixing this, marshaling will cause corruption of the corrupted slice + + require.Equal(t, emptyArray[:], corruptedSlice[:len(emptyArray)]) +} diff --git a/types/rlp_marshal.go b/types/rlp_marshal.go index 7e244b9d27..be4f3693e2 100644 --- a/types/rlp_marshal.go +++ b/types/rlp_marshal.go @@ -1,6 +1,8 @@ package types import ( + "math/big" + "github.com/umbracle/fastrlp" ) @@ -40,7 +42,7 @@ func (b *Block) MarshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value { v0 := ar.NewArray() for _, tx := range b.Transactions { if tx.Type != LegacyTx { - v0.Set(ar.NewBytes([]byte{byte(tx.Type)})) + v0.Set(ar.NewCopyBytes([]byte{byte(tx.Type)})) } v0.Set(tx.MarshalRLPWith(ar)) @@ -73,12 +75,12 @@ func (h *Header) MarshalRLPTo(dst []byte) []byte { func (h *Header) MarshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { vv := arena.NewArray() - vv.Set(arena.NewBytes(h.ParentHash.Bytes())) - vv.Set(arena.NewBytes(h.Sha3Uncles.Bytes())) + vv.Set(arena.NewCopyBytes(h.ParentHash.Bytes())) + vv.Set(arena.NewCopyBytes(h.Sha3Uncles.Bytes())) vv.Set(arena.NewCopyBytes(h.Miner[:])) - vv.Set(arena.NewBytes(h.StateRoot.Bytes())) - vv.Set(arena.NewBytes(h.TxRoot.Bytes())) - vv.Set(arena.NewBytes(h.ReceiptsRoot.Bytes())) + vv.Set(arena.NewCopyBytes(h.StateRoot.Bytes())) + vv.Set(arena.NewCopyBytes(h.TxRoot.Bytes())) + vv.Set(arena.NewCopyBytes(h.ReceiptsRoot.Bytes())) vv.Set(arena.NewCopyBytes(h.LogsBloom[:])) vv.Set(arena.NewUint(h.Difficulty)) @@ -88,9 +90,11 @@ func (h *Header) MarshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { vv.Set(arena.NewUint(h.Timestamp)) vv.Set(arena.NewCopyBytes(h.ExtraData)) - vv.Set(arena.NewBytes(h.MixHash.Bytes())) + vv.Set(arena.NewCopyBytes(h.MixHash.Bytes())) vv.Set(arena.NewCopyBytes(h.Nonce[:])) + vv.Set(arena.NewUint(h.BaseFee)) + return vv } @@ -103,7 +107,7 @@ func (r *Receipts) MarshalRLPWith(a *fastrlp.Arena) *fastrlp.Value { for _, rr := range *r { if !rr.IsLegacyTx() { - vv.Set(a.NewBytes([]byte{byte(rr.TransactionType)})) + vv.Set(a.NewCopyBytes([]byte{byte(rr.TransactionType)})) } vv.Set(rr.MarshalRLPWith(a)) @@ -131,7 +135,7 @@ func (r *Receipt) MarshalRLPWith(a *fastrlp.Arena) *fastrlp.Value { if r.Status != nil { vv.Set(a.NewUint(uint64(*r.Status))) } else { - vv.Set(a.NewBytes(r.Root[:])) + vv.Set(a.NewCopyBytes(r.Root[:])) } vv.Set(a.NewUint(r.CumulativeGasUsed)) @@ -159,15 +163,15 @@ func (r *Receipt) MarshalLogsWith(a *fastrlp.Arena) *fastrlp.Value { func (l *Log) MarshalRLPWith(a *fastrlp.Arena) *fastrlp.Value { v := a.NewArray() - v.Set(a.NewBytes(l.Address.Bytes())) + v.Set(a.NewCopyBytes(l.Address.Bytes())) topics := a.NewArray() for _, t := range l.Topics { - topics.Set(a.NewBytes(t.Bytes())) + topics.Set(a.NewCopyBytes(t.Bytes())) } v.Set(topics) - v.Set(a.NewBytes(l.Data)) + v.Set(a.NewCopyBytes(l.Data)) return v } @@ -188,13 +192,30 @@ func (t *Transaction) MarshalRLPTo(dst []byte) []byte { func (t *Transaction) MarshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { vv := arena.NewArray() + // Specify zero chain ID as per spec. + // This is needed to have the same format as other EVM chains do. + // There is no chain ID in the TX object, so it is always 0 here just to be compatible. + // Check Transaction1559Payload there https://eips.ethereum.org/EIPS/eip-1559#specification + if t.Type == DynamicFeeTx { + vv.Set(arena.NewBigInt(big.NewInt(0))) + } + vv.Set(arena.NewUint(t.Nonce)) - vv.Set(arena.NewBigInt(t.GasPrice)) + + if t.Type == DynamicFeeTx { + // Add EIP-1559 related fields. + // For non-dynamic-fee-tx gas price is used. + vv.Set(arena.NewBigInt(t.GasTipCap)) + vv.Set(arena.NewBigInt(t.GasFeeCap)) + } else { + vv.Set(arena.NewBigInt(t.GasPrice)) + } + vv.Set(arena.NewUint(t.Gas)) // Address may be empty if t.To != nil { - vv.Set(arena.NewBytes((*t.To).Bytes())) + vv.Set(arena.NewCopyBytes(t.To.Bytes())) } else { vv.Set(arena.NewNull()) } @@ -202,13 +223,21 @@ func (t *Transaction) MarshalRLPWith(arena *fastrlp.Arena) *fastrlp.Value { vv.Set(arena.NewBigInt(t.Value)) vv.Set(arena.NewCopyBytes(t.Input)) + // Specify access list as per spec. + // This is needed to have the same format as other EVM chains do. + // There is no access list feature here, so it is always empty just to be compatible. + // Check Transaction1559Payload there https://eips.ethereum.org/EIPS/eip-1559#specification + if t.Type == DynamicFeeTx { + vv.Set(arena.NewArray()) + } + // signature values vv.Set(arena.NewBigInt(t.V)) vv.Set(arena.NewBigInt(t.R)) vv.Set(arena.NewBigInt(t.S)) if t.Type == StateTx { - vv.Set(arena.NewBytes((t.From).Bytes())) + vv.Set(arena.NewCopyBytes(t.From.Bytes())) } return vv diff --git a/types/rlp_unmarshal.go b/types/rlp_unmarshal.go index 5177507224..b651863bb4 100644 --- a/types/rlp_unmarshal.go +++ b/types/rlp_unmarshal.go @@ -218,6 +218,14 @@ func (h *Header) unmarshalRLPFrom(_ *fastrlp.Parser, v *fastrlp.Value) error { h.SetNonce(nonce) + // basefee + // In order to be backward compatible, the len should be checked before accessing the element + if len(elems) > 15 { + if h.BaseFee, err = elems[15].GetUint64(); err != nil { + return err + } + } + // compute the hash after the decoding h.ComputeHash() @@ -376,30 +384,71 @@ func (t *Transaction) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) erro return err } - if len(elems) < 9 { - return fmt.Errorf("incorrect number of elements to decode transaction, expected 9 but found %d", len(elems)) + getElem := func() *fastrlp.Value { + val := elems[0] + elems = elems[1:] + + return val + } + + var num int + + switch t.Type { + case LegacyTx: + num = 9 + case StateTx: + num = 10 + case DynamicFeeTx: + num = 12 + default: + return fmt.Errorf("transaction type %d not found", t.Type) + } + + if numElems := len(elems); numElems != num { + return fmt.Errorf("incorrect number of transaction elements, expected %d but found %d", num, numElems) } p.Hash(t.Hash[:0], v) + // Skipping Chain ID field since we don't support it (yet) + // This is needed to be compatible with other EVM chains and have the same format. + // Since we don't have a chain ID, just skip it here. + if t.Type == DynamicFeeTx { + _ = getElem() + } + // nonce - if t.Nonce, err = elems[0].GetUint64(); err != nil { + if t.Nonce, err = getElem().GetUint64(); err != nil { return err } - // gasPrice - t.GasPrice = new(big.Int) - if err = elems[1].GetBigInt(t.GasPrice); err != nil { - return err + if t.Type == DynamicFeeTx { + // gasTipCap + t.GasTipCap = new(big.Int) + if err = getElem().GetBigInt(t.GasTipCap); err != nil { + return err + } + + // gasFeeCap + t.GasFeeCap = new(big.Int) + if err = getElem().GetBigInt(t.GasFeeCap); err != nil { + return err + } + } else { + // gasPrice + t.GasPrice = new(big.Int) + if err = getElem().GetBigInt(t.GasPrice); err != nil { + return err + } } // gas - if t.Gas, err = elems[2].GetUint64(); err != nil { + if t.Gas, err = getElem().GetUint64(); err != nil { return err } // to - if vv, _ := v.Get(3).Bytes(); len(vv) == 20 { + if vv, _ := getElem().Bytes(); len(vv) == 20 { // address addr := BytesToAddress(vv) t.To = &addr @@ -410,45 +459,48 @@ func (t *Transaction) unmarshalRLPFrom(p *fastrlp.Parser, v *fastrlp.Value) erro // value t.Value = new(big.Int) - if err = elems[4].GetBigInt(t.Value); err != nil { + if err = getElem().GetBigInt(t.Value); err != nil { return err } // input - if t.Input, err = elems[5].GetBytes(t.Input[:0]); err != nil { + if t.Input, err = getElem().GetBytes(t.Input[:0]); err != nil { return err } + // Skipping Access List field since we don't support it. + // This is needed to be compatible with other EVM chains and have the same format. + // Since we don't have access list, just skip it here. + if t.Type == DynamicFeeTx { + _ = getElem() + } + // V t.V = new(big.Int) - if err = elems[6].GetBigInt(t.V); err != nil { + if err = getElem().GetBigInt(t.V); err != nil { return err } // R t.R = new(big.Int) - if err = elems[7].GetBigInt(t.R); err != nil { + if err = getElem().GetBigInt(t.R); err != nil { return err } // S t.S = new(big.Int) - if err = elems[8].GetBigInt(t.S); err != nil { + if err = getElem().GetBigInt(t.S); err != nil { return err } if t.Type == StateTx { - // set From with default value t.From = ZeroAddress // We need to set From field for state transaction, // because we are using unique, predefined address, for sending such transactions - // From - if len(elems) >= 10 { - if vv, err := v.Get(9).Bytes(); err == nil && len(vv) == AddressLength { - // address - t.From = BytesToAddress(vv) - } + if vv, err := getElem().Bytes(); err == nil && len(vv) == AddressLength { + // address + t.From = BytesToAddress(vv) } } diff --git a/types/state_transaction.go b/types/state_transaction.go new file mode 100644 index 0000000000..bcdc0ec378 --- /dev/null +++ b/types/state_transaction.go @@ -0,0 +1,135 @@ +package types + +import ( + "fmt" + "math/big" + + "github.com/umbracle/ethgo" + "github.com/umbracle/ethgo/abi" +) + +var ( + stateSyncABIType = abi.MustNewType( + "tuple(tuple(uint256 id, address sender, address receiver, bytes data))") + + // this will change to use the generated code, but for now, we leave it as is, because of the circular import + ExecuteStateSyncABIMethod, _ = abi.NewMethod("function execute(" + + "bytes32[] proof, " + + "tuple(uint256 id, address sender, address receiver, bytes data) obj)") +) + +const ( + abiMethodIDLength = 4 +) + +// StateSyncEvent is a bridge event from the rootchain +type StateSyncEvent struct { + // ID is the decoded 'index' field from the event + ID uint64 + // Sender is the decoded 'sender' field from the event + Sender ethgo.Address + // Receiver is the decoded 'receiver' field from the event + Receiver ethgo.Address + // Data is the decoded 'data' field from the event + Data []byte +} + +// ToMap converts StateSyncEvent to map +func (sse *StateSyncEvent) ToMap() map[string]interface{} { + return map[string]interface{}{ + "id": sse.ID, + "sender": sse.Sender, + "receiver": sse.Receiver, + "data": sse.Data, + } +} + +// ToABI converts StateSyncEvent to ABI +func (sse *StateSyncEvent) EncodeAbi() ([]byte, error) { + return stateSyncABIType.Encode([]interface{}{sse.ToMap()}) +} + +func (sse *StateSyncEvent) String() string { + return fmt.Sprintf("Id=%d, Sender=%v, Target=%v", sse.ID, sse.Sender, sse.Receiver) +} + +type StateSyncProof struct { + Proof []Hash + StateSync *StateSyncEvent +} + +// EncodeAbi contains logic for encoding given ABI data +func (ssp *StateSyncProof) EncodeAbi() ([]byte, error) { + return ExecuteStateSyncABIMethod.Encode([2]interface{}{ssp.Proof, ssp.StateSync.ToMap()}) +} + +// DecodeAbi contains logic for decoding given ABI data +func (ssp *StateSyncProof) DecodeAbi(txData []byte) error { + if len(txData) < abiMethodIDLength { + return fmt.Errorf("invalid proof data, len = %d", len(txData)) + } + + rawResult, err := ExecuteStateSyncABIMethod.Inputs.Decode(txData[abiMethodIDLength:]) + if err != nil { + return err + } + + result, isOk := rawResult.(map[string]interface{}) + if !isOk { + return fmt.Errorf("invalid proof data") + } + + stateSyncEventEncoded, isOk := result["obj"].(map[string]interface{}) + if !isOk { + return fmt.Errorf("invalid state sync data") + } + + proofEncoded, isOk := result["proof"].([][32]byte) + if !isOk { + return fmt.Errorf("invalid proof data") + } + + id, isOk := stateSyncEventEncoded["id"].(*big.Int) + if !isOk { + return fmt.Errorf("invalid state sync event id") + } + + senderEthgo, isOk := stateSyncEventEncoded["sender"].(ethgo.Address) + if !isOk { + return fmt.Errorf("invalid state sync sender field") + } + + receiverEthgo, isOk := stateSyncEventEncoded["receiver"].(ethgo.Address) + if !isOk { + return fmt.Errorf("invalid state sync receiver field") + } + + data, isOk := stateSyncEventEncoded["data"].([]byte) + if !isOk { + return fmt.Errorf("invalid state sync data field") + } + + stateSync := &StateSyncEvent{ + ID: id.Uint64(), + Sender: senderEthgo, + Receiver: receiverEthgo, + Data: data, + } + + proof := make([]Hash, len(proofEncoded)) + for i := 0; i < len(proofEncoded); i++ { + proof[i] = Hash(proofEncoded[i]) + } + + *ssp = StateSyncProof{ + Proof: proof, + StateSync: stateSync, + } + + return nil +} + +type ExitProof struct { + Proof []Hash + LeafIndex uint64 +} diff --git a/types/transaction.go b/types/transaction.go index 92d4ef5e2c..a66a94a3ba 100644 --- a/types/transaction.go +++ b/types/transaction.go @@ -5,57 +5,67 @@ import ( "math/big" "sync/atomic" + "github.com/0xPolygon/polygon-edge/helper/common" "github.com/0xPolygon/polygon-edge/helper/keccak" ) +const ( + // StateTransactionGasLimit is arbitrary default gas limit for state transactions + StateTransactionGasLimit = 1000000 +) + +// TxType is the transaction type. type TxType byte +// List of supported transaction types const ( - LegacyTx TxType = 0x0 - StateTx TxType = 0x7f - - StateTransactionGasLimit = 1000000 // some arbitrary default gas limit for state transactions + LegacyTx TxType = 0x0 + StateTx TxType = 0x7f + DynamicFeeTx TxType = 0x02 ) func txTypeFromByte(b byte) (TxType, error) { tt := TxType(b) switch tt { - case LegacyTx, StateTx: + case LegacyTx, StateTx, DynamicFeeTx: return tt, nil default: return tt, fmt.Errorf("unknown transaction type: %d", b) } } +// String returns string representation of the transaction type. func (t TxType) String() (s string) { switch t { case LegacyTx: return "LegacyTx" case StateTx: return "StateTx" + case DynamicFeeTx: + return "DynamicFeeTx" } return } type Transaction struct { - Nonce uint64 - GasPrice *big.Int - Gas uint64 - To *Address - Value *big.Int - Input []byte - V *big.Int - R *big.Int - S *big.Int - Hash Hash - From Address + Nonce uint64 + GasPrice *big.Int + GasTipCap *big.Int + GasFeeCap *big.Int + Gas uint64 + To *Address + Value *big.Int + Input []byte + V, R, S *big.Int + Hash Hash + From Address Type TxType // Cache - size atomic.Value + size atomic.Pointer[uint64] } // IsContractCreation checks if tx is contract creation @@ -86,6 +96,16 @@ func (t *Transaction) Copy() *Transaction { tt.GasPrice.Set(t.GasPrice) } + tt.GasTipCap = new(big.Int) + if t.GasTipCap != nil { + tt.GasTipCap.Set(t.GasTipCap) + } + + tt.GasFeeCap = new(big.Int) + if t.GasFeeCap != nil { + tt.GasFeeCap.Set(t.GasFeeCap) + } + tt.Value = new(big.Int) if t.Value != nil { tt.Value.Set(t.Value) @@ -109,32 +129,79 @@ func (t *Transaction) Copy() *Transaction { // Cost returns gas * gasPrice + value func (t *Transaction) Cost() *big.Int { - total := new(big.Int).Mul(t.GasPrice, new(big.Int).SetUint64(t.Gas)) - total.Add(total, t.Value) + var factor *big.Int + + if t.GasFeeCap != nil && t.GasFeeCap.BitLen() > 0 { + factor = new(big.Int).Set(t.GasFeeCap) + } else { + factor = new(big.Int).Set(t.GasPrice) + } + + total := new(big.Int).Mul(factor, new(big.Int).SetUint64(t.Gas)) + total = total.Add(total, t.Value) return total } +// GetGasPrice returns gas price if not empty, or calculates one based on +// the given EIP-1559 fields if exist +// +// Here is the logic: +// - use existing gas price if exists +// - or calculate a value with formula: min(gasFeeCap, gasTipCap * baseFee); +func (t *Transaction) GetGasPrice(baseFee uint64) *big.Int { + if t.GasPrice != nil && t.GasPrice.BitLen() > 0 { + return new(big.Int).Set(t.GasPrice) + } else if baseFee == 0 { + return new(big.Int) + } + + gasFeeCap := new(big.Int) + if t.GasFeeCap != nil { + gasFeeCap = gasFeeCap.Set(t.GasFeeCap) + } + + gasTipCap := new(big.Int) + if t.GasTipCap != nil { + gasTipCap = gasTipCap.Set(t.GasTipCap) + } + + gasPrice := new(big.Int) + if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 { + gasPrice = common.BigMin( + new(big.Int).Add( + gasTipCap, + new(big.Int).SetUint64(baseFee), + ), + new(big.Int).Set(gasFeeCap), + ) + } + + return gasPrice +} + func (t *Transaction) Size() uint64 { if size := t.size.Load(); size != nil { - sizeVal, ok := size.(uint64) - if !ok { - return 0 - } - - return sizeVal + return *size } size := uint64(len(t.MarshalRLP())) - t.size.Store(size) + t.size.Store(&size) return size } -func (t *Transaction) ExceedsBlockGasLimit(blockGasLimit uint64) bool { - return t.Gas > blockGasLimit -} +// EffectiveTip defines effective tip based on tx type. +// Spec: https://eips.ethereum.org/EIPS/eip-1559#specification +// We use EIP-1559 fields of the tx if the london hardfork is enabled. +// Effective tip be came to be either gas tip cap or (gas fee cap - current base fee) +func (t *Transaction) EffectiveTip(baseFee uint64) *big.Int { + if t.GasFeeCap != nil && t.GasTipCap != nil { + return common.BigMin( + new(big.Int).Sub(t.GasFeeCap, new(big.Int).SetUint64(baseFee)), + new(big.Int).Set(t.GasTipCap), + ) + } -func (t *Transaction) IsUnderpriced(priceLimit uint64) bool { - return t.GasPrice.Cmp(big.NewInt(0).SetUint64(priceLimit)) < 0 + return t.GetGasPrice(baseFee) } diff --git a/types/types.go b/types/types.go index 692fba9d71..71b02e13eb 100644 --- a/types/types.go +++ b/types/types.go @@ -11,15 +11,33 @@ import ( "github.com/0xPolygon/polygon-edge/helper/keccak" ) -var ZeroAddress = Address{} -var ZeroHash = Hash{} - const ( HashLength = 32 AddressLength = 20 + + SignatureSize = 4 ) -const SignatureSize = 4 +var ( + // ZeroAddress is the default zero address + ZeroAddress = Address{} + + // ZeroHash is the default zero hash + ZeroHash = Hash{} + + // ZeroNonce is the default empty nonce + ZeroNonce = Nonce{} + + // EmptyRootHash is the root when there are no transactions + EmptyRootHash = StringToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + + // EmptyUncleHash is the root when there are no uncles + EmptyUncleHash = StringToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") + + // EmptyCodeHash is the root where there is no code. + // Equivalent of: `types.BytesToHash(crypto.Keccak256(nil))` + EmptyCodeHash = StringToHash("0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470") +) type Hash [HashLength]byte @@ -123,6 +141,27 @@ func StringToBytes(str string) []byte { return b } +// IsValidAddress checks if provided string is a valid Ethereum address +func IsValidAddress(address string) error { + // remove 0x prefix if it exists + if strings.HasPrefix(address, "0x") { + address = address[2:] + } + + // decode the address + decodedAddress, err := hex.DecodeString(address) + if err != nil { + return fmt.Errorf("address %s contains invalid characters", address) + } + + // check if the address has the correct length + if len(decodedAddress) != AddressLength { + return fmt.Errorf("address %s has invalid length", address) + } + + return nil +} + // UnmarshalText parses a hash in hex syntax. func (h *Hash) UnmarshalText(input []byte) error { *h = BytesToHash(StringToBytes(string(input))) @@ -194,14 +233,6 @@ func encodeToHex(b []byte) []byte { return []byte("0x" + str) } -var ( - // EmptyRootHash is the root when there are no transactions - EmptyRootHash = StringToHash("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") - - // EmptyUncleHash is the root when there are no uncles - EmptyUncleHash = StringToHash("0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347") -) - type Trace struct { // AccountTrie is the partial trie for the account merkle trie touched during the block AccountTrie map[string]string `json:"accountTrie"` @@ -311,3 +342,13 @@ type Proof struct { Data []Hash // the proof himself Metadata map[string]interface{} } + +type OverrideAccount struct { + Nonce *uint64 + Code []byte + Balance *big.Int + State map[Hash]Hash + StateDiff map[Hash]Hash +} + +type StateOverride map[Address]OverrideAccount diff --git a/types/types_test.go b/types/types_test.go index 82d6ae3ed6..26d1b982e7 100644 --- a/types/types_test.go +++ b/types/types_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestEIP55(t *testing.T) { @@ -68,15 +69,17 @@ func TestEIP55(t *testing.T) { func TestTransactionCopy(t *testing.T) { addrTo := StringToAddress("11") txn := &Transaction{ - Nonce: 0, - GasPrice: big.NewInt(11), - Gas: 11, - To: &addrTo, - Value: big.NewInt(1), - Input: []byte{1, 2}, - V: big.NewInt(25), - S: big.NewInt(26), - R: big.NewInt(27), + Nonce: 0, + GasTipCap: big.NewInt(11), + GasFeeCap: big.NewInt(11), + GasPrice: big.NewInt(11), + Gas: 11, + To: &addrTo, + Value: big.NewInt(1), + Input: []byte{1, 2}, + V: big.NewInt(25), + S: big.NewInt(26), + R: big.NewInt(27), } newTxn := txn.Copy() @@ -84,3 +87,28 @@ func TestTransactionCopy(t *testing.T) { t.Fatal("[ERROR] Copied transaction not equal base transaction") } } + +func TestIsValidAddress(t *testing.T) { + t.Parallel() + + cases := []struct { + address string + isValid bool + }{ + {address: "0x123", isValid: false}, + {address: "FooBar", isValid: false}, + {address: "123FooBar", isValid: false}, + {address: "0x1234567890987654321012345678909876543210", isValid: true}, + {address: "0x0000000000000000000000000000000000000000", isValid: true}, + {address: "0x1000000000000000000000000000000000000000", isValid: true}, + } + + for _, c := range cases { + err := IsValidAddress(c.address) + if c.isValid { + require.NoError(t, err) + } else { + require.Error(t, err) + } + } +} diff --git a/validators/store/contract/contract_test.go b/validators/store/contract/contract_test.go index e164538126..d0a7f72e50 100644 --- a/validators/store/contract/contract_test.go +++ b/validators/store/contract/contract_test.go @@ -4,6 +4,10 @@ import ( "errors" "testing" + "github.com/hashicorp/go-hclog" + lru "github.com/hashicorp/golang-lru" + "github.com/stretchr/testify/assert" + "github.com/0xPolygon/polygon-edge/chain" "github.com/0xPolygon/polygon-edge/contracts/staking" "github.com/0xPolygon/polygon-edge/crypto" @@ -14,9 +18,6 @@ import ( "github.com/0xPolygon/polygon-edge/types" "github.com/0xPolygon/polygon-edge/validators" "github.com/0xPolygon/polygon-edge/validators/store" - "github.com/hashicorp/go-hclog" - lru "github.com/hashicorp/golang-lru" - "github.com/stretchr/testify/assert" ) var ( @@ -82,6 +83,9 @@ func newTestTransition( ex := state.NewExecutor(&chain.Params{ Forks: chain.AllForksEnabled, + BurnContract: map[uint64]types.Address{ + 0: types.ZeroAddress, + }, }, st, hclog.NewNullLogger()) rootHash, err := ex.WriteGenesis(nil, types.Hash{}) From 4c04970afe34917692685f25c3c49d6188cfa6b6 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Thu, 20 Jul 2023 10:08:27 +0200 Subject: [PATCH 19/24] Add current node to trace in case of deletion --- state/immutable-trie/trie.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/state/immutable-trie/trie.go b/state/immutable-trie/trie.go index f71d8a7cdc..2ae8764924 100644 --- a/state/immutable-trie/trie.go +++ b/state/immutable-trie/trie.go @@ -471,6 +471,10 @@ func (t *Txn) delete(node Node, search []byte) (Node, bool) { nc = aux } + if t.tracer != nil { + t.tracer.Trace(nc) + } + obj, ok := nc.(*ShortNode) if !ok { obj := &ShortNode{} From 20e45d0de516daf2b3235a33f484293f0459aa3d Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Tue, 25 Jul 2023 15:51:10 +0200 Subject: [PATCH 20/24] Add test to verify that the nodes in the tracer are of the expected type --- state/immutable-trie/trie_test.go | 37 ++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/state/immutable-trie/trie_test.go b/state/immutable-trie/trie_test.go index 9d1c8fc818..bb003f4f6c 100644 --- a/state/immutable-trie/trie_test.go +++ b/state/immutable-trie/trie_test.go @@ -1,12 +1,12 @@ package itrie import ( - "fmt" "math/big" "testing" "github.com/0xPolygon/polygon-edge/state" "github.com/0xPolygon/polygon-edge/types" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/syndtr/goleveldb/leveldb" ldbstorage "github.com/syndtr/goleveldb/leveldb/storage" @@ -19,6 +19,11 @@ func TestTrie_Proof(t *testing.T) { } val := acct.MarshalWith(&fastrlp.Arena{}).MarshalTo(nil) + acct2 := state.Account{ + Balance: big.NewInt(20), + } + val2 := acct2.MarshalWith(&fastrlp.Arena{}).MarshalTo(nil) + tt := NewTrie() ldbStorage := ldbstorage.NewMemStorage() @@ -30,20 +35,36 @@ func TestTrie_Proof(t *testing.T) { kv := NewKV(ldb) txn := tt.Txn(kv) - txn.Insert([]byte{0x1, 0x2}, val) - txn.Insert([]byte{0x1, 0x1}, val) - tracer := &tracer{ + tr := &tracer{ isAccountTrie: true, trace: &types.Trace{}, } - txn.tracer = tracer + txn.tracer = tr _, err = txn.Hash() require.NoError(t, err) + + txn.Insert([]byte{0x1, 0x2}, val) + txn.Insert([]byte{0x1, 0x3}, val2) txn.Lookup([]byte{0x1, 0x2}) - tracer.Proof() - fmt.Println(tracer.trace.AccountTrie) - fmt.Println(tracer.trace.StorageTrie) + txn.Delete([]byte{0x1, 0x3}) + + assert.IsType(t, &ShortNode{}, tr.nodes[0]) + assert.IsType(t, &FullNode{}, tr.nodes[1]) + assert.IsType(t, &ShortNode{}, tr.nodes[2]) + assert.IsType(t, &ValueNode{}, tr.nodes[3]) + _, h := tr.nodes[1].Hash() + assert.False(t, h) + + n := tr.nodes[4].(*ShortNode) + v, _ := n.child.Hash() + assert.Equal(t, val, v) + + tr.Proof() + + for k, v := range tr.trace.AccountTrie { + t.Logf("key: %s, value: %s\n", k, v) + } } From c38f3f2b60bed850d8c0c95e63a9dc765050c078 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Thu, 27 Jul 2023 16:46:12 +0200 Subject: [PATCH 21/24] wip --- state/immutable-trie/trie_test.go | 99 +++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/state/immutable-trie/trie_test.go b/state/immutable-trie/trie_test.go index bb003f4f6c..9f11718e0f 100644 --- a/state/immutable-trie/trie_test.go +++ b/state/immutable-trie/trie_test.go @@ -1,7 +1,11 @@ package itrie import ( + "encoding/hex" + "encoding/json" + "io/ioutil" "math/big" + "os" "testing" "github.com/0xPolygon/polygon-edge/state" @@ -13,6 +17,64 @@ import ( "github.com/umbracle/fastrlp" ) +type traceStore struct { + // trace is the object that holds the traces + trace *types.Trace +} + +func NewTraceStore(trace *types.Trace) Storage { + return &traceStore{ + trace: trace, + } +} + +func (traceStore) Put(k, v []byte) { +} + +func (ts *traceStore) Get(k []byte) ([]byte, bool) { + return nil, false +} + +func (traceStore) Batch() Batch { + return nil +} + +func (traceStore) SetCode(hash types.Hash, code []byte) { + +} + +func (traceStore) GetCode(hash types.Hash) ([]byte, bool) { + return nil, false +} + +func (traceStore) Close() error { + return nil +} + +func LoadTrace() (*types.Trace, error) { + // Load Trace structure from JSON file. + traceFile, err := os.Open("7410_readable.json") + if err != nil { + return nil, err + } + defer traceFile.Close() + + // Read JSON file and desrialize it into Trace structure. + // Read the whole file + tf, err := ioutil.ReadAll(traceFile) + if err != nil { + return nil, err + } + + trace := &types.Trace{} + err = json.Unmarshal(tf, trace) + if err != nil { + return nil, err + } + + return trace, nil +} + func TestTrie_Proof(t *testing.T) { acct := state.Account{ Balance: big.NewInt(10), @@ -68,3 +130,40 @@ func TestTrie_Proof(t *testing.T) { t.Logf("key: %s, value: %s\n", k, v) } } + +func TestTrie_Load(t *testing.T) { + tt := NewTrie() + + ldbStorage := ldbstorage.NewMemStorage() + ldb, err := leveldb.Open(ldbStorage, nil) + require.NoError(t, err) + + defer ldb.Close() + + kv := NewKV(ldb) + + ltr, err := LoadTrace() + require.NoError(t, err) + // ts := NewTraceStore(ltr) + + // Load the trie from the trace. + // txn := tt.Txn(ts) + txn := tt.Txn(kv) + for k, v := range ltr.StorageTrie { + tk, _ := hex.DecodeString(k) + tv, _ := hex.DecodeString(v) + + txn.Insert(tk, tv) + } + tt = txn.Commit() + + for _, txt := range ltr.TxnTraces { + je := txt.Delta[types.StringToAddress("0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429")] + for slot, _ := range je.Storage { + v := txn.Lookup(slot.Bytes()) + if v == nil { + t.Logf("slot %s not found", slot) + } + } + } +} From b4d8a70bcb40eaa3bd8bfd8a134929d0f0b83267 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Sat, 29 Jul 2023 21:22:51 +0200 Subject: [PATCH 22/24] wip --- state/immutable-trie/trie_test.go | 79 ++++++++++++++++--------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/state/immutable-trie/trie_test.go b/state/immutable-trie/trie_test.go index 9f11718e0f..119613a9af 100644 --- a/state/immutable-trie/trie_test.go +++ b/state/immutable-trie/trie_test.go @@ -19,37 +19,36 @@ import ( type traceStore struct { // trace is the object that holds the traces - trace *types.Trace + tr *tracer } -func NewTraceStore(trace *types.Trace) Storage { +func NewTraceStore(tr *tracer) Storage { return &traceStore{ - trace: trace, + tr: tr, } } -func (traceStore) Put(k, v []byte) { -} - func (ts *traceStore) Get(k []byte) ([]byte, bool) { - return nil, false -} - -func (traceStore) Batch() Batch { - return nil -} - -func (traceStore) SetCode(hash types.Hash, code []byte) { + var v string + if ts.tr.isAccountTrie { + v = ts.tr.trace.AccountTrie[hex.EncodeToString(k)] + } else { + v = ts.tr.trace.StorageTrie[hex.EncodeToString(k)] + } + val, _ := hex.DecodeString(v) -} + if len(val) == 0 { + return nil, false + } -func (traceStore) GetCode(hash types.Hash) ([]byte, bool) { - return nil, false + return val, true } -func (traceStore) Close() error { - return nil -} +func (traceStore) Put(k, v []byte) {} +func (traceStore) Batch() Batch { return nil } +func (traceStore) SetCode(hash types.Hash, code []byte) {} +func (traceStore) GetCode(hash types.Hash) ([]byte, bool) { return nil, false } +func (traceStore) Close() error { return nil } func LoadTrace() (*types.Trace, error) { // Load Trace structure from JSON file. @@ -132,38 +131,44 @@ func TestTrie_Proof(t *testing.T) { } func TestTrie_Load(t *testing.T) { - tt := NewTrie() + //tt := NewTrie() - ldbStorage := ldbstorage.NewMemStorage() - ldb, err := leveldb.Open(ldbStorage, nil) + ltr, err := LoadTrace() require.NoError(t, err) - defer ldb.Close() + accountTracer := &tracer{ + isAccountTrie: true, + trace: ltr, + } + ts := NewTraceStore(accountTracer) + s := NewState(ts) + sn, err := s.NewSnapshotAt(ltr.ParentStateRoot) + require.NoError(t, err) - kv := NewKV(ldb) + acc, err := sn.GetAccount(types.StringToAddress("0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429")) + require.NoError(t, err) - ltr, err := LoadTrace() + storageTracer := &tracer{ + isAccountTrie: false, + trace: ltr, + } + ts = NewTraceStore(storageTracer) + s = NewState(ts) + tt, err := s.newTrieAt(acc.Root) require.NoError(t, err) - // ts := NewTraceStore(ltr) // Load the trie from the trace. - // txn := tt.Txn(ts) - txn := tt.Txn(kv) - for k, v := range ltr.StorageTrie { - tk, _ := hex.DecodeString(k) - tv, _ := hex.DecodeString(v) - - txn.Insert(tk, tv) - } - tt = txn.Commit() + txn := tt.Txn(ts) for _, txt := range ltr.TxnTraces { je := txt.Delta[types.StringToAddress("0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429")] - for slot, _ := range je.Storage { + for slot, val := range je.Storage { v := txn.Lookup(slot.Bytes()) if v == nil { t.Logf("slot %s not found", slot) } + + assert.Equal(t, val.Bytes(), v) } } } From 722bcc50b30998d6ac952418c984452f563ad1c1 Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Sun, 30 Jul 2023 19:53:39 +0200 Subject: [PATCH 23/24] Missing slot trie --- state/immutable-trie/trie_test.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/state/immutable-trie/trie_test.go b/state/immutable-trie/trie_test.go index 119613a9af..ec109e0834 100644 --- a/state/immutable-trie/trie_test.go +++ b/state/immutable-trie/trie_test.go @@ -3,6 +3,7 @@ package itrie import ( "encoding/hex" "encoding/json" + "fmt" "io/ioutil" "math/big" "os" @@ -34,10 +35,12 @@ func (ts *traceStore) Get(k []byte) ([]byte, bool) { v = ts.tr.trace.AccountTrie[hex.EncodeToString(k)] } else { v = ts.tr.trace.StorageTrie[hex.EncodeToString(k)] + // fmt.Printf("key: %s, value: %s\n", hex.EncodeToString(k), v) } val, _ := hex.DecodeString(v) if len(val) == 0 { + fmt.Printf("**** value not found for key: %s\n", hex.EncodeToString(k)) return nil, false } @@ -52,7 +55,8 @@ func (traceStore) Close() error { return nil } func LoadTrace() (*types.Trace, error) { // Load Trace structure from JSON file. - traceFile, err := os.Open("7410_readable.json") + // traceFile, err := os.Open("7410_readable.json") + traceFile, err := os.Open("../../test-chain-1/consensus/trace_140.json") if err != nil { return nil, err } @@ -145,7 +149,8 @@ func TestTrie_Load(t *testing.T) { sn, err := s.NewSnapshotAt(ltr.ParentStateRoot) require.NoError(t, err) - acc, err := sn.GetAccount(types.StringToAddress("0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429")) + addr := types.StringToAddress("0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429") + acc, err := sn.GetAccount(addr) require.NoError(t, err) storageTracer := &tracer{ @@ -160,15 +165,17 @@ func TestTrie_Load(t *testing.T) { // Load the trie from the trace. txn := tt.Txn(ts) + txn.Insert(types.StringToBytes("0x0000000000000000000000000000000000000000000000000000000000000002"), types.StringToBytes("0x00000000000000000000000000000000000000000000000000000000000048d1")) + for _, txt := range ltr.TxnTraces { - je := txt.Delta[types.StringToAddress("0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429")] - for slot, val := range je.Storage { + je := txt.Delta[addr] + for slot, _ := range je.StorageRead { v := txn.Lookup(slot.Bytes()) if v == nil { t.Logf("slot %s not found", slot) } - assert.Equal(t, val.Bytes(), v) + // assert.Equal(t, val.Bytes(), v) } } } From e751a63e239fa49798dcdde819d47b7e7b90a90f Mon Sep 17 00:00:00 2001 From: Victor Castell Date: Mon, 31 Jul 2023 12:06:37 +0200 Subject: [PATCH 24/24] wip --- state/immutable-trie/7410_readable.json | 656 ++++++++++++++++++++++++ state/immutable-trie/trie_test.go | 8 +- types/types.go | 2 +- 3 files changed, 662 insertions(+), 4 deletions(-) create mode 100644 state/immutable-trie/7410_readable.json diff --git a/state/immutable-trie/7410_readable.json b/state/immutable-trie/7410_readable.json new file mode 100644 index 0000000000..7e582d47ff --- /dev/null +++ b/state/immutable-trie/7410_readable.json @@ -0,0 +1,656 @@ +{ + "accountTrie": { + "079a8ca10bd34244e1c9c92980526f090ec6b6cac52992a6a2d4c8f78f35180f": "f851808080a01a43c8e838c70073f22eb72cef68940e72a4b6a8711a73fc40c4803a47c4787f80a0aa0501033b4cb2732f45ac6ec31a3f58bd21b4a8d675dd4e9d143a3ebef9f5508080808080808080808080", + "1a43c8e838c70073f22eb72cef68940e72a4b6a8711a73fc40c4803a47c4787f": "f873a02080c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312ab850f84e808ad3c21bcecd03172430aba056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "1cbf50250961fcceddf28e78b51758a27697625fb4f41547380286d38690efcf": "f85180a031d1eb10fdf37ef90417d463e9e3d1dad5bab6a3e8b38ccc4eaa744250317457808080a0e98d73f14c784cb1a2782058fabda51afdb2e6f19347bfa00299c0fd960275438080808080808080808080", + "7af909cad6f85f8cde7145f8ce00e6291269d63bb3145b9c6b0ba7d1bfdb3fe3": "f873a020d511612a04be33a906f4a2f355cad1fe0ff4e5259b845677431e9de1a89524b850f84e808ad3c21bcecceda1000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "b57c2d7989e9b67f8e019850d3d8a8290e971398b028e458728351578dea7b4d": "f8769f3eec2b84f0ba344fd4b4d2f022469febe7a772c4789acfc119eb558ab1da3db854f8528248d08c033b2e3c9fd0803ce8000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "cbccf9f17eecc98379ccf4a140a026a8c2585ca3b0901563e4f9a9f1b15907c7": "f901d1a03f84f317ceea01d67e9da286f143aea01d93cc275c3d9fad2722ce1aeb8a39bf80a0a65cefec668d4a8caa4614f5bd8c22cb6a89387efd124add03c6a29f7ca5c4f7a0ec7a9e4d6b11b2e73c2950ef2c2eb3109007070aa184d928abb3593332366f52a00a5426c2c1c724762a0a59e81f6d3386d66d7fd5b0f2e8909eaafd4d590355f2a0079a8ca10bd34244e1c9c92980526f090ec6b6cac52992a6a2d4c8f78f35180fa048431a96134f4c7b241dd5c282c352e9ed6e8c0a0cc0663b6dc435514d29d829a0e31ed7224b4a1d1fb39677e4a2e7404b8dccd70bfa62725fb24377c71cab65a9a0364969fa64ed1edef177b8a87bbe20e26615582bf935df361abf64c0b7e2b589a0a20860bef0bc90a25310ca9dfde953060116407763f668bd32cba72582909d1ca01cbf50250961fcceddf28e78b51758a27697625fb4f41547380286d38690efcfa07f20ac3a7307ee8054cfb13327949b7cb3c4ba129bb2c9efc225a1cbba70e12aa0e0a430b6cc0eb1c8f2160c8f114e5f53df7da2adb83ad4cc4df66fed88cf80c980a00627f2d180ee2cb033d4dcd5572903723c4fad4f6fb41ebd7b7f58cd0c347145a00f31a4067b26d457ae8724a2d8d41d63bc9f4ec34c008c959b5528d040f6bb0880", + "e0a430b6cc0eb1c8f2160c8f114e5f53df7da2adb83ad4cc4df66fed88cf80c9": "f8518080808080a0f4bfbde517227e1dc06a4f7dad964f892016b10b8f7e34a6b785df99b778e3048080a02b552522c790b0433d466408318c5c61bfa7e2dbb9c2e13bfec3d1d51290addd8080808080808080", + "e31ed7224b4a1d1fb39677e4a2e7404b8dccd70bfa62725fb24377c71cab65a9": "f8918080808080808080a00ba7e530fe4d735de2592c5638b234c135d2f70c088da1e20605596e33332ebca07af909cad6f85f8cde7145f8ce00e6291269d63bb3145b9c6b0ba7d1bfdb3fe3808080a08a0977db0c40a342485134dc58b8ec9ca0c4d0b37ec2659d0d7333265623b7f580a0e2e4bceb82b6f7009ba7fc3c188cae32138588d9d6c69b97933388e7e02ac69980", + "e98d73f14c784cb1a2782058fabda51afdb2e6f19347bfa00299c0fd96027543": "f85180a0b57c2d7989e9b67f8e019850d3d8a8290e971398b028e458728351578dea7b4d80808080808080808080a0b352e4c72d853473be5eac69cf10adfdc61a3747ec26a4b424f0a29292fc1d3780808080", + "f4bfbde517227e1dc06a4f7dad964f892016b10b8f7e34a6b785df99b778e304": "f869a02058c2c1ac06ad29eab5b631a2a76f7997030f5468deb7f384eb6e276208d046b846f8440180a0135f236339b97faa1a721e7235b386ca95080dfba8b57f0cbb2dd58959819bf7a0e86cf7cc93bf311f1751ca156a07c54a62d0769f9a09b61afd05b037a4713e1b" + }, + "storageTrie": { + "00567c7cdd86650bec3c336cc930aa05ac2b63e92fa726b295bff1978dc6ab9e": "f90211a0471068f6b9e2fd5175d0dffd385eefdd104b4dc9f5800842cf3ec8d4bbe6bebfa0a9dcf1378700d82c908f416919d9bacd50484ffaff9d6ad59c334ce7f4501466a0bcfac5f6db5e6818f4224f192b1f3a0486397d8828bb24067c1433476bd29b3ca04ed4f6c0ca3c5a4ce495b86dd1cf9cfa8240c2e335c3a8a551756ed0d3570f7aa0187a59c4a4995516cc2bc5cda57dbd92c3bbe4ab9609b9cf20ca2fb1a53a2da7a0e4ac1f6f1954c232b2e52095e2da95e6faa424c3ac50b093929ab46bae55b8d0a0aa3440ac48aab334411813b2c19565d9d203b8d2290d10d857c1a0a21300216fa087b63dcd8946445efd03560e7e9da922168ec931203738dacbfc15d6aad1125ca056bde8be391a620b0403918362c2d23efab0611b7a71fc82fb070d127bec045da072d7c05b767b37ce2df41e072e926c8fa9b81ea1782b74b6e3ce48c233e41e9aa02b57918ad63adfbc7568eb010a3a913dcd05c4c062aee46bcd833b27476a612fa0f68386f34ac8642aed0dfd1ef529744d637d5aa4e176b899156aa8847114fd63a0c46f88be29860c109dbd7aee11778ea53e58323086ad7ba9a1bed3baf737eed6a0a367e4d9a3be5c6062d88e2139348149fb76b2e80e91457f5dfee989f3c0c017a01fa007ed8b910d71ebeb5c50615c0241e48ed5d4553e08b43bb6cdccebf485f8a0760214f1ea0c2a4b06303ff42deef40df228e03ef56526b3d846cf7a0cce0f5380", + "00a7df79be1db7e933de735cae2a7f090c2a7a9aa53d0f5f644bd09a07d13134": "f8419e33037749bf5af8ba3f2c748cfebcf81578c7c063fbeede49b5661b6a1b22a1a0defec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de", + "00f493022e2595e2ae4e7f3200f3227c21890da2f6b41d4a7ae3711d33728e38": "f90211a0bfe397072abb61b53b346d53ddbef46adaf6ec501d43c3d396f97739b4b80520a0f92ae4b2d9ef7de568091b7e2e132ec7a062f8ca28cb242d7e55cfcc30f58d36a051dadc1aa4646d72ec841f2c4023909d8e14707ebb7152fa17fd6e2e297107bca0b5a62a82b7639bfcc169b8f9877776edb5424c9ccf99290f1ea7a4daaf27c554a0cebc3fad56671c5769e75c9ddfe1a2b5704b2e90ca22b9b99ae637820a5ebb64a02e219edc68e9b851c1e25837004ba7d0bb626c0070dfd5a36da149d97de5625ba028acbe1752d045030eed44d425ba79c1af43ef8d0476f6d68376981e5e88acfba001b5416200b4750bec0d2bb6b699fe5d2844187a39a7f9609d4f8e0acda82fe3a001a50169f40ff2c5591c1016934015a78bb65b409005caf8194a102940ec16f0a0c0ba342529964c458d74e308a4c5d3b820d9fe070977a0b6e522fc6fe9f62202a06165f5b68d169b0e0735d19bca33c657410a16aa1659a177868094ebcc097a87a078ce528bcb17b0b62486027de39829ed320651c9c039a15b4d19f015c3cea6bfa08fbbb331f552a4947045918b81db1602022564eb1bdfd142f584f42a69d4f36fa02951268a9660414df24770534c3684e7a30aeafd3ce267d112859abc25e5a20ba026bb1e4c5601ac6aa3215f6c2b4380048f9cc86e134f755006490d7e726db2c0a0b061012d20af5d234bd35f2fc151d1d317bd16de22285f86e62f111e0b8a688380", + "015d270f3764bf8ae4eee0a546ac8ffd49b0c9ee885245df980a0c4e182563aa": "f90211a0e141fcb98f85e87bb8b8ce35c883974acdbefc3873d44576bdc99d580e76ec92a077ee2dc4146a32b01e8460db3274e890ff27ff6718bee07c2e81f5ab56064f1aa0c69723b8eee941c18761a9b0c92e3909b57af75d9e70263a8f9a411f39528502a048ca89beb7163525e531cf8acb18cef55918a08c5f8e13edc845f19daf9891c4a08583c4c6edb284e6af62277e6b891664999951135074e0a5981c9ddd5155b9e7a0f4dc42e7ded8ede43acd6e6be2bc324619b9cf93fc4432607ac2bd1855e70e75a079ac01e942f819ab0106fa9bb0486362da2f7581a15fa36961310b8b2afb517ba09bf65427d3a6ec93b8ddb161404fa06cebd03fa51d737b424c24d76d49157ccfa00779dda32eaa328229b98306a77ec4a298f1c5d47c20fcfffff947441ace05b4a065ff0b248aade96072df8d754591771ea679a585d7445c0a75d9d2221c0c6c6ba0791febdcee78f9a456b93d6837a3af10b52e2df5eab377b3ef9a4420c46028d6a0aad09f05adbd6b308b30ec2c69ec9c88b41832ef9ddf187c18047b4efc742d7ba001e6ea3a8b0f065897e39f412c0ea373e09b3ad6ff5c45c48abee880930f8773a06b513933b6e3a5974c1af516bad9feab7ff8a10c47dc957e15fd04cc650d96d6a0289169dd3d8ad996e9d9351df718f7c56cd8a510b0765df5ba763a78fdf4c7c3a0fa34e726a851f88ebf246cc2c108e0fcf7a02f53b80aff0ec56fce187fdcb46480", + "023e05f135e193efdddbaee178977c260cefcfce0a49f16d669e09841e6abcaf": "f90111a07458bb22b218094949c3434a71467499ad4738a5b5dec09108807c0bd7a5efb8a053430e03d5bddfa87d798fd75ad0d150f88250c21788a9b5685a74f7bbe525e58080a049607ff8e8a4c2cfdceb12e03f0b13166ae9d6ad163f2f6873c2760a48543baaa0390ca4accb091aead43fb495f8a0dafcda165c4ca908b86e60750920ea9a8d6f80808080a00f2e9306cb003bf4f5e06e1715074bc6cf57984ef0ad4336f05457b63f5980a880a0267f17046e467e9f11a6fcd873f68de23edbd1b98e3cde996c8650e0a54faddaa0fb8c0ecbbb25d738bd8fbdd89e5f6c9ddecdb6c8fc72ba6a4bbd9feb3b6f6deda098860b5844e3a8e8c13d05275b4a0bf7be7e4d5b47e14ec7975886318d1923a88080", + "02788dddd0412b9776b73bb77e9ee771f7458bd7499b4b1f0af897f885c7c6a3": "f8d18080a0e943b01b078864d06f02501832b0707d072728d512b1b30291b7c782ac52a3a2a0011593f4317372286957e8f9b47a6f38468660fee1297eba774658deaeae118fa0f0b6554e3c7aa535de48890ed6626ba9dd75b7ed46c636c347df49d2880ef62580808080a0a3004dbd486c091bf1a04e09c3e0a628f904093122682406523eb69f630956b38080a03fbe3364c2a2450528278f488da3918dbd14839a0a43514d60bd665fbc1f8bea8080a0dbcc017e0b20bd7c82c3eb9d6396dfa68a2e0d67051fa3322b4e372ec3ed47ba80", + "029992bf1bd117630e2a7b067d841f7262c1cdc59102cd729e8645a6eb4181b6": "f90211a04e2584c890a0dab0f2e393e7c3a9be3fd36dd384335b7ed0acacece3be514ef5a048a7e29cf8dd0f6850ce297e689416f324acf518726998606464895039a5cf00a0b9774feda0b704119a51a7dc221a1fe8939ad401a0e513f98850e5f6d9f41a5aa0e4cfe49f69c4f5c088890253050d14907990acaf2d6496d32f7c9cbc6dc77dc7a06dff2dfad15ccca45c84bee9baf648879d79af19346b8bf37dfcaf4df54816a2a05b396e0598d4a5161e346ea0aa2fa0f50e2cb2e605282b00cbb921412a7a1a8fa07dda3f130810c3683e87d943cd258bb78e16dddd772f24ff4eea9258421a70f7a0da68687a9b35ed6f2a70b85ad12b3a045deab691b94abcd4da36555f39cb5d44a0beb8a6db01c3937079eda2cf512963ef8b155653133ed848b191f8765b1cf468a06a78de0605c5d4b535fa67d6fd11c26839791169685e97a6d2f84439903fe389a0afae15ed4d407a28eb2c6f28dcc8f849e29510efc2039448762366033bb4e3dca0eef79425f276ff1f89096d34a74891f9b831a3b77b88b89b97c65665a79d6b16a0b31b004ae4c8d3765bd8d2e09a7c83a4f43962b6d8471f00810da2a39960339ca0993701ced777f3d1699ef5268be0a3c9cf1e978ed1676ab4db44145ee14f84eea0fb00cc3fc1c54270f597f182ab1f00eadf0b5291c13ee8fbe51fc05eb3a07371a03bf3c302f951e9a100533d177aa32bd7dc07a5fc372f89f6784ee905930a9c9a80", + "02d9c976fbd2de150dd04f9f3be6968267ed8624e184a019fd61933489ae78ad": "f8419e31a80794a2e8646cf28280f9ba1296b884b97617a98db6a1a513f5fae630a1a00b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabe", + "056d8c961e5ee897ce79ed1585ebb1281c28b85f7f3b8a1bbcefa809789975a1": "f8f1808080a0a25a438b53db419b06ba86680101db133d5aa4be62a90a886c82f2ea8b8d92e6a08430b2a01eb4d75888a1e13e44c0617aea812ccced5a56ef629be8cf043b55a78080a045e7a1be1d3e871c0d76a1d15a9e1788a1e4c1d3343db8be009d032572e045cfa0a5514fce0b516ebe2169e0086954de106ae4d5e507d97ed0a89fbdca931b39b0a07bd9854e1bda3e9c6fa9ba1a4696757374e91da688250451f0b56b0fde68d038a0fcef8054763af3dff0c963f8df3d06bdfe5730257341121ee24dbfe7b3f966b28080a0a6d1b83ae92d9dc3fd1e89f255384124caea4f6ac89b55f175d35233a8ecf877808080", + "06148280c6df9f5d39b7e6c687b4fae70fbe889b8c3069e3dd79b7a2b94ff3db": "f9015180a0008dcbd554834b26d0c99a930382939fbcd288e17039539922c4898a47b97067a02bdc3168e57b967072a0020f24a4c3d60f232e04e62dfd0030618513e041cb6fa0dd0f8c2e7b991d3962bc25fb2823dced92927443b6d7121cd71083681ba9da978080a05379a17158cdf7def23141da688b505ac9078aab428ff6730d55d42b6f146a3d8080a0e953e4415ac1cd258910d8c197020418e790eed7f549ef363fefff45430ba60ba092a3db6240d350dfd3fd265ebee2e0adb1e11b29d2df757f66ff6e1312668824a0d93c4df928e125e4b02982f30a41737d8db103edc0ad7640c72f68fd51be4ab1a0cd0a2392eb551ccf3f5e00a885e3e3e9d15d3f33d485eff45f8934c24b4015b480a07bddc10bef475cb67a3d70874d5a8a855093331565b3a694e019a69e2114bf9ba0ad42351d76c77a9b6ded63e2d58d4954bab9200eb9efff12f16ff2196e89638780", + "06338a8b9ea91eddb38de1faa04e4784653e71678da5f9af483dbd1e295f623c": "f90211a070637c256d39d05beae2f655371717e0795a9f93429820dfcae562a12da5c509a0223e9a0fef9833721eab0e6bd167985074d2e3256f5a925bae949650093387ffa0e70ca022df7793435bf43c3f3b669ebe9974f74199793b417e824c025579916aa05a8eae7185727f0e3e0e55a6d1c92a02be474bf7cc0a21afc0de93f2fc548f49a059ede7c3b818979fd7bc2a01e8881cb7fd41011b1599ad3ce65248856394be6da0fd68a08f603dbd3aa5729997e4e10a83fe7e1cc3a8217c38d5a76e4e48bcce19a0365d5ba3beeaee81adc3ad3c79b18eadc5b838effbff2c9247451de2cee26b8ca05b8026fb6d9565b902fb36cc76a2e42520af3cd4647823dd43b821648adfe5c2a0d5359725bd4e840d95812a7348f72cc2b72d5848d162d3cb6ee27213af750a10a02f56b284637146d58282c18df381c05a24f063bcec312cfd8bb468f88d9df45ea08def8f5618c8805eade0f660715ab3f6cdc13f1574469ca8042b07e85dd9a1f3a01aa20da3b6e470319962a87991e8c619019af40a1980d716da7c46a11db5143fa0735970a3569f64c29296a5dfc914f5dcdaee47e7fdd52808a1b1581a2217ec48a007d77df92225fc0ec04d3b288f99d2cd45e8f32ed9cc1ac0b4f0c846b6774e28a04562853e1af3c22ebf2d2cf4b28fcc89456da9eaf2255c94d935a67257e0eb54a0c299743f285087429f19a60a2e4d07216f5fa065a3b4e2a9700e9960870b928680", + "068fdab22ea07c60658ba3d8cde35435b9eea250409af363915ba94bd41f23e4": "f90211a0b14a26936987ffb2309b25cdfd00215abe31b0a58795d3f1ea8c966ce1bd8ac3a02dae6a2796b027f9bc3237c98143d607f0f50f4e444e5599950e0958c9caeed8a07ab98847a17f5f8eae2cdd55edb0cf6ff2d4f0e6d16a3ce87f122fc85f5ca368a0233ba0c981ad18f49a6393a59ea62586780f042649ffdf038435cbaba5eacbcaa0ebfe68a5adba39698f9ff4f9797c409b44a66c36353b0a2a45197620e162fb34a0a02ef35388c0095ae15b8a1bed633f3bf03153ac99bd232e7d6254f41eaad5e5a0e1df5d8c0b6c6e069fbbb35f7fafa2c13f1423dd53b45da478a535189ac6ea34a04ca5dc5cb48efd291ba7dd10e0887fb2e2a6c76f5ac8e5b97a50c5d8583cf91aa07e6ffbad32c7e2bcabc84674ffb9eb06aa8852ade69502340f4b03b5f25ec261a03399fb6f73fc5e0be348ef5984869c69490244898506134fef35b66919f03d6aa04835ddb3e9a9e91216b09b9a9203618eb42ed80c54d5055af5ea3c8fa0f36e53a07c82972aded74f8cc215244d97e28307f73790488b7a21b5242d54bf1f40b4c8a018fc2e2330a4d429e92bdc45106fd1c82e8df26a270dba2b4449dbe0fc6052bea02c6219de2d21721a69a4e1f7e72442a2071668aa6a99c9c66ac6e8ca2ec34b8ea036374ecb0fc371680877e401f141258372589bb3af2740b6355593fc0d0bb463a0ae2cf9d86e4a3d5e79a765e518c8c3f6cf7f7b2a85dfe62ea6aaf4c4c7a69c3c80", + "0819a182c07122df1df57599dc3d6227a01a2a55e6311575b0081a8f6f14c936": "f90211a0384207a78392e2dff3dd54aba8e09417f36b656e1fc6cff26d38d371a470788ea0c61a5eafc125d17705154a826f8a0290d22bb499292e19a95c1bf6bd501d935ca0f735c55ce00c83a0273434f40fad42a3615ab48ad3f61eb3a2da59f09bc56fc1a0da47a0e34b8dc2cb429f8357f129ef6a26b6056aa51fb106363835e3aa8cb06ba04a477e1d39b740d6fb6c7c034d2f1211cceda0f46fdcd5ff09e00d66165ffb9da0cc77371dc61b9c612891413fd1d1734cf93950a472a02b10e47ed3f7e878bfbaa0fb9711856b7bf8ca08fd24700f9a9072415f85893125aaae813bcba74bddc192a02228b1ef1c31f8fa8e4e292ab9132901ddbdb6c08430e86a760894620106f419a04964e8cba605f670e80854640f6e0ba0ba69e3178721d08ecc5a47f859111878a05bbdbe0e8e741b9fbb74d182591230e0728f34bb9bb580e6aadf3fa30d48c9e9a0c93480bd8a38949cbf42c01ae88522785a105cf92d1d274a597a9a6a034861e8a05a8af56e51d32c19e910022052868ee372d4b8043886bb3e420e93824ea6b2c7a0cdcbfd97a525db5deacf713a74e2443c5ff9c540e38f070c5fa00dcffd7ee320a09583880efbffc3466a9829c43c69699ba813ccc050a0e0192ff0882f81653ac6a06fe2fcf9aed2caac885eeb8e7e407a4270f8fb30347cb01a8766f2610a6478c4a04b6c1e65a46c587ee0e548f01d907796b5fe8c7dbf6c11d0b04e92d3ba5b8c2580", + "084d01bbc325816f824a6a5cbe87962f9192be41c55a294ab54e5d2829428301": "f90211a0aa898ef3a5f2f4e44f7ea16a62bbabdc8195cd5f1d2327885b112512ca98ddefa025570eb1b43f299f201eff21394b7626ba372f518303a913d397bf0513dff07fa04ca67589dc10f9b89212ed6572af5433d9c3d82b7b652db1a808a14ae3c1fa67a04f7d4dcd20c533f5561b7274a6038360b6ffd518672f2b27ffa6e9454db1f78ca0e5cdac661e8411ef431da9abf0ecbe19fef7b490fd3f3adcc846e40fa9aba5e6a0db23e72670fb5c345e9015442e94c4668b68fd778e842598028fe0c7bf583793a067b50107a3022a9185a2b5998634c836e3161529c2c9c3631a9447e15b99b1d3a098ed64d8a838ed4b0a897a27c6ca6b8f8baf5aa3bfb5003b86072f65e85ef071a090f3b9f81e179e099b9154b6dae425d3f18352af55786e767a6cfa946d90c13ea0b79df6744f053966539abe638025db0b9456054e475acc1e28e4748a4fd6a314a01c2f1abab13692188969fe6525194d5326e0d4485bab5cc3b39a6e3f07990baaa09cbedcc8e17f42094ec6a38800cad84cc34062e64ceacb1a04ec5e3d676aa65ea0efd17f1a0824e68c8bbc8b5fb4aeab4f3ccecafdfbe98248c239ad5b19382823a099ffb746b6f7bff6e98c7bc1d1f01d5632cfd5eb2105befdddfab3be09c7a138a0801c5a05dc8488c2f83189d04aa46c58f196abfdc585b6a792ea630177fe4b97a01b36b41cf2a72f734888a55bf4346a3fa0c55ed381297ae18e74c7faddf5919780", + "088c8cf58072d3f3ccecfb162df0845a14e89281d386fb05b68d09bdd0bf7ef4": "f90211a07711a775af98e88a5f09f7e86195157fb58b7e289ca5716ccef68665d3cd79e1a0c4cec992bc6f3405d6e443264bdbcf904074e9d797bb523c69c1eae5d957aeeda0f45ba1a79edc239f7a3e2e9e14b33c699f8b2248e52a21f4ac51fc453dcf5482a0700ef44699e5759d1b4985fc5896ee96fd4ac03f76aab2f9541d0de2c5f21474a0691bb54352af6056f9593f6d906d04fbf5bd9dd52f1c2090713808b3e73ff30ba098cb8d8c9204ecf78dc89a6b9c6a617751b23a85a9ecd6f14f8fc9b996997b8ca046bd7514d99fa7db4524da6c9c0af989d2e884ad21d4699340baa991a4c7be1aa0b0bda08d6d4f44891e7faf42a539a393ef61d8c4cd42fa34c94a42d8fe2a823ea0b5d189a8b3f1a848bc326e16ea29e352847a9b2b9b2ccb053252ed555aaa0275a0da2d58f4b9eb7a2555c49d3829ef09e7089a13286faa94d42c241107ed198600a032bdf996b9f6546eaabb7949dc8900f361964625c36d9a4bdd3799d7661ab270a07c6a8ea7be2ab328b6a327153060430bd07644c5bf0ce72ee9fab2d9538cc7e2a09f8d4e079a518fca1f39788ae37f0be45918500e88e6449225f4d6f1bac70179a00983df6b8a08fa2becf5f6ec6891acb733f3b7367ac2ce33bf3e2c947fa6af4ea0ff2d76b2042a583e16cd976593ffddd8a6324037fe78dac6c896b9c1b6613750a031b879f1e9c21fff189095094a4373782a489deb28a75e426b63fd3b95c4ade180", + "0976838ecb5884eee898f1449ef015447145455023b7ea37d8813f97e9f70147": "f851808080a0f982cf0b997675729bb85639b6e152dd536d41b598620f6a786a810407283bef808080a0b70b4f6ff909f6d27f1e2321774f3a4cdc5996fc7d8c05da9cd898907b922a6d808080808080808080", + "0a0e0e4961268408114c1df2764e4a6b8ad84ac1e1a3afb87f1cb3e722080285": "f90211a072173a92bec14944f6bf87b65385f4d6d1af9345633207d8507fd51e8bfef81aa05b0a6b46eb3716ea6f4674a329ccf39673331aeb7cfe49cd2bb97d29e9b3ded0a04d2ff52efbdca6b59d9655ba87113a93f5cbdb57c3d33beb89dd5e984f756dc6a04e8982f41620a9b02889f7f0c396f4815feb4253a0fbbcdce8d36f0d6d7c2930a0bc54f4d7d6a46b9731a9ca3b2572b516b2cd373cc473b8a38cd836de02eddc68a0379136db1a846416894a8f87d3c1c8b20232bc7ce1ed120c3792275a0bfba31aa0efc9763cdeda240e018b17c8607563515bf273335854a4f6c19092d6c49bfdf3a0aa47e12e9b140c237524fba6cabeecfa1bb65783f611b2cc62a237b1d005c47ea0999473b628994ba7ed98b3ec000745f58eb838ea011f81c4fa62ee29f4a1f677a0bc6365d37e64eb1b4ef7df8a48949047a83fc4d6ede331d9a977b9c445039cd8a09e645f08f542dbc07ef46745d1d35c88f9d12327eb66b3457c5228e67ed9dc20a0285227bb890674880f49e5a288bfdbc7b6dd868d73f1d21dfafcee1119ac9064a05311b8f01659626cf832f995300b736c1bfc24a43c72d2922daa0fda935e48bea0e7ff567033c7679c4fb055641bb42ff39aafd2e9bef81dcf20d32a2808718060a08b0e0db1f0817781baeabffaaf46d3def228d6231c7af536f59e3eefa3e5c42ba086d2e287c53212ce83a062b5cc64174f1ded6d5bb721d80e12eda7c0f7387a9380", + "0b280dbc3c33d7b51f70240ab01371ca210ace47ea77009c1b484f50402826be": "f90211a06662e3cc8a6169d6fb3bfc0f649960ab09305e01f9b53594e095af282aa82370a00c9f7298d426c03bff50c90479d5595bafa45766c365d3f06406138293ddf091a07d152b2a669383b29ad72d143f7d43deee5ec1182dcd012e17cccde89e887cb7a0264eecc9c66651bbe5841d6eb38c8b8613beff5c09bca79153dafda26f4ac214a0c80274665a42e8ce5b6437d13c1a165361f417dca820990560843218d56487eba0de5a408032511bce0a62b9c21e3a9af5fa91716d3a698e91d640a656bd634a55a0688152bedf35d0b3fd49114e4ecc67e3db1bfbca3b7d6b446e78baa60f45ddc5a05d3f3e3a8298b4b82551b763751e60bd03d836d7b48f3314905f4abf4a7b7a08a0e4262ff9f84ebd6f4ebb136fe4bc50f9bfb88bf13321cef717fad3094c04e149a0df81b5b0e37d60598f2f6ec2e388e2744c3018c76c95a372d605d6bcd97a9b78a0f33b3762daedcbcd555b777e429077ffb39ded1905a8efb60322e5586d0c4116a0a4059b7e6b2b8e0364fa30cda7630c0845c7bc051a98d0de02a1774f96b328a1a039404f5b95869f245c32a47a131d9e68aff085f5e53e331b39c1f947f31257f6a0b9fbd2612880d62ed54062709c0bdc9d62e62a1922418ff48d9c9d3626255c7ba01574d33cfdfa7a09d5c8bfbad9fe8bbc9cf38caeabfbbf9820ea6c61cf10264da06bf27e421f815ff81a737dd7241377660bc80b37e9beb2d9f7b91cc1102be5cf80", + "0d3b2b3a3e48bc00281b776d0793faca63d878e86822eda6c6373e782574ca13": "f90211a0f7150eda9f75be8b10400df4341342d0a964a03f74ba2c385329732382ef036ca0e4fdee61c805172c10838be0d7170c3a6c84022b879e04bcadf7180c0150876fa04912ccda03dee09891c6b41c336aa352500763319963d6f4c4cb07980a009663a0d7c756b8747fd79d367e54e1b700b9db891a88a3c4bbdb870cc3c3ab620cc0aca0bf8acb84e3c23b9b8d68310c066eba50c1b4029113d6d9e26bd6a2d575335f3ca08011240b594b7189076cc49b81b890984679301b65e9db25c56ba3605cafc1eba01d7d56c6e1f34dfca0615c5551589bd17afbf472b5e1112fab98ba709fb7eec9a053907a38af836114fdbaf7ab535117e1789288a466456f7b75cb5e785518f554a003acfb8f28db4dcc0317d3f32f8bf5262181a05185a39893d3f3368d6c284f0ba05c4d9f86239411ebc1b662c958d4156162497b583041af5953139a2e4b8ea7f9a0bfcd7e1866e469e1802898c9c8db3a092125636819a9717dedaf7996262ad4a6a063eb99b8270f5a9e892b163a87b297b404b49aa44d8759395679c704b2795432a06fda998c25adfec2e28ed071dab107954ca73b7dd5d9e451161114b5858ed835a07edc6ffc3f76f9f3d8f854beeb93061be76cb3bc49ac6490b5ba8beb51068258a035bea319bb49911060233e908d29dbb16fd1ec11a50d016dae875b2a1958d61ca06db1f40b7faabb4608b7cd522cb4805102d275379f2f56e8b7fd1903130ee8bb80", + "0df072c2899efc8de1ed0d84eb8c75bde585e97bfd12b0a18f0a69e9cc8de387": "f90211a04af102b2fa3689d0481dacb746423b534615291bff4e45497a2ab27244566a7aa0179d5ce46387a0e88f9147c1140169e06ac8185d205b192a132472823ed565a3a0a63b19dffe7e8f2c82633a2c641754364412b99dab77f5ccfd5183a96fcc222ba0304e5ee52cbe7681a3db9ad72576b34d87dd799a56afe503fb757e02c4ff88e8a045c07ee4403109146f7cfe165959fd999ffa8a101e1026ee21f322ed45e25a08a004f9bff28367eddecf2f62f38d967d769b96f2bcd0c2ef82efb068f4e6419716a03420efedcaf086169764c3c68f9bdb25730890a6989fd0e4e7fdfe844acd2b11a0e938a958ed19321ab83ea051a872ef66ba4c981905235d623070d6b9ab56f7f6a0070f1bc7620d27f392c8a0ed5d2500a8219cb69a600ddbc974d95f15f3087de3a02640a2eaf6148db42325eeaee01c55fef997f87226aa2aad3757b8b436f9ea2da076cae627572e7cf419d0d5ae9fd1584e9b5e13bfd4789e150cb24a85bd0b206fa0d7233f721ea2bcbe0639e17350230f5d4f31966422c6a7fe570738d6a757cfd0a0394420a28f0416b1548ceb6ea758c4b7ab8416d90c1169a9416f188cefc7961ca0cdeb4734a4bbc5eaabcd9129b2ad3a90b9f94c130ba9872fe32e5553114a80b7a09cf7b5dc0055ca3d8409355c5af35c56e586607ad7c347710a05b455eef57269a0f655327263ba6c584bd18f4505e1839ded7c2ef3b83f5e3cc80baf8426875e8f80", + "0eaa4ab5738a4277f8eb227fa2c8af8aa97d633645c4bc261a3f71a52c2d720e": "f90211a06c6e183bdc04a389cd39b60ac631fc937aa4b6e83419c44171368b34e2c7caa7a0fd1f40b6c63a059ab8d9701cb79ad91e0f77126c63658fc0b03544dde711782da0c19d91c2a81180de78273b7461427b337647ff9b42e79a388433396f4fa150e1a09f03fee8a9bb2365586c3e6eaf96d5d800f7b5a02e965baa970abddf42ae6ef3a02a9042151594738cf4b61bbfe309a4d0a5913f3044d72daa8eee2085999d69aca039555373cf2b0bd698d1d92744487f415931d5f10152a8649abf764c4535b7c1a00a59d20ceb39b6ae74f17f21928147213c2295ec7bbabc895367e44271dfeea9a07cb32370e8810296471daf1d5a7e303bf47edb7cd5b9cfbf7664fc44e0a789fda05c5da18ca949a0ea72f80d3d1cd1648454d562c0a1058dd1b00a069dff79b255a0aff4b18b5843067936a27e1d93224e806f6c216ad4e72a8522c057d52c95773da05cf9daeeb01e6fcbe397dc63463707e1f7d5c68179d4e18889100e4cc0a4e6a5a0dd0cd2fc41294efeea51516f42a480395564eb6c7eac5b54037652085c6c5462a0986aa8213d7ca238843d2adce2b9a2e797a6bdf6d6c3d7ff427d1093f112caf6a0076bce7476116a47edffac116e2592d7669e5ca460891be8da01cb7e0962294ea0af7bf7deca73677bcd3c202b2b13da521a929ec4f2e635a9e6965fdf31623305a094e44dcd0e8c80687a0b4c015abcb16f09794ae623a859ae788603f51577d1d880", + "0f16d99b8149cdd636b00e3e5623f709399982841ab9210acbdddb06e1ac2524": "f90211a02a2885b1a72d4baa691fc8c883ab69fa74cddae6ebd2028b402cd8705fb2c2c0a014691f2f532d4f5e15ab96cceebd5e90420d80f1a16d46b32844887164ea2717a0eefe719ed10ef1b61cf38448ce1a42628bccb724a58d6e5f9867ddfcbc27b8f8a0f25cdef62a036ed6107b5b46bfa0a68d6d50287fb12d7a0ea3f8d4ef3d4452aca0f44c6be4e507a65023ff8ee38d86304290da4f0c823a1cc4f3f640777f27ed4fa0dc06bd5baacab1a97e964027b0cf1af2b5526dc75a6f285b0c24153df8852c10a03b7c87218cb4c3737638de3cabb9d995b14d99d5bbefd3d6ab41a6a638dac4bda08181fc1809c24f212472328c67043e9c2bc884baa4f1f417b37bf500fff41381a04df1e36111a6971c215da9a2ec47f6fdd971f1dac9103f7f357e84c3fcf9cb1da0b3d7dd85e82a49ff2d157e9b7c8d6b8d4f17b4720b69ec21abde970f4580f634a074385f59e3422260dbe06cca4d91cf979c5197876fae0afada27ef91af49b3d1a07d2a9191c1e94dbe8c26d55852405cefae7e1ad2fa64c79dd5106d507a56c315a0ed9b9980d4440a3f2def6b7628678ee2c10284ec2e771a6e01fdac893cb36108a0c89e8a859b2ff542dda37467103651268be0bc72415d5b861fb8abdebb750bdfa02d8ccb9cd2d05b6084ba4f1a88cc47d63d9d9fc0c3b0d9a80eb3a256523d1317a0733f4b94743dd80ed3a301c11d30928d8306a3960c86d7398ae3a09bfe7ea04c80", + "123b1a213154d80867e4c50eeb7898c0850b0722d487533744ab207df1336518": "f90211a04b6d7083f5a8a64360b197e7364516b37f2b4f6278f235143b961268d1372e6ca0d543807955cd07da46f740c561e8d128731deb1185f68c6739d6e5c3287b70c1a08db75e0e5ef9ea575fc8933b20e9ffbbb28f0e4d88c9f21a797a6ff3fa6820f5a0ebd5332ca24e5ca847eb2cd1cc0d661668632aa02bf11fc096b1debe0c727236a09c385129b140428377cc02d4334d52eab433141470888ac66883e44bd64c946ba0fde1e4ac21d7528f90aabebe45fc13bb7b2c0a17e492e8b734f971b02b814916a05ba067587b1f1c9ecff934dace76646ba8ebfcd0daa29faced0cb95279da10c9a0c085b4153a361d74b35b23116ad768ecf2bc9d4ae18bca680d6b9a72597e7983a035c92460e5ace6fd55a3c71aea5f7ad1770f30eaed01be6917d09213180e16d1a04b8f98f7d3608d29e7bad83389b1ded13df8e0cd496ab2afaec15a51b810d68ba01e7c6aff251a0bb09f278b73e6945e58fd0b3691a2d87233bf388b121451c5f4a0f424524e15bf7904d5b0ab04ece08073bbebb2fed66b58d6003d69b688ea9057a0b66d081c3006b961228ea1bd73f38c82d2b5467f8790ec1da1a2d2533fb58b9da06a9c283d04396af907812ffa7d28b4f06e332a2d23b4fb766c7b78669e0f1bb9a0ec8972f15beec00c03f1a83ba36f03c33e6b8952aaff8a81cbd08112c5f5ab92a0fb617882d02c69c87240a7bfc0b9edef6947702e866391241c057acc846ddf2180", + "135f236339b97faa1a721e7235b386ca95080dfba8b57f0cbb2dd58959819bf7": "f90211a0c9ef4bef7715b41226d59feb20be7b511c33dc60a9ff64ffdf93f0858edddfb1a0156fb97551b1cab868e730b9cc4f4a063e7f95869ac00eef789965a2c7a57e3aa074b7181a85d773c8f24663cda8388ac6df8f5f56cf9229dc97f7920ca39fbc18a0ac87e70fc7ef7fe6389288cebc1e790e25491bfea114e9db2312ee688debcca3a09bebc1d8760826b3bdeaf111cae1f5d3793bee1aea2b837b6433feb872f79d59a0764ce32d1a586bf7505d0815efaa9dc8b56b084e9c4499e3c5ce98a4081c4608a03979b14ae2085de9cbd50f62f4dee7e90a84eec8100fb7d47ce108cd82791451a0c0906a846ae684eec3864a80092f59acaf47e9e080d0fa37b2b0600422a51bd4a0123b1a213154d80867e4c50eeb7898c0850b0722d487533744ab207df1336518a09f0f9fd3c8d6caacaadc2c0947dae4f1f76f905da468265057b8a3dcd5d72918a09a03b15cfd03fd8eba10b1263bcd49e3320b40dc802163f22f26e535af275a83a04b35e582f15c2bd913cf035aac7d15090035b0482c8f251a9356f34ab1c9dccea08dd682f2190a96ad9e62c4459a96e275077a365300e8a94de3a1b9aa7fc1ab1ca09fbf100487cc3810607a8765e733294545ec457d91f203a7cdc2d2b4670abd1fa048376b10e7dd81d7e813cb6f4a8d36978eb47e7353a6f6197b9b7b4de6a0588da03e10b1fdafeb71e1dd31f7d8cab206066d4c40c44bd91f3fe76e2059bba1cfc880", + "146059d13f34ad5457f9b100536215da8245ba48d27b3fe4d0ec566fdae0a847": "f8f1a05b3d2f49cbb9d1c5912b4427fe5c9093494b1f51742491c68908435be7f64a7da019c39c7ba8cfef51fb505785f6e92a24eef7be18c2e46d37c8fde62008b65bdaa08f75e476a1a5b0249b049837ab5b8ed96c3bf290bac67761415e468be3e4f9be808080a09e9fac210b1ca4d0aa4f645ede53a4165d7498bfb82cfc45db6c1d8337b12ddea0a4014d67eec9f6b06b129b3fc9906f28f35e0b02acf26ae2f7213139382b7eb380a063163c92fc9dc42be61b7049a1fe49083a565d40015ea2f02986d9a0f2534c588080a01d6b660e07df224a887b604300a8274261d7a3417bf59221b774641ec0f4ac9280808080", + "147312cacdf36308c90d8b59776a3f1cf059cde76b85cf99382a0d14aa8f7683": "f90211a0154acb03abad55fb49b8af8080d8b7056675d2fa54abdd3c09d4361026c42f57a0395cfabfbbc40d80f5d48031792739cff4500fd7546e19edd62d67ff0febe9e3a0147340e5db1587ef993dff118de976ff2b9cadce9ef735e695b6a8ba9486d808a0e83c0b7171b4c0afe10305eacb581a7a1ef05968350e80ab2262d66eb68696e7a0c3db196c82de790c4b8918365b074c3b15eadad43c074a24de7ebe0c6042407ba0db2c6dadb93f8378b6cf684b2a642f3fe5b92e09194ff44b83efba07c9dde79ca0123e31ffde5f7f7f1968d8c7e405a415944ef3776046391c15f1e62cfbb71c07a0d5626cb68f579840457a7bc4607260af2798fe34a02f1b80871b7e240eb3eea7a06c3d79ba9c7e2d70de5b00a1b7711bb9980c5617e7714bf851402c6eb62ac91aa02b3bf1a5ba307a7fb6444a27f39affab16c5c5dc51a59a9fb18c4ec93bb51f36a001be0b16f74a0a35c2c9f1292ac63a0d5a86e505d4c7effb1f1f5012990bf9eea0fb58299ceeaec8beb5b56dc1f73dcda0f55108d4ef622e61bb451fc4d63c491fa0c73b0b1fb145a03ef39d59410880867f9136e7c539eadb36cfcbdfb03c5ec015a0b6e8f08aa9c831884af5e3076f7a5a782b601bab3f31227c4df83ae56cecd833a09e483c1e0f3f8794322189bec2cfb16a2f2183e11d7ab23177ea964918cfbb0ba0106dc313f14e4e9580162d9aac66ad9389a902a6f782efff0ddbc2fe0e51a93180", + "156fb97551b1cab868e730b9cc4f4a063e7f95869ac00eef789965a2c7a57e3a": "f90211a06078179307f48162e042e41a29e87df84e0be78971d2144755132a7ae182a726a0398d70e2a99fc8116154189b4b3e363b7c1ab89e82ac870f4ef18625a79fbb11a0a5b9ad3b312ff578213c07cf92825266e9ced5adb18671ace9fc2af4bada0efda01f6da886499b7bd2559bfb8051496b63a99338bccf99f071d4ab182785937f59a0654e618c69cadb39bbe41ef8e635dfb196fe8adc24cf7fbbad9629f7e71e4e3da0a49d6870b2be04193b49cbe9c16b7e897e18ba3e19b477932de8fde578c1fb6ba0ffe2f055cb3d69b3f6e91b5021c4d6156f618096258db4ec130fddffa90f3ee6a06e7be549158c8620ddd60ca2d888434a1cf0d295f87e261f5d5457b394c8873fa090adf05c69d9d161148daf8cc7cfba322e6d6b722f9003ac950efed0edcbd3e4a08afc93ffbe19bc48001013377c3f32d00cc6c25238f0c044474e294569d2412da0518876e0f325280ec3ba986c3c7880b115a9c207373a627320f39490c22ae7e7a035de7be5749ad715ce0b80379fcb18b79e77f2e180bb03d788dc5b4625974171a048b75528a6934e1b85bd9a59d61ffbafa2154ffc822fc2570be2bcc490bb762ca00333d99c64200facd1ee29a6a1b33ecc45d9d8677e31a97011b846ece8ee9fc6a018a19d48b26e8ff937563c7c14489058332983283395b9770d4ccc7213ccf3b9a0d05b2c08981f3e32224210a1be3a3de94f82e3018e108c3cd7bf667681555bff80", + "16542f514f2786aadf924c99e251da98e1195b6122774562a273318518a1ae1e": "f90211a01aec9b1bd1c98fe37c2ff03be7b21d70dcc31f3fd824ef4ef6aaba262a652eeca0ce8e246e7279f57beda7545bb3fe71372ea432afd2b33d0beb8268e74d611dffa0cef1d01a9be2c600c5bd236be48d39278d330e6ebcf47c98bc470c3968e63f4ca09599fdc64fdb1aa8dea4adc401341ca88aca2ac00e403f8e44cb911e9b5cca4da05496ddb6be25748be8dd8177fc99708f09e4a651a8a10286c9fc9208a0a5f090a04e472c98af20f0c220cd7bc96686a7bfa0a0ae0bab9e69ac09894901696471e3a0a15a461d184d3f48a58bcbb3172587ae8b6ed30e99bf5da0148ff8f460aa914aa0907cead42b202b1d6df89ce58354888822fb52cdfbc9802d42e81c576bece1fca041d8a628024ce92afc6aa36467ba7430dbb32093d119be810bfcc45839a09733a080e8c5102f36fd74098da575ef09ea6567462bfa4b1514eae892b54994ec5a92a0efd6326a3edb23474e81c2d10d1d03d56aa3a1155557549ff369e3f88a29c39ca0d54fb658fbf854b8f7b0c123950e540d6803711360cfb010568ec7cb43c3d89aa06a7fdf3279d1c8d6b53918be8464f4e193dd0919645b3a422f40b19403ed6aaba0de3dff98369f0c2c0a542863e33529548ff126c83017ca0bee197255257d18b7a0d7f3e60960e5f1fc37bdca70d8e3b929286c244a04de124a2c710bb5b2cda2bfa09f41de32fbd02415d60e4e1c2bcc8524ec3a89e26649007d5815409a1c33d29e80", + "187e9557c004906a7c06b0602ae8340d3ad98047e9a7c975d3bc84e420de9772": "f9013180a0378411201fd63f6180636ea48a2a45173fc2627fd052c6f765e09f70bd1a1bb280a0e661bae10ccbb4948baa1d304bd6bcd230fb0222cbfde542f85889c92cac7e7ca072cfd91698c5e95a281b8eb08801611a11519101f634fb4d61b9e3ae9137495a8080808080a01a04270e9ee2e77708ddc4e6e6c4b281f5110362137701e3546304486fa1a245a0178277ce5fabef84b9ee5b881010f6c57ca00a18a5fb762799c84063f9004a62a0274c7bf43bd5eca6e5a0dc6594c9fe5066fed8acd0ab0e3618ad55666944ab69a07ce1e92056d889762146126ef502e927e78de1c3ccf6343476ac668684688116a06c338317abde7c64583f16052264c9b4984c41ecea19714de2bb31a5772474c1a0a58261faf56f88850161307b7a4ccb756484ba1397f44869afdacddbbeb066d480", + "18a19d48b26e8ff937563c7c14489058332983283395b9770d4ccc7213ccf3b9": "f90211a06971528aa8ee3f884dd1ee574e8345901a6633cfa4054815079995c7f50b32c6a01e40f5bbec62062dbedbaeba874255636c646f687980a2bc9d08fa9ee96a3ea2a0c9304867f75ecd03ab15b818844e3285fc0a1362bc9fcb4e594a82cc3c4fb9b1a09272ee48bbf1a9f2873300fd63df59767e10c7eb3a293b3bda742b0feda40ab5a09ca3957587b2696f37c40c038cd29ed3b0b94614f0aff3305737339a1449360fa046d56fcdd2f0e778cb4c52e526fd0ce9d5fd65392346075e190ac62e637454c6a073e61baa8c9cfcff1187d8e8a41259449572d13f912df61f1dc2e690f68ec2a3a07f870fd46ae70f8fca136068a10eaa74ff756d067acbeb9c5174bf31804d5595a05482434eb96a04163bab2de812fa78935de3a67af29ffcf99dca3f05fcfb8058a0f47a1b510cd5312854913e742e8a01748561145bd4789e43ab2cbccb08edcaf1a074d00b1b9280dbc094e43082412cc3b3416fd2c3aa4954b0f5a23a9163930b0ba04052dd9100525820575fb7451b4b60d4fea985710e41c2b10b24c872fe8fb0c4a045db18d7acc6ff1148f5756732b10c2c8103fd57ea1f4ba3409eba113dfcf8b0a040deaef35bf7c019c611e4597b0fc737fb1b3d42594dff401556c8da4d14eff5a06377090dfd8841506b41218b867f548bfc4433c7b89f469562cbb5bfd487ab2fa0b33cb2f59382372a377710410a85c9da40bacd8d81afbb61dc1dbbc36c08fb5980", + "18fc2e2330a4d429e92bdc45106fd1c82e8df26a270dba2b4449dbe0fc6052be": "f90211a064a1d0c9c1327bb003c85459f4e6023335e44f3aa0501c817e71e6d7e7834c86a054cb9ae21ce893141807b1be540f9095590cb98572bceee4c8ec538bed21408ca04b7adcc792ee953c8acb92ea330fceb56d76d4448d0eae231416643a469144b3a0d9591543a76e60fb5afed0ef96b9f56063369471da62884494f6a47a88bf21caa07cec599952f12641e7537e2e25c874393701b133d7980be66f4da253705d2770a024e26ffb49a0c92a267bcebc29f341ac44fa1bc6601c062e70676427eb29a92da09b4cf04c357ebb339d241bee505c3b9130a6bd712a4b12aecd793fc94b4aabbca01dce8921c11032f283aea9990eb3e8ccc300c7f9a46b2a5c1ed0646ed548676ea03c72bde16c213546b1e222a538ffd17699ee2a327c2f7d02a5f6d1706a30e5c6a04cc070435a45691160eefc396802c040c8fccb0a39bae2a5a52c2e810bcb5c2ea069bab46548c16440ac803f5970e7f370f67eeceac5eb8d2f91f6c5272a0956d4a0895731b50872138f274c4ebdb38751ba0dc336e5b70a91724ce5f1ee39cae87ba06c529fcd302f358c4c72efabcf13ab6d6ab83f32f255882ce0e0953730cd7ebfa0705e6d2d9bec284c214c6349f4446b97a218347952c874d936fd9ca93df61137a09e193fadfe6a1cd22b27733098d7ad42507c1ddc6d7d59f41cb396edf4a084eaa0ac49865d5e9a871e6f8c4c3cf2636a1acb607f6c90fb7475ac4a9f2327f267bf80", + "1c9a9f46c4d688a8e102e19b57cd78910cd6fcbe7a7e9e5d310abe9bc3a7ffd2": "f90151a00711c908a764787083f5198dfff6c4a27d42307284e9f5c2964959a941878e5b8080a01ba0202579bf5f455fab03ee56aa132f7f1c758936325655f9ed70355fb9432aa0c6bff9d47c07bc008d9d8490a60a243945f0c4e38b1e5addcab9a0c511cd4dd2a0045fc6732666a230fdbe028df8d9b116e7c075e1e8c0e6d0bad47ac04e450cfda03a6d5369879a24b2c33f5aec9a66a578ac6c5b1cb0e3aef0c5a5d40eb010cb2d8080a0c46978c3b59f391fce8242d175ffffc0d8aaa2e414248804e613145302b2046c80a02d9595c3f2a61212b66f606c797f74dd6456503acb13fb4e683a79ab455841f0a001bf09c045435b3f633fd70797f05b4915165cd45b3399398e0e36dc21e3b189a0a0a47224a98b75e280781ae2edf12872149982c1ffdbcd4c0c0ec3d2a403db87a0aa52eb79be291249a909398223c2c7b1f2e88a4b7d86749a3489bd5ffaa30bfb8080", + "1d0396e06998d362ea361523d6926d0c5b1aa893b414a84d8ea6720152c1dc52": "f90171a038a4cbd66fa514f5746e368ab70c7842e56f10f5532909680c7e8442698dde6a80a07e69ab8a81f999a1aa4bd3a6d8cf2659476a25b3800eafc76b8e3ba61cd0adbfa0a980635d4e18318cfebefa5984c2718561c08ceca747d270731943b4e285666f80a0939653ad22cfa2baa9eb55e72f806868641da8d4cb3305533034a2476618bcd080a0ad53b0ff8311926d27e360fd5d75a5c641c9b7a99edadf1d7cd28a4fcf18a7f680a0bb3c5fb0646efbe389a2b8bbac6b96250819527082148c07b78e79bb7d1da32680a0fd0e970e9474c2cf723100bbb69b74ab707e3d8980c252ffb4ebce983f9b8374a0641bdb70db6c642abcecaec579c280e85cda5d6387f8bb12323545f6a3176a95a00ce141d08ccedca5e63dc9e1fb1ffdca2999923b599df4cf3c29dd8d6affbfaea05757f8e8ba0b783dfafffc5fcb593bac65c190b4a4ae47c68cfca36e45360e66a01e2c6562d7b1d8a43017de7052546975b9e993553e786e127140a25a6acbd54b80", + "1d6ae070e7ff94fd948b839a3fd67da45f162cb8208828a5d2310cf3f422175e": "f90151a075566dc17908443f88337ab8f327c95d210dd4c20b81a13c6e7564d802dedcfd8080a0850e5abfa00ed652aee2b3fe809652b05581fffd2220712de0e0d39e4e26cf92a07484581cb032520d60d612b5b42e2a1d54b53939a659aeec72e1501230a2106180a0859e866fb2db068df76d18c230645b895fc99ed8e6f0758479a45ee6a833eaa2a0e4cb8e13158f76ab97292976542df7cf15cf1535f8b3b9f2b6873c033b386c17a04fc5e76e1b6752d9d94c3a4925c4551ca64eec046da006180fcd027fbff19f6ba04cfad536a133c6f8024bb417ed92e19026b29243edf19cd6fbcf9d3afe58829da0aaf9780bdc0734fb8c578b8c3de4387590271fa903aa4b8deb5c87eaa2f1e491808080a0e026f27e9587168867962d743789bddce72efbb0ca4526ebff4125a5bab546d8a0e9ea7213d92f621c7e02c129676b9b3c4919ac21d8d96eac09b78f5246f4964e80", + "1da84049aa01531cb34e6752ea2793ac51824aec9831b0005a7f3f84796ba06f": "f90211a090c9ea7c47e710e6d10e2d344ddec799dc72f449325923d622fe48f49a623f11a0d5ed5b662b3c4ae850fdeac45d5cdd0e0a5c9aa2d225371330af034905c5ba01a060f4de379a6e43f9b56b42548d4898157d930d0ff7628e9cd205eed65553a232a088c4d863a6e64413090490b1eeda9afeb928e0e648e3f04298bfa08d740802b1a0e35e7c0d9fcfc30399e408713324b54b7a69bee0c7a239cfb74cb619d45a5bf3a0c0e22243a4c2dba3c3684f2815496ba18d2da39fe90d20197d29a0af7499e2eda00a3b34fde61bedb39ffbef25b63698bfed6f51b7530fa0f73dfacd22681baf67a0088c8cf58072d3f3ccecfb162df0845a14e89281d386fb05b68d09bdd0bf7ef4a0cc448077aeef7a6dccb244b1ea2f45bbcad8d9ce53dc60578325305198bb0f2da07f9cfa185f20a43dc98fd84ba389e73f6dfbb7093a0158b2564543d58d83266ba08d51d1a345c99e4aaa8d856ea802c6396b2527f42a2d75beab066e94b4ed5bc8a04179995564df67ae66a439f3c3162786d392897f945d92ac568a1284622e40d6a0cf8b5c2ddca4970914e91453811c679830cd5aa871d722c74ee285a84d9faab2a07af05217a1fa7357914cee12ef125fe72f92e2b061a1311c2c6c047f1b0cb7e3a0f0d410a57cc9181cc033ba8b01f54922d002a2cf19ac78b8afd9439f432f935fa0b1f98846d6f1835fb5e4907da07cb1052217bcee6c03096fee542caeb7cd3db080", + "1dc5adb8c3afd19c5c0491b441f538739af9e9a0bdf1c050109de3cfc70353f1": "f90211a08857c12eb96d832b92f51d7cf41cece5873e4c10b17af9f4fea0118ceaca8503a0801be3c048912cb78c9f1b8709c7a2a3116c4f6c61d318e2cb4aa8616498e77fa068bf93018254edaf5b86f0bed0ec1673282b5a8c89bf39ea4cbbf43ea636cd73a065ea0251360a0c9382c94b6b461dea9e6d34e2aada721d37f98c5f7246a6a9f7a0ee9824dc08adb4e34aa3f575c1fac8fbba3daa7d2740a8f5e9b50727815f5593a0588ea2e8ffda17c1e0d18d80a5db366c43a52f89341ba1fbbe20fd5b5010788ea01fe78101f834f80ee71a4e0481b677ace69a66bf383e0f34992416293ffafbb6a02466a0498b29820f32776b0fc297047c0a64ff0fdf6961f3037836889df4dc96a0c44854e615d6174e7e5197e04d26033d4e433173524df999935318fbe7102f64a0c2fbc05301f576de6f362ff4cbbbf21fa0176e009a2093a3601c32ae53525f33a0113dd52f072f8dff00960ec26bcca7146a4588e396d3cf15b079c947ebddaed6a03ebce803130ac496dccec9b324f74c9942c394ded403dc12befbf920da3d343ba0dbb82c705bd7293ffbb22269238b50029fbde4c38de44a75af7fe57cabdbcf3fa05995f00d61c70cd83f5f4d389272d8c0288feaff9506f28475a5632d5a03b7c5a0543c5adc6cb70f17cad1d4683bee1799714e67ccf8b534d44f5f1347ad2f3601a06e7fd310f5d11ff727acf4c27f69f995cb5ea66fdf8364df4ee4d45af3bd2b9480", + "1ea1be3a80091c7126e1913feec45ae1d13e01826d0bf9a6629851caa6783675": "f90211a08183567c6a0372d7938dc2510cb18dc4bfc57d66a1b6e64e3d59cd28c02e27c6a091c56e137f92b3e1cf99644cc03261c785c74990e1508557db5c98b7f499c70ba0c7fb6211990633f9e814208ddc7db15be38cffb9faa6ab10d45b3a40bacb35d0a03028002d4d56b538ffc748f1c2f15ce509974e8c0d1a54c94e88984b7d915f84a0cff963d252b49c7d72dcccbe7661bb15cd411b913f2ac47414c2bde6f0e2246ca00c8536eb53c7a987505f80b42f52252816e3f0864163d850e1097899ace97e0ca0f2c6eb28933174a95ba2f599409a24c6c2c27bd2fc00c4b57fae0aa7c2fcac4ba001fa86b27b61a80912331babc69f005428331e01d4678cee5337251c5c87d6b5a0da263dc977ae8a598ac4ebf1dcebce846333ced620d8964c35c7da306a74992da0cdc75fa9865fc40ebc29e2fe74c83f117b82b0d101934766dc142f17bbc6eb04a036e4b7caee623af058c7e528edf5c0119d436276ae3b4726084612bfcf17b442a0138914a786c7701e7683025092e559ed175769ceaf7d4e1a083efcc28602ee45a0f48dda2860ff2431edd1c839da7194caad08494e9c06fa1a1c80e7f633a3bb8ca01f6e2954bce48d59cc2849a3de63f9f2171aa94440d37a739804f66cf3484a3fa0b9770a6c407e470b1e6543f94410d649c8628aa3954350a8929fd57b76de4841a076403550fca7257f89007b4c22744d6b75e303ffe191696ef891d03510358f0980", + "1f20b9f30078dd0ac3c67b8269a6870a8db581d361125d86e3799ea7324dbac8": "f90211a098c50eaca21d6a8d3e923580bcb037c11e6c2b04bd5b83f37e4acc79b4e6af41a0229db3e7d78f404dea7e85c0a0937fd3ba876c8f3e13391725f6956ddd2de284a015285ff4679e4b5f42b01fdf4c2c0a7674674a4c97ee1783d4a54693fd9d31baa06c65b9df26d32f6fe5d883dc4788865554f6d7d84c33083186c25132ef0b83a3a04ad4b3b8efe21ae8258d839cbda1bd1e7250ca993fc2d49d271c2c8b4b7244cda0501f0cfab59d47f3c5b47b9e974db6bab22d96486f5df98873d54c60e93cd174a03e745a25b1f92ce88897f399eaf7ad3205b9460fcf0f9f9423bbeef20bb61d43a0ed458c90f00d63a294d9e3b445de61d9bd030241e5614a8a0b649330fa16d542a0d620ee98d1d3c370024a3660bb4a4f8d39ea98924ee0b0b4df1b076ed4f2ec80a0cd45e89ed1fbe13685cc55ef908ef787baf7b801b5634c42034e831457b8ea4da04d0a9043bca5a93cfd73ada3874e33fd821da3f1be052ec0a3e72f67db3edda5a072ff327f63741b881ff872de02d20ae4379efeff97d855a3a07e0fc822eb13eca07a1a2f5e230836402d99a484f708354ccd186e4e4b875ea36f2370cc556d40a9a043db4b1c4c5cbc015ca23cd50e0e1e9007d2a0a6d258fb6f6cdeec62a70b7cc5a0f30747068dd251739f20acf607419b843e5814608211e314c8c4d7bd13beebb5a0c60ba4673caa7b3017828364decb09e94fa533caa1989d0737dca3f980fbead880", + "1fa007ed8b910d71ebeb5c50615c0241e48ed5d4553e08b43bb6cdccebf485f8": "f8918080808080a0fd0c4c6c40e8ff7309433986aac58cdf2e0f68549e51fa966bb177b1b7203b3880a0653473b7bfba908adade3297d600310287f8d69e708af2d2267fa4e568d884e1808080a0a10f3738b44e01b21c8ca23c8420607060f2ad025ddeb7d38a6d95b61d99e956a059cd29e1439e6a15cb55ac34b423aed9ffe13c4a1d88303331650845742ce9ae80808080", + "213cda86f44dfdc6e0fcc7d1c587b740cca5ebe7f0fa1525f27b94a84418e27c": "f90211a0cc995795a246e706f1f256b174337c4ba11df6d475be2e1712f7dc659b079915a01801d58ce26d479332882f6e3d54a779046c61fa05af5702a88fba4cbe82e49da06baa9a28079f464342c536e25531833119033621137f18dba7cb07575c386bfea01a9f1527bf6da849ddfe27759f51629a4de94c575ef3a5edf3f1a221ad76a320a0cf1ab848ddd3061d418b76f9f5022b162f6874d220c88fe294bb692cb886a7bba0d528911adcdffa713b2a259abe017ada11e7786ecd75dd73154f2dbc9aeaeb26a09f653f43a8eb2db0236706898545a7f9ed4ab26fb32748d1ad433a4b637dd5a9a073bf2855aa97b0ad491a87ded8296ad48c7c34c60c385671a357e799ff3b99d9a0b37c0400876a655da2847964176785a48b03153e153bb79b757065c04aafe314a054c9f09eeadde8e65d336f1370126bd8bb0a649a12f87d369a38508beae43433a03d7f472b72c3a8e24650c22a86c28c10eaff37fd5ea5564f758000f681f77a20a059d47af9c489bb7e4e66e703986f385ffaf8d4a49b5ed81562d84bbfff7e88f2a04198ab2624286c72a822ff78a89f94d99e2e2f15c807b4e0c223204b16f38b78a0732f466af8d8ecb06c4ff9f2cc18d421067077875075b24b9d1bc72410cf8a51a00039c46201b305f181038a94d9deef6748c7eda16feb7fee6f2c51b5359d6ab8a07a70f4f5dbb9dec15e21977a86f50f483caf55bd378bce54e1df81a4e7c5ccc080", + "217ea47fd3f307ffb3a071bb720fe6aeca55c2ccae75876c165febc1a607f2ea": "f90211a0cb6dc37855fe135d9e2f706bf10d5db729e6b4338ec369a421f56db61275a3a7a0c33f20dbd4b806fb6f90d7b2f5de1ac637e36a2c7a7eff7cdfb210659bbe5656a0029992bf1bd117630e2a7b067d841f7262c1cdc59102cd729e8645a6eb4181b6a0d0c8622325af4ba3ccc5feacd32713069dd75142bf19323b9c9ee420ac42b03ca06b5e56d2bd98a82cbb98674007d87ebca5483985b28a36cc815ce343e1b7f56ca0d0137ec4864686c84854f685ea25b46606ebc4803a1a654291434b0e8a896142a037def1ba13a45b61fbdbc65be1914dd7d09ee5ec632857e98793cf68e4c556c3a0ab42b8a0a4ab70cd5edbf515b6f75b1558378e49bcb847de06edf9bf2d675722a0094d1001b16ae609a61889ab3a8f480a32ef52792a1005ceaaf9d52a6daa3496a0fba3f6d01efdfb81785c3afb8d3671ed8a2136e2a3f11678b481dc3dd280315ea07f5ebcecbac751b51d6f159a5594407e8b6132efb629f1b57c2cba239767d876a069d03a7ece4217e3cf1d65c6f7e311a613b4ba5acbf838656626e3b281ce639ea03f863826a20454aa5251c77c8c19803169ffc7ecf3631633ea365ee7ba94affba0b09b1fd44124730bdfa561ea1e593e141080ae8e05c30f44e3702936695322bda03f91e9200c55c06e68eb32e49cdb42813d58de886677a047ada39eb0c587796fa0de41b847101abd13384b2e0919950de153d6a94e28595b7e9f204a5014ed337080", + "21b94d6071040b17e281fd3063a7bdd1d96a213e0c61730d95ff55a7e05e8c58": "f90211a0e93f8e6220faa30e5579c6df966acbd4725fbed33bda95261a1d51c19882931ca06fef50b47968be99e2fb705290b0a5345eb006eddf37ba480106982dd96eb194a056321ff8c992990f363a2016e952e6a8b6206a4db8926dd0990e8175194093b5a0a122434bd144fe018e5eb00368ed86bafcd75408592961aaded2ccb80f3bea33a04fd7388c05c5049d41a010b8b193a991799777939526cf3a746c9f8b6e5ab1a2a009dd8fbf10ed2d9af2b75ffa816896a2d14ee90b622d54cf3598696314932c37a05fd77b0d01c57ea42ae7e7da29bf1a72fd0f396342f35f408f8b5db15ac28d98a0c07b640f45202ab33e0d2add56c1e05b708475acf75cef1ee3a3d5a545ddff16a0b4d114a968ac45ddd1ec3711ef18a4c6df039f2eda281265dadb2b504c0d98fda09057972fc016d291329ef38d0c5a1ee549c500a57c38f48dc52030b6fbfb2669a0ff89cd8e1c0f040fad5c0fa7bca821642c100c0fd0fa33f3462b6d7d329b0d24a08f49c749f6588a2a57f527d27d5eb6c0719276d2f857339d2f59d730bddd5bf8a0c0e0ea4b4924e8c21d6e5c0b2bb87225cf96fe8f8fe7d52bc2053993ce6d9297a0fdcaf033d7cac8b1f20b110816d6019b539dc83c0b3ccbff412c4a3476e1157aa0872c0395b96cda5cea44005467ff2e43a6fb00b67c3f4cc392ebef6c3b561133a0ef02e5d7fe1ddeca5038256d8d7dc3b2fd7855d2034d488abf0a6a2050882e6580", + "2228b1ef1c31f8fa8e4e292ab9132901ddbdb6c08430e86a760894620106f419": "f90211a0fb3482ac9338bf268bfbbbf8479cc55032f4d13b88ed8c48d1638f64af6f4d7ba044c863267b84399765b6615792a1f164d762f86d5cebce4ec8432ea660fc3c64a03fc007c4b6e035741ef32029ee2125e1ff5e5831e11d3779341292703478c9a3a0c879b27280ca0e72223a2a629693466fdd34b1006b96422d7908593c140f0da7a0bb175ed3e16847464092f1c8429a4fdcabb350e325de0db476d0b3db846c1e77a08a6c3007a3c638b56c8b6c06c26090e493da5001b145c94dded42268ec31f61ca0782c8dc7dec84878133498e7701a2363b86db9283b9a485a63812b815b8e83b7a0745f719a86874330d43f0c4857b58ea3c5121006ff4b2799555079d87fc672aaa0e7d1395aeb8e549381f46e12e4c8ec5538228e93d36641416fcbe0942bd98d60a0de82e9fcd39aa3110a25aed2ebd502d7057380019ea0ae15c050a12a961b5c09a0daacee95953c74bc1b73f08117287826c2b97041e680168cdaad18b21a903713a086b5f2d38fabacbb12e1da44d6600d96ff949095ad6ea742cdf8b5674a5eff53a028e5b4ce42b0c9d1126087742d6e1fa33b17efcbd2752c8dc8b2b78d45d0709aa0f9ed284e2a6922941ce77c4124b7b523ffaaa3c22647fc2b55d423870f527918a058c80eed9c5c134f6570ec4f5d96b452d1f84ab8c0566603030a5590d2faada9a0907d0344ed23d7c7c406820615cf6020b0c3b2e9ecc3836c2c8c8f31fac0900180", + "233299e13d87f02f2909deba397de4f97527c217d526d15e5ba17f3eb6781d4b": "f90211a08053853646153738bb495570227a839c769bd43e870f46880102d408e7d1886aa0883bbf53c0babc220e58fc9862c4bd7ebe436475f2a6cc56bcfbd5f722a855d2a0146059d13f34ad5457f9b100536215da8245ba48d27b3fe4d0ec566fdae0a847a039b90bf1fe55c3b3b1705d2cd2a18894288e07e883dabce1248cf4cf6fd68eb8a02e6a1bd7003d4dfccb53497cc8032498ea0a67d796f1b417c2a9acbdac8099afa063ee4d35efd018c9ca4b54b7b6b12fc57a757fa75b642efa66a3f7892faad0cba07c904a2d9e7b3ed0aefc0c4eddf2dd9d6b6e72541e9ecef702764ace265b9692a0ea47c0f1bbd50259cbf9ba41ce582b12ab6e54ca8a930d5499bb7269a6c59763a00f7ca9deb3b5f427e279980920a4743e40162a62442678309064eb7cab63ec6ca09d3b3f92c09578c30a5c0927e901497715a8172d38734c40150b4a2fffb61433a03c5203a6827d0b94cb1ba6141879c6f08d5acbaa65c7258ed26208af73e09606a0e30680f9158751a33f0fba1f6da47626587b94c83d9be3366b0706616004a8dca0babe072b70b7492ef5274a114b4291f5ebfabbb387306f525668d2a0408d725aa0135f8f113bf7615d234aa365e1a4e4bef71894037969b28bd43c12a18a27c686a01522f37072e9350294a756f6b4f7689dc5afe20fe019582923635edf3c285340a032bf9db1400a84f0d6b4a7392fff4daf4054fde1411e7a63b7275e8e719926db80", + "234b49e2fd87964dc7849cd79c50af5d0778db0b4349ec54f97f4ca60956cdcf": "f8518080808080a0cb6e86aafc535d7324bb97080f7b61bfe83f17cfdfad0fae3489b80282df0ba9a065cb648e191f0d2659faa082f80b6a284853a1ddd60914b975149021cbfed60980808080808080808080", + "261105c27f7b982277b88ab1b1ceae7136782ae16c16fb005d833cae16031327": "f90211a05c47a3ee1b80b54280278921d3781a18e1d03a0303e62d41eabbb233f50ac992a0397b3ae09e7b5eff7312040fd75e2970be26b0b9efb676d6f2dd5057e2b8548ea0b2d9c6566cb35f54d81464f1be04e36d3fb00bb2bcf75b880fff26a196e8dce4a086835fee3825ec6d92fe7bed98fee500826eca6462a90d2135dbc0f259a1fe6fa0912588951bb7994002dc8bde834276eb726fc7d9c39e272413849186c19ca2bba0c0b7e78a4de56ccecdda99eb8a5ddb8c9d4fd5921bf6ba06aef279525d8d8ca2a019b064b0f6eca33614512cd8ef583df7f4a910221442092de058f9d97196d36fa08629634fcbcbbbb449f016cbe8bae26bdee9375e1f11780a7392b34ff9f73ec5a091c35a362311f09ec305def4ed64bbf9bc658f35c74bca10e548f0b336964084a0dca26f9e4f55d2c39b6c1c8b7b4d7b25668d3a176b77f350c9edec74e66d41bda0d706322a3d0cc1d9ed30c519aca353ee54e97744c2d8b19df188cc9efd89efa0a0358a63589a07ab1958aaef5b9520b4ae2dbcf649b1a7aa3c4990f8413ecb4d97a05f23c86ed17e642dbfe39ab7828d5d1a8fdc7b077d31cbd8669ae8f07bf6fc8da08b07b85be8db7d5c69195ca2f65e6ffb9a203dac4e864e98e53cdd2d2690aeb0a0a69b13b4100461a1d5edf8c571f18b4c734a0fca87ff69dd74e43fbcc2f52c05a07d259aaddb74f1775c278b2a7c032bf3d5de6773293ae6680ad8da16c906d7ee80", + "27d01748601b67f84204741ab93ff1927c513f58bff22bc4e1e1d22700bce5ab": "f90211a02fe02828db6e648173e317d1ace39deadd38eac809498621acd64492405eee02a0773a0218701040a5612c297b8b86163d50c76d5aee1b31e924192cf236459b79a0d11cb2a28b5aa32ef5ac34b890f9007e38f9225bf138fb34c543435929270995a09073372e7902de47b6ebd2a292e8d9953c8f0819c2aebd5010d32d2fd337441ca00e91639b7c89021258eae08b2725674e68d2d365fd950770aff94c3d5c393a0aa0138e0b71b7442f23de2f92f2ebdcb67a837b3bc2789a2f0f0f5b7761342f46dfa088da855d798f614e1baeda090ec2037c2be5b5a5c1d8207c6ea6bebc3d4c69c7a0f78d739e65674ddbb52b181e4fc62dd9f1adc3bea3938db501589b3982ccf6f1a0697b45a5bd90e88d261738d596f6356129d8cc2a67244e360b25f55b7caa9a8da087aee177ce76f33974d5028589ec418f628287b45b8747a0dbf0552fd72bea57a0b3668f78fcf3c1630ef6f2d1629e794deb00c60c7c8352273c18e74cae268c7aa06f7b7c4e2e98fc2ea4a500c9bfd4b07e82cac262568162c007c18e3efffc6cf6a0125627d02c395759fb0b36ff8af1cbf78ff4034466a15c699b39df9ed271cef1a0703f48055c07bc02e5b8c45ff90f592e8192e766909eb3538acb1c22655e2b4ca07cf3ebb76221d4d96a08bc63b0cb2bbdae4b455c7ab18d7ebd3ddd9988259baca027eefac794971eed60ccfc2ab083ea5ecc976159992dcb7f41e34eca00642fcc80", + "2951268a9660414df24770534c3684e7a30aeafd3ce267d112859abc25e5a20b": "f90211a0ba32d656c4618673b416a6f3cbe398bad96c0d77a76b7a78a10566de2f641f10a05ce57288cc0cc9a492cb3b6d63c52e63b8218eebc401c8b45115e59a37ef4c54a000caf97a1be60651bd062f769a3bc8557af3b2fac6dbf266df1129cdea806970a036f35d605dcda682737dac011f7780f5ef39e1a1a8dda974ba5dcd02a97b72f8a0250cb77cf77af5e0f362315e5941dc3fa297f2668b7a81bbe5a9d58ca82a75c1a031044f56e6ce77effb1990472bda709e50f1bc75e3dfb58474e891209498d7f0a097ee492d79fe162c6a21e23d61042e38989363f993cecb5704546a0710544a5ca0a8c13ff6ac16db5d06e9f4b2d660f58352de92fc2eb2af81bec36e1b259a865da04f4aaf593d2f20a795b91ed3f2ce4ebf66959b1837cbce7eba6d7c2fcda2e080a06ad2643781882649e073347c18f740bee90a1eee33255d40360a1107acbbf386a02512dc913fffbbfc88e003e91d3bc22bc0f12de5173ef003675e4aa1166d90e1a081977396ffa2c485325608396b999c28059a6cb6597f04d6ebbe183683d1b705a035ecf21922d6d764f509dfc64e23d96d3051ff3ebbfbb4cee23b21725757476ca0b9b40d4e9a66c638baaa738faab4fdaa648111b02e336bb4201c5a3e2f8b4004a055da0cce604f960385aecb50ee7dcb8a379a1c8f0b8afdf507188e91523fe94aa01b4f47cc6078373dca5cf27992c32ad0107dac718dc125b7398a7f32f903256f80", + "2a62f90dbc8a93a11d923328df94528856ee8546cc3da3e1b9ac004cd92c2e4a": "f9019180a0d2612ac9819702ce18497c2962ed0593920fc1a273518e6631d2372d6d3860a2a04f549a013e44e1dc74e5adf74edea023750c0a3fd986b0d3ca9bf7090856c4efa0543d176dd3a6270f0cf55b58e5a286085b678a1e1dec441e31f00fee7142139fa08c9cd1cae3a5d6ff5dd1e09c81038aa3a9094977ebff39dcf1ea21e53c607720a0a1562bbcdebe339f609d2d80741b04701b0750d37ad4927526146c6caef985e3a06aa269f1cd128d1b626589e57cabdf97b961aac2aa245e914ea937fa571d024a8080a0d6e376cf453942691a4fb1fdd8c2fd3da1c350ad96c6a50588bb941cb278487ea0ea2e3258ef3435ea0834fcfdca5b64806b062643d36ce6721d17256cb7aa7b9ca075fd9726e59b59c7216ace5f3a95dc767590851a7384721a1df8d679683eedcba01b1607eeacc9e9e2cf0edb9d965833d6ba10261f86ef11d195d64fe0b4f76e10a0dcb0fa0c04287c30b6ae3a64d6bfc1caaffd2b251a219ef07a56eaf885e13eeca0b3132c700606e301d2c8f11cd7d0297eed438b86bbffc07e620d2e73922317648080", + "2bdc3168e57b967072a0020f24a4c3d60f232e04e62dfd0030618513e041cb6f": "f89180a088bf07ebd4298108d401f77a8b8cf15fed9cfbfcbb128eb908d7316d11fdac1180a0190834d0a48f98666fb282bcebcc5ccf4f9ebed6ecba787a807b7bb5293876f98080808080808080a07325fca424ad02cb239fdef999b4c7e7038ea5120ca2651b70513b48e97d9dba8080a0935097dc1f0c5338f335eaa356755bbbe2147be65fe94276fcecf027b94209f880", + "2c6219de2d21721a69a4e1f7e72442a2071668aa6a99c9c66ac6e8ca2ec34b8e": "f90211a0503f739339eb75cc38754d328c6058d4c07defd7be292c2d8a6e74efca3af29da0c14eacfe8952d2c1a31e8210c8089b61c2b9a6905cb1726801782824278e39c1a0971b5a62eaad43e77bca02ea9b1f30de3b5bbedff418cc0c1e15438c7265829ba0b13cdb9c08e7097e11eed7b782d544767b29ea55873ec57a4c6f78814bbddc1ba0d3c91231cc26d0777387793ffbe3b8e0f051aa37c3589fa230ca37a8ffb8a52aa03e065d058e6c7385ce0a585c4ffb1eda68b75a8b11f67613f6edb5b8b94d56e6a0d078592c2bd02256538818527f9c9e5abe68b29c4b90ef42f173dffaa6052048a0081be2cde020b254b98c7c426e24134f35beed839179a2311ee8cdfceab701b0a081c9617d676d614a989b3ba6ce7e12ca5a4e41e9ffec9e9e8cb0bdbca7519e13a00c7e3897e12a0a0b3d5c171a9e563fcdda9976a6053b0b57ae60ad862a8f6509a0cc8c6110ff1b98620f58bab267c3c5b4db7fbb208f867c215646292cd046d8cda0838943e8a90b3ea1c64fffc0e3561d16c5915ed0c9d17a1808ea2a2d292a3b38a0a1627ea13127b4baeb6754c4b42db2b5c86a76ca1442416ef33de9621b16b0bfa0e9df89274442b4ae66662c9f0566ed0076d1ba38bfd36b96a96f54f03f39a20ca007dc025978cb7886e3d071b463184b57fc30568c24f8d4ebd1fd5f9c788293faa0bb698990e9203eaaa73b384d816489e25dc5a4af045eeb2fe6a11fff3741525b80", + "2d512c7518b2a42e45c998930db9e4ca1ad1ff4d054a056653caec7f589bec6e": "f8f1808080808080a0213b2351ec61b79833f4f284257d4f771da6d057cf4a867129624740a71042d8a0847537a8616a61a259719941ed4ee55bed5ee8a7314e39232f2e2c49c33a5c97a00ca08d2a13504d7dd33bd0aad2ea3baddd2820b5ab584055a237bb0cb1c42c9da08c2c3d1ddf21dbb361b40ad3d5f70b8ad1cb7539af77848aec76caa0c6b937dd80a0a76fe52be499ec406691fe60812412eb39ec23a2dd524dc66a48370b1978f550a03a62e4a95293c0b31b49b9005d4c480e8ba467ad5591c0e27af4c980e1daed5a8080a0a036c67874f5ed4be294a3fa0291a2f78357c915147b9ebf2101428a1ae951fd80", + "2ddf54bc06f3e1618b6961043571ca20879253eab6889c1c76885138ee34b458": "f90211a0300a0d8bcf45aa9e7633b1c946d91108b1e552b2d8f45eb5e7816947e0bb9216a0b453d72598f344cf288be6ab46a5ae169dc9da055ebfc5c03346f92ac067c6b4a061690c6da747e945b247ece6698cb0cac5ee00a525b78c0238b13a27841b4181a040382f49dae46d55db3998c554ea514aaf253e94f09136d492c95484be353d06a0aeeedcfe013b07050f791017808a7f02082a40c0c37501fc369500284cc0778ca02c1b60e904a7dbaff71821bcdba0ad2cdf3d17c910d8c547033fb624c2078edea0a02a040514fe7c97112bad6205cdb617c9fd5580edf08dfa09aef46393c31eeda0ff58a543a459d90a73c6153c1536eb0b880d239f8e2ff4a49a375a8ab3cda4a9a03ead5eee639887bf174268a4706d881d574768c4cae621a14599844180d91a43a00e134d184fe742d19762f263c846d4df40725f8ab04b3595f0433e3507501b3ba08e8e895a397cb8a24f91b1a02a7a10973ff703087e0d5884eda645db5d5d2874a0c24cbe4dd005673f9e5dd6823782294d91d4d568f93eb83670cc086cf552fcb5a024116e5048f7cd7016a762da832a1efc842c7a25c2c912b4a892ebb13f5a5b13a0261105c27f7b982277b88ab1b1ceae7136782ae16c16fb005d833cae16031327a01b11a7ab7b4a638910cdb700776f900324dda6210678dac5440b12d7d9545dada0e539432fd78a7164c7de1d2426f8113e2a3ca2b59925db026ca2a5e2d14a348580", + "2e73916747bd1ea38d34d5e4a7533c5aeb1c0f80b2e070baf23d9ca9996dfb17": "f90211a0f739d159073e2e35eba3db0c5ccfd367b545a8d9de89745a4f341c655041dae6a06407d2c3850b3de7fb5e594facfaef37d554bbfc61d2e0f1cc95d4e74f8afba1a0b868f2cab98504def0e3754ae4cdb39871e63c7f487a4112e75580bcb3a1a978a0e14d8bb5b51656a11d9b10a253494c36e4150873f4a244b85d5dbd8bce06d16fa0acd4dd99d96729011fecbd6161851ae15b8e2ff619449ceb7ccac82bb6fbd0a2a02b3b33c740e177bd9a34d32ab652230d41589bfe62d621a76fa1926747506d42a0ccdc99b093b13044563fdbac2ac048a5f5a614e58a37a243845a22d80006ef86a0d51298b81d60c0b73858e760474c17aec296f549b123975fcbb1278914ac8ee0a0d69ef37cac2623b69f72dc9d8582c2a6c8e511e6691f125d0aa3687146308d8ba0bbc21923a14bd7efb5ec41719dd9abe37339ebe7a0732bce58251b2f777910a5a00eb725b9f6866b8a1a940bdaf733a01e2b5b883bd662e4fa512f86e6e63d61aca04f98d9d7a83447140408d5371e82cb47fca3fb62bd648a85ee018c18a94209efa065c57ee5e64bc6f5e62d5d7d112ad94aaace59ff178b8f57597ce24fddc92724a051758e48291337c415ff7d0e983dcc4fc0ad049a427637282ff90e7eadc0772ea0bf429b0e14584939e8b6c40b3bb0967b899e5435d5bc3239eebf889a92644d95a0215d78df150a0dfffd95469da19e7420a3db0ec1148df73d29547f49acc05b8980", + "2ea8f2898220d76cc68b3378120c7bd1a8081fe6dcc4258a63c2fcc053814539": "f8f1a0ab3001b16f035e257446b2a6c5911ff9edfeae3c54e8e604d0066cb4de86336e80a0f7a2c2c0c5103d01962d4cd00648908d1052f943252db512b6870deb9502bd1da0e901bae6a956117f97b5d4da6e1146a40b1502488bc67f8e4397155ee6c43dff8080808080a004b9c6ef89abf6ec52d93417458ff6f1a99c129022c5df159326804366d8da4c8080a0ecaad37fe1476a617644caea9c6cb59226c7c4b860f5a7a212be99c1f82c3271a0b7b1e932a472a251d118f0e60ac1ab39b32d17cb5d9174b404cdcae96ebee97580a0ba455d68425ec8c34b96bc2267142424da9b2d184e150c117c871b381468d26a80", + "2f076749258f1190b54bdbf383d447c0161c1f5c859d10973e204fdf7827fd48": "f8419e37c02a42821e711d8b306dc8828b969dca8c2110eb133a7a9e2daef2be27a1a0f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b5", + "2f5321575aeeb91f8da931b9b252ae053fc510fb0e18a28292d0c8562cad64ac": "f8d1a0df0ea67c100337d4f6bbbd5d66b834572cd306112ba367a202de85ee79f184f6a05429a0e3dae5c4b60d00f7b4f387a501a55e9d2aecc29a0febb92795a5795da1808080a02bc8ecf21b3d69ed1f980a52029077edcf69ead2f5939930f10baee99575a9328080a06a9714986e00640158a455c0d49305d24575160e1da41a9410feeb6b8fae19ae8080a02e9af3bc2a598a02ab1de318254f6edd72f7a1ee1809bf5cfe23f60b56ed91d280a0609e67089d5ae50069fd15f7fdf11b4fc1b5e9dd6d3068f1dd85e3ff0c8ccc93808080", + "3047f6408e5055f987993312a846bbd736edb6df01e841a8779977e29aa6eb5e": "f8b1a04c7446da0c1786c9731019144cc027b7ca01abe57df2573f8d6637ef853e999d808080a0728f1e5bbb8da379fa17e1827fa6d442d26a68836b003fd367a7a87ebb7b7f41a05f9039fa6cd9fb5dcb5a8b04e865f05f073cac3a7a266c9de0a0b4cd4e80f8668080a0ad6bd5842bbab9ebd916b6cf0c41ac648658622185495a4630020230437c7e678080a03517b6a725051c4db0d4fc84b7134c11e79861c79a0ec2191d09d63a32ee0f078080808080", + "30918625375c49f396b96291f10f4c29b285e2923cfcc6ff963ecb85a7757857": "f90211a0f596d6ecb39f5d5184bfd628fe957b4aa9e8c43b26740c26ac2afe7ec82cb42aa02c91aaa98821541eaba63ab99e169009113b1330689d5abb642abe88bb4cf378a018e24b9f9fb6a925cd6b4ec457d2ec350e66341187e038af63af5ffd8f96d05da02c7076e5b20388ded2be36b4aa64ddff31aa51175ccced011af6ef66eeacd694a0df69994d6479c94f6550520e19c36c5661e64ebbda9d2ca3bd13398800608f29a008b3a3a6b31a6fa98c1e2241bf6d8e53accaceec2958d793d94ff54b0e053486a021b94d6071040b17e281fd3063a7bdd1d96a213e0c61730d95ff55a7e05e8c58a0246c1c22b4fdb4417a3be2193ac13a8b1885567b500508f07c72d3e1b4385f2aa0cea46ffb2ffe24e25b6436074dacaf352f8c9bd5565b70f30ed4809fdd2c61caa08f6a06f7f5ddd58c9cd975451fa026150572a39bee56be03351fe40e45ee834fa080b9da78110c619f4809ec492a50f6e03e8c13d4f3e423f619defc30ccfabc78a0f1538ce31593c83ebbb2a6dfd899b3967a70106dde58ff5633e20f19d21b412aa009470284bfdb3d153bc8e034c7b65ff59e290ab66b063dc043baacc47b3cec85a0c7c2000e2a6aa6343174bbae74555c317c21699cf7f5909903daa1d34b679fb5a0c891f491974096e1a3ce570c97bbe0d5892051c7260c391290c7503b34ed6152a04c1cf77bad3601215f5f743a6c591c893d7ee024a24d8af374628f77c7c6214f80", + "30cba20b2fa16674b4063e9958a82ab444f4f1b342df1b0aad139916a7224959": "f90211a0fb9e088f053945585bbce5fbe3371c8f7b11a3856602529b48c23eefbc42fbffa0c4029accd8f241e82085a959855e1496b2f2a271de6d90717e3449384c0adddda001db903ddfa39ef9ad09a4444370456749b5de95a1eb95cd713e95d192b14d90a0f897acb77d09199525df3c290953070abd2ae2fb009d64b1cfd60470b5943dbba04053440df42f6cce334c0abc6ab849bf419166d70d691ad2384f5b90ed1afba2a0921219934ce54b3d31d7e4a680a4f62205a92813829d522334d6036e1272de6aa0584f9bea748cdab124667621a63ab8275492fc572b5b35e1568e4b8410a3d474a0f68239c46315b5a2d49632d5deffb70f3aa5eda8d183a379a48d8866e52fa07ba003897ca3745f8e211b533d635bc00efa7524926dc97d1b50e5b19ddd128d77a2a05b5ada8f0cf2732d469afaa16acdd43eebf40ce98cceb344dddea1a96d80e8a3a07f94c3c987bdd6f0b04cb667aa51260ce305c094122a89201206c267aded198ba0b8d9a1e83f92f710416b357e1b062593ea1eaf3333dd5be6daecfee7db4ce2ffa0ab6e64d12ac795dbba1ad190463fe3281ebcc4fd80bb9c4b68ba7e560b7cbf19a04cf09ff8214307c576d4ab9e7adaa3e40553b5e992046783d628641c161fbae4a08de762be3d5f028416286413a8455a9bc597d5f0bc67b991376e78ff055dfa7ea0b7e16dffe60d55c19fa2920f0c3e6b256e1e45c0583fefe444e9aa04708ad2ee80", + "319a9dcc15e8a4e0a2a166c2a81f37693b6dade76926211e2c3f96967ac44a52": "f8b1a0555fab40f4f59fd03776c57d5e1989ec3ac38414bbe613157cf85cc8a64e8f1e8080a0b784786f056513f59bb0cde10fe5cf9ea6c167c39b52f84f0dfdf6588a62643480808080a0e9109cc1ba1b7a274f88b8852ea137d3b2370b8f34b9e42e47b8dfdbd3fdb36980a08638aab8b707c00eae5cd8dff350db1ba28ab5c1bfa30a350acd796115f1cd38a00ed45ae7bea7efb495a5c065beee107c3d8799fe65113af4c3621259eebf2bcd8080808080", + "32a8aa4eae262d2b552cadc763c68c8428ccdfcd23faa756b9818678c1bb7d56": "f90211a0f71305d6c27f3126aa03aed08cf4ad76173cd9339945642682df5944686b3f55a075723aa1022feae053164eff03de339c85ef12779f6f88a413a8f7fae72d7692a034bd945ce4c7f55cb71521f0c36c9d6ce38caf4cd9885de75a01021ac953c59da06721087cc363b10611cf6f8c64975bec1115bde643953bcf75b7e0d958ddf58aa0f2dfcf7c3672e8d1622f4ef514e6a6636f5267eb752c002a8ea57adc3ba541b6a0f7b103c5911e937e8cac881a33a093fb3b928ca24b7fcac34d5fc5cb188ad44ea01628f2693f8bd385d2e7f882bb9c437e92b6e987cb4fbf874ba3ceeb88c476d7a0dff35da212733cbed590a3e3bb8eaa45ace4448d6dc426da882cb3b058bcd639a07b8e94917e90e53e6ccb0fd78931e333133e0d32e66426c0c00845420e6f2cc9a085fafd665b06ceebcdb92583510b1b1e39df6154e9049c651c06224ff1442ea9a09e2a49a6cbf5a55954431571075f4e8f083e8f486336aea8dcc083d1b5ee312ca046887c532b3ac41b943e8b801f30daedb483a60cb5e082b7c44080e52face440a0ea60c0a9cf4ec07c61b4ad4534afed1fba9dabc00fed6ab98054135690f6d1c2a0352e3443b7356cb7ee2a498d5346d82c8fd99ba377e9655550564e7938c6504ca06dd2b64671177a602f3cbef7918b6b886fe011a5572a76cb66884eb2d3d433f2a0a439c67a3142a0724297b80a32c7ef07652c241573f15bdc9538211b7b17a91980", + "33386b2b812bd72a1580bfbad0f8ea0bdac53f36bf3b8905765056b8bb314120": "f90211a07d90b7438b96d0c7ee74a598b3cbe8c1f8e3f85dd3f05f18a8429a47c42d4cfca04c9552016acb3f4581fe8dbbc41ed1e2db68199796ee9e9b535e10f040bd12cba05646494d189e356fe5a4d23ae78e6c609315a5ee61f3df14aeab483ee025d919a07b81c1b66a1bc640fbf1f996e3073fbd69429f763ed694d8eb27139a4792c0c5a0439da4eae561f7b1385e48a57a34e6f3e746cbfb7407935317b1397162332bd4a0954b71eae9a9e74570d6db015261970c2f4f23b42f42189b0c307f042f754181a0e35c99751d1018b57bfba6f984c9aa4601f2ec3d6f5aeace09a6e8cf99c09867a0e1ee6a2975ff27a743859b08860d78cfc3650511c2f7e4b5e12599d44d3e02f0a0d25b79681b6b992c086b20fb9d7762971ded3faabcf3a9d2f4f0bd067e4a8894a062a1ced4e940393055e511afafa67368f9157166f1c319d26ca13f8c5a4052f2a0ad1dee3f2979282ee02f570220033e79596bce509b1ce2dd1ed8e743204a62f2a0dabfb2b30a2d0ff115da803d93252db2170e07b02b71c0cf1d8bf3769d7d9080a00bc00a244051b82b67db48604477a94cadcec72a00b639531f7fbc37fd0fb61aa0c49508ad9ca4ff6fd223123ed4e3d6cfe7df4cabdcda9dab38e022547a959cf2a0340188cb3dcb9161c58d538b58eb999dc408c52d1e2130c3ad885cb8e3bb6539a0551039bcbc3bda42a2eeabad1241ab44c37ace63681150d15402bb66864fea5380", + "33df31e890c7f10da97a88b2bc5a56292e0ea8def1f7ac1383842b1a0132bd95": "f90211a0b687d008aa94aad56bddb8133d19a3d96fa7faf729f4b25549fea246cb645298a05c2d7e41422560c2bb79efe524d847d5117f6b4e70ee950df9ae23818c0fd2aaa09d70cc0994f77094e2658c03605f24633a7e5e6f0dbd8a51b95a61a4ddd80320a050f05b7eb7d85dd555f7c051ea679ceddd061ca826bcdc11000ea77b6bfd9076a083873a46a133163525fa752cb8069f1663c27ee96015345acaebb6cc51e8909fa0193397466d079761d45bf2e15198bbba32e1839333ed17d91e29853711fd2a5aa091dca3fcf9236d4efb0122f68af15ba2805c5dc59c4575a64a85024b03178a92a0f33530d450f5de1250ee98690733c01f23c79d693aa38cea35804252d754fe20a0e0c0ac0df12e4d23287571a283dc6b66330eab82e82eba53075c3f822cdc2171a07719ada8b27bbd07c1ad9d582db0dbe9a01efe35e61ff0da4bb0b70cd230f869a02e136bd74d45e2df3f708791ae11e36cb3e015b0795ca41cf7098588a9cb907da019ad0ca1178d7eed371d4861d0c7421fc26fe7a4793f0911a433c3976ce545b3a0ec6633b74b67cc70282bec89727f7f249bcf44822e97cb4737310cf33b49d53ba040687f5d005dbdaeb328d8962131dda7c4711d8b830f2cc3ccab325a2b3d4d5fa0674bfa651b1b6df5b6a6c6c011204c1fa16d412500280bb2bd037287113bb80ca0341968235ae4038e959adc9f6eaf55cd676be8653394d89f16e0678be7546d3680", + "340188cb3dcb9161c58d538b58eb999dc408c52d1e2130c3ad885cb8e3bb6539": "f8d18080a0dc330ffb9c65e8cb532f6b0e777464d3210524e23abf5c586558ef78ad0079c08080a0782e0c173fa8923c0e86018d8e6b040b09d6df4eb69ee56e6a831b4dc3b12a7c8080a05c5180e84990050428fc2be9afd2f9d466a8136818d94592b78a79e5cc9e1926a08a40a0100fc07099604a67598e7a41f57f929ac30687d755bdf60e5e84d73be680808080a010d2621d98e0212b5a8db447815fe1dffaf2db02a4714a93e7301b9448a43b65a011c2907f40e830d84bbb7bf2ba92e009f0f1e4da1ffa600bc579521b1f4d2dde80", + "34fb87e29438a1fffa11b93547e8d04758bf5efb223a2018f23d7e82f89f2a40": "f8419e32280ee3ab6e374a0164cebe54d393bdbd757c3ffce8cdd83d083463db63a1a0defec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de", + "351f49b334aca2a1a88f1774e8f5f3d4d5aef063b3ec1d8f77e26fffe13884d7": "f90211a0a93e46eaff96478be1366fcec8654ed6881b371c4d6106f6a1790f0289277883a0d28c18e13afe286fe2b20c319c6baeffff9d6c267f19a3a654ba82313ee368c3a0603fe0e9f289621544fd55399f428213d07b8cbc4191a4951f16491552f21016a08be30478f9e59fcffa9c334ee93a9852db5eff2128d5bfffaf64e42e12d17897a0bbfeb2e5d36fb0d2d331978a9ffb35dd920fc619b8b1b1dacef60ce79740d66ea041323e470a55090faba3a8761ee4675c269ac679c3c71cf6c25b02a03a364ce0a0af1d465d8955018ca31782855c712b104b98ffe8d26a47ab287124640d779ab8a03e8f56df3ce63d28b93322f5f2c7f6b603af354cb0ecca36e4c0b8fb944f84b3a0f636ebe99fe3b858dfc727f4be9ad6f600fda1eacf911deac7c50c977b1391bba070396790765fa3c15e2f15083b650afab483714a76180b5d5d0898e1c7f1b5aaa0022d25eae28ccdc302279c5efe7e55340b2acf2a181051b9b0917cdf16cff2aca0dbc030165c1e3d612019ac3f7d0d8e03eae4abb1661ebee9da445b7543520110a02ffc080051abdecedb340150b070f29dbb4125b4947332e4d60a368ff10f02b4a0e5d6cb2cb0ae24044c3be4d196dede5d781cc11041785416ecfcfb7d553410d2a09e1980f0286ac18b84916646deef179ad586b638de15eb084f3fc8a6a7818054a0fd04f892e94866f46bc67717b51e39069d815433ae81d22ba57fee38197d3eb480", + "352f091cf3b2040a345f06c96e7951e62ff6080f90fe9dc01082c892e492c191": "f90211a0f97bdfd4502103bb567df29ee0694a12b5fbaa8d18f6ee71e7761f1ecdad1d90a0caa482827e86d181120c76dc3a387ed2ef4a060512ef069761e46dd0ae36f247a014ddf44fa412008d1474dc05213d071811fc028823d2813d9977a49cd1acde61a0bdd0c560b880c38a7d46bee3a43ae970418b3df807cc51d061b1d267ddbd71a1a02a22ed740df193d59c2243b1cece7c80fe72db9ca1757d66e7caf3fc08b6c7c2a02bcfce0095d842ee2ad23d02e1949a26d7d9626d9cf22f9e900f5324772f0e3da0f4a0e3cd5d97e73506413017784dd6f1e33f061a354397e0b1a56e58fa9b806ca0dcc9dbf005fcea417fa7beddea8da72767d82c9be70a4fe25baeafe1a158fc1ea0d3250b7d995446f64647907f0d772923b83515ca18299158063b1062a6e0401aa0e464dd36ba4e3ee346304f92a8fedaa9730b7fd77836f8803cd6ed0db00ec9a7a0a3601e249fdc62cbcd1579e152a19b9203449b102a2c87078949e553bd51659da0aa6c480cf9ede965816682cdb99e7f3c5a62baae176b72dbac0e27997c1348f3a03b3318df3cb0c81229deaf3ab72806e0ea417a8b2ecc52e1eaae041b6f476f78a04db38a94f545e3cca425528efbcc2f85ddbb1d460a975e66d98e285e1c0a71e1a09d5ea6a9670bf19041f977baf110967e1bb3c04166b619d4370461c1782f1fc3a0502f8d31f0e3419ae95d6b0c1f914a5cbb223996fdaaa76c160939ddbe588fbe80", + "35c92460e5ace6fd55a3c71aea5f7ad1770f30eaed01be6917d09213180e16d1": "f90211a01ba3b7ebc7083b3971ed261547a2f5f1a9f8c46f5b218fae72be57ef5f23b9b5a0fc6ac87d10550c904ab264584511899a12edd23e6801f80ff68b5ecd7f774de1a0e2db3fcfdd13306b3d052656466e2e9706d3619f9dc753a6827d04f4a9ac1c0ea01d6a1c24c64bbc9cd18fdcd46c80fea8d488ed75887fa31c05ce6564e7292dc4a0f1383be4d7fb5342d50b0ea180427f325d4449c875cd2751f95d8c84c280b2a3a01d7cfeb1bc2dac55061059dd4879a84a1938e55fc91519c91d12b10aab86349ea0dc8181e6dcdb6789e29ad5088bc979e3684556984cde5bfd733941656e52a9cfa09779e74af651bebc8064fa4dcedf0ea1d1887aeac1da02a18c939112cfb3f73aa02b1b6130687f690a6ecb5b5cf278e184972d8a2b7b80a16b400db20d5cef97fba0f86132b520369be5b22be0cf8f11d59dde496ffd06d39f3f4382cf1750867238a0c163bb1d08ce5f47ad12dd20e813524e9ab1e7df8cd40cb11dcfa1123cc2b464a00440390a059d2cd8d4fcfdd14a30e5a1f468bba28481b365b8a8492ea4c64de5a036f5a1053bcddcf7800d764cf6b65781a9289dea6bca1da6cdc9c86bf6a9c5e9a0b54c1ffc2900df0749148f1686c327c73171a4ab8e1decc30a6039356d8f2183a095231e944eb277a289826b94ad1998a247a83c318ae8823a257fdcd0e0d40180a0e3d7020041eff5135f1c20c3e7ef7dae9f4458d4cb23dd74a7b27af3f135f0cb80", + "35de7be5749ad715ce0b80379fcb18b79e77f2e180bb03d788dc5b4625974171": "f90211a07dd334682ad04340534dac571420563e12dec07e7bf428077a14dbcee4e61883a02c362b58777d008fe70c1d29431af65c67e423ccf5dddf89d225d4b18a8910e8a0b1817f7f16a7b5d7f2683a749588746e02039e91b9f3f6ab6c1f7d94dc264274a02696cd27ea9033e6f469ff0498353cfec363ec3ca3b2125a3c76d1460ab4fbefa0d59a430939cd95ccae40d799b395f29fc0fab8030aa32e267dece6fa719bec70a068155b38777ab0a56c106b8d342e56cc515da6a3bac1fe3ce202430d605063aca093eb22fce415ad57f73c106d5532f46b48575004db20cb27f606f86affa9820ca0ced74d4dd711926312796cb73e891d42d5f04583bbb9f65c14e2fbf1f098bb74a0dad5074f837ec2c20a2e176ea2aa47e5a6486ce1e83e11358dc37d7b53f36c23a06c9761a32021da74497b22902bcdff0e1e08d63f5bbb2c6c231bcd97b5dbd3eea0bd8a42a728f2df1a4952fb0ba6184fdef06e905921651baa957319260c20b13da035061c0d4e91bff9030cdfd45d293cdc1c01bbd128db8b631554946e3e6b4135a0bdb692059679e655db8c058884c95c08dd32988e555acb442a0b1f2060deecc6a0d965851d41e33ff2069828ad97e4ef175a9fcef2de2f0e1d5510a23e1efae0e9a0eb3d868e6cfb5ec2dcb64353858136fad82fd968e1f4ff7595f252c41361e472a0a51ddeef009ad15e4158ed8206d43c00e4fab767e3a364183fc42b6bf2915b2f80", + "35e2aa19a97f67ab742e104e1d8eaacbe1d584a6d645b2611eb587d5a31920dc": "f90211a081592bf1e8e07ff838859bbdb4e2848efa64c26f4de05f177bb2db0e1841d60ca08e269e250d0e979e9b5ea21b3bb4e13489f6ae121d039e6bdf0ea1c18e79dbcaa0406978fc2475be66e65bb0bec1150283f09953754c3fb08e78d5b6008d01a4aca0a9a6657db7b1ffc9b7c5181e0b876f5d660440fd5a0970e4027b4afbd9ca4684a09e29eca281c928d303c9daaaadab8b0d49dfbe7c3348247a315ba63fdbb59aada034c03f086e96386e68103cb51019ed8bd52a0724bc97ccb506a77e2f377509c6a076bb06bd39d957dcacd6d7ee9c4c760b43efc57ae96f1183c7d3d1303682d69da07527dbcb4f2cd5bbea0c8aadc2d7f9c62a47743d5cbaa8ddc7e6fafa2cdc747ca08537137f19303515afa1ead5f04ea7d537a51e3b27913539cc461552a1af346fa0eafa7fe4b63d2ef5695d8796e03750edf0f901fe8e650af42ebfa8bad1fa1653a0a08c63b09aa02e40f3282f9633eb0a719ee888c9495e9c0b13b1ca20af5b0cb8a08f07b99b208e9dce86c97b9efa0ca9c581d8ec3d0c587bece3d3c29f1dcba359a0409ee2204104f89364d8ff702eab8fb8f3f3605cde756c6b5dbe31b6e3c426a6a0f58dde8702ff92a6b5b794e7b21a801ccde3c6340ab800af6e649a989e1d8836a0a4d9ad6afaf5a1ef480077fbd324becd03e5d64e8ed0919acbbecfb2994f2384a03f16a7d45beb6634247b3b4c13d20095ac65e19f11f5ef73c9839741a7c0cdc880", + "364d76b7e3b2592165f3f230f886386a3109deea68cb89f02aa0889b35631081": "f90211a07a9cb3a03da54602db9ff52e32a1d66d907be4ca835ddcf6096ba58ef9d5ab00a084a9ede2e3c7a9520b093922af992c21bd2e4439584e3e4ca164c5b237d72ab6a075935b87cb5c86539232da70a34219ea7dee9369501015f78623650413605a11a049942eabf678b897f018a6e069034cd01cd4733ad99a7328cac51548d995f6d4a086e13736582a41648e65c6b25296a7c8bfb0790c1b60b0c9933e47693a1f21cba0840f2b5551e154a7cbce3245ffebdf778c06f8249f0fc8677de63ab26a9987aea0d8cfb2bc08221d145770ee03362b310c6ca2eaf91082a10d4e6398fc42f59491a0f87116007c5bd281ef623749e2cb5b70a58780339f559bd0e474282a58c289a4a012c631552e81b5010a823b8cec3da02ac1392b805501b74c8e5a47624161a2b4a05896d899ad0b84f26f14b5ab176a91feb722f5fe9227bb84d920e08255d59de1a0233e1f65fd7ad4277095db17b2c2340c9ee9b8f26724182a71ee369ace04caa5a066397da5d271e64818798e2f37d991783d2ec7be870f2ade33354af437b40907a0f07f078cc52f6cad9a7bd99cc65b53999b2d08915f1fdf0a4c27366ee344dc45a06eea92e4d6b00ed36c967305f5244ad9f070af12c972145547eaf34ee88955c4a0fe763937a1ef7f025d78822923f9bfebf1bec60ad6f42852460fff0d1389c24ca09765a7cde4dd9af9a32c9ae542fdb13196066f06669ff9b061ed44d278cc052780", + "38c407ee099396fea70641e034a9adb064feb55ee847cbdd16efb3088ad0bfde": "f90131a0eaa0c4cb777640ca66e3ccc8a96add286e331d9c97de5dfe74914955d4330ec1a0e829163300261b3d87d0c7d6d471e5a56b574c002228488b10e1a3780f412f2080a06930937c080b0cf158c7471321e9a6101a692de1406aef07256c6f909784a8afa099642b3f00590eb1853d37be12322afbe89bc3479eafcc241657058c43f3bb0780808080a0f0570d0215c72c80f88b99fbf3066173f08d70b1a38710d2c8f7da1b338c63afa0f12f3f649bb77b95f95af0da0b7fb3551c80cff7cc3fcc1aa73d1296118ec8faa0d9dcf09b4e25e287e4683e76261acdaefab82b871ab09d5dd65da5065b83cb5580a028dd75094542ec3120346a146e07c65d6e16ef4442ce9e86fbdbc9192aa3f64380a0cef96630ad5be040e91bb32b5a753e09c3bed4ff07c31708a4bb1a2fda76be2180", + "3979b14ae2085de9cbd50f62f4dee7e90a84eec8100fb7d47ce108cd82791451": "f90211a07b44c72886f3d3e96f257d1265972ba9616177b5055ee45835ffdc0e627d4ebda093138eef616cff0b1eb5303b0a19c81968a61d98d67b6d6e9687abb8fbc24539a0b552306ee77d1d42500088da9bd8043abb00f22b0de77a95c34fa882765cc98ea03363c174813627645b9b5d678af35f5cd41b066d7d0aca6c56f98567299c1469a05e90023969e99dadae2cc3744af16a5dd3fc38e66db777d380ab9dbdcd752331a0d2acdf341efd5546d58ab22f801a9e83906de77871398be1c09ee5543ee21687a096f0366d2c3fe2e119a28366e85c96741d4d8e0b93759ca05f9ea8c0a5fbc64fa02110202beb9f5d1291ba7d837e06b6cd25098033d55712d3636984a4355eb6fca08c4d037248f1e876b855c0af4998d265dca626bb3ba7ff58262373343d0fc09ca0b00002f24b378c8f3f5eedf4ac6d134798a4413d34d16ffffd97ac81c3d11a87a00dd0c7c97df01cf94b3378a5630d60815d41f16f399f0a0f15532dd4a9a9d98ca0f28a6fdc2ee2915b35ca6ddaba9195a836e2378250c73e5546866cc74af20565a0a26ebcff23ddee6272de9c6d19bd955af8bc050da35198ce8e472c36796d86c1a0ea20d5a286aaa075afe2aaac98f53de26fa250a220d0f36ab4bafcca40628e74a0e4e7cd62435218a66d71cb8d59124df4379b20192aff3504628fbc9e23141414a0ac3fa07afad499090ee0504149efd5ffbb692227f13ce4e711c25afbc42e680880", + "3b4f0fb6fdaf2960de68ac16e541328b49d12a2401305c36dc8474966b3db08f": "f8419e3b08f6bdd1b62e712ef7d2d838e79e828bcdaf725e4ea914ed0f1f0e2394a1a0deadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1dead", + "3b9f979bce0c4e71b0ada08233305fb42b28cc6ea5b118a71dee59b7f4a41386": "f9011180a041aa3667291d1a1aede4a0d106750f51d5e415504262411b2f34ca35637dfbdfa065ed69960271db1bf64e6520c909354773c6bf8a47b6c60f04ece48bed55dd7b808080a06dec15d6550be8f9003f9b8c92225492fa68a82e1d973ab52e85780dfd85c54b80a0497a280cfd9e04c9644e0537bd3a0e9ec49dbbc98c6976f7829649b044439e4da03260eaaaae93ad207f3e53af71044c55d0ddf40cb64c73318e1aa1d4957469808080a03e8363d02a7abdc271feaa79078b06807194f35b3450422a6ad8125338fb44d6a0266c4e4d19b7ec0339cd2795c63dbd018f81e479715cb03a28f9ef74339938e6a020af231645431a55df0d73c5460e4283ddbe4fa856b726578de41dcfe156f7808080", + "3bbf6c6535a3025f1241b51863b866240ed9931e748f1151290b4d6a653668bb": "f90111a09d7fe2349228a26b04c1f29fce533fe4719c8b173e81a538e54bf2b9d8ececdda0efe4122fe7c8cdb70e3901de720b2a568da7137a77907b6426e266252714f5dd8080a071229f863681b7dcb6fa1b011a3ecb551db477782a2da44380d05d66e3cb2b0f80a018c38b5d40f3478fc935a61b1a04b1e5428543028be6885e918bdab29eb33fe0a03d09e76a097d20b3d81b4b77dcacf35f42b4b8670448dca0cd04c991755d41df808080a0de4df359335ee25ecc15beab8805a17b2870990f4c5f440f9a13964e66ec5dd38080a090f5024d3ea68b0552f989adfaf032d8e476d10859a0eac0b9bd427eaa39f50fa0383112f1cb7cf0ea8ac4d4292b03f85451e49f24100dabf6978eef9a75c743a280", + "3ce9848a03f46346998366b6463b6a8b7292a11d9ca88e7b09180414d3dc862a": "f90211a0bdc7055bc036c070ac439d707d1036d7ef09fc8c11598e91366f155b7dd98208a00a3a474a2cabc0608cf43321b2a501cab74bbe7ef4360287ef26d0daa6e1d617a0a1c5a1f274a57ec5d9266ff6e4adfcb36a1a481702788b26b3e1a09062616be7a024c4e6a218c94631c8b592ccf5d79556968e90540d4f2eb4cbc696a4496f6378a04a196a217d4779421d6f16f3c5e4c71774297581edac672565249030b8025763a0f6f2adf9d99c40adfaaa8af04d8ee567ac24bc5fef5a366ebee82d84d4a3dab2a029ccb2bef54d42becd507ba6a1c2697ee3db7c3234df9e12470c369b91f3c86ea09bf1f58f54133a91fddb5de5dd17b2eb206e4d442063634957114c5f42475653a089789256c17ae705e6843d5377e49afc2e38fc67b2318bac1df7adcfdd9332b0a09e188b8ef859f18bc5fd78fb850d6c7b616cf4af74ae09c192a55ff12fb38deaa0e4fcacb1b84386560467ede11a97a3c8633b0280bd630d6fb6dc4dbf34b855a9a00795ba7b29db84bd95b6f7cdd593a55a7b6f3631e904f91b33b57ffeabe9498ca0feb263c1068bcf20da3f2d4d869c6a77932d2cc11c1a41250fffcec286b74dada05e26a870655f93d2c01dd44f36db8c6335b8a28e3bf18cc35ece2dd5f2250241a0ace05f43632b41dad7e1dffe274088fd9f245b1bd4964ccb1773e7f5c601aa2ca0560e599211465c8be0ea593c4aae9661d5738b8556e3bd2175410df85439093280", + "3d69b5c506034c07d79a910dff5574d882ec9f5fce414521f4f0fe0d2b9fd6cf": "f90211a035252ad0c1b042216e446064fe62fe34fd70070b8777cf16aa5d5ad4169b6bb7a0f7261242aa5d2015de9272a781712f2ae68f64468e0226557fef6747eba17260a0a3a61a074cda9666fc259193fef8e93c0bb5ff30ec7dc809ef7b029e3723012ea05c139098057d1b2a2f7a5d8fea6c6707df1706c1416cef9dbd317c84296c987ca0f591a21eb6ec9a43ee6dae1f3ce1aa2f325e5ba5094d7a56edbb94d7f3abe8f1a03984f269fbc7749b9fc5a0ad851affc5678b0e69a1988a915c18e50d86a4ae6ba0accb7aa10bf06a11781d12757829736dd24a29ef152ed3dfda429a7911e6543ea00b4f2d2c3e1fed8f9cee9f6e1dc89a18e7eb2c920c39a19b8b73be57fd84fc49a0c78383a4daa4571ce7f9dbb12613ebaa319e4bf5cec634a8878481ab50afda2aa0ad3e3ea14534d872123a12790b31463925dc4f6b67890cf4ce9c732300dffe2ea07038cade5bf3f1c0cc390ca269355428b0acc08f16e971127ad838db11df6a58a0470df882ad012efdfcc4f76614a56bd2f5e0685c82cc8215738c54cc1c4ad353a0c627bed6886ed02399a189f56888b942d77bf6cc59300686b5ed77cc4153f2b0a0b2da5feb95604d3ea1a9721d0022d604ac74b2444d2a525f271c5e44fa8739cfa0544344f1d3beed0e94f8aa4ae42dc5b33f95e36e6597277e97859ac62e220783a02a8b3e808b6fd58d530ae68709b0accf86a031e04ecd11556eb241834c6460ed80", + "3db13a12eb71d23b238d7c68c6daaff0fa9d996232af6bba35a404cd24e4e7e5": "f90111a07096f2a2e23b843798fa206ebeda3570c9950944463874618d513f52625142d4a09d91272a9919a923f1908c2ff02dcdcb4ed112c7c93851708c78aed6022f55a080a002d9c976fbd2de150dd04f9f3be6968267ed8624e184a019fd61933489ae78ad8080808080a038cdbd05061085c9a4d1791f0af283219d8f7cc32d41c0d370db17d02d198fd78080a04e7b46d258a705ffbb5ef02e9102bc92f359583afd539250bf75aaceaaf0e17aa06fdddb0a08b0707aa7add6bde7db8f681873a50e5c9a1935dcc21b272836c578a0fe9d760f2888c47d73394f9b732b363df59995b0f18e894ec9fe1959c0a647bea0b2cd109125a195335df79abd32fcefa9f568904647c96838cf22e84d780c063180", + "3e065d058e6c7385ce0a585c4ffb1eda68b75a8b11f67613f6edb5b8b94d56e6": "f8d18080808080a05085a3448cf7a9a038a091c82da9390e2ba3eeb50235ef4039b0238db6ed3d40a0bd2a4909af6dcf9371d32f5fc561ac72a4b467ea343d67eb607c525ae1d1d99580a03364f8c9b491a56633ab538180dfe33f0857ea12404ad5ad5241420c2b6ca4bb80a08b12cad89d808ba0a0881f0ceafffdbbaadbf1e3f477221d6f608e2c789b6069a0074fd7d0a32890ecef3a0dc7f7058d8840041837c2e53c15e3c1d0c7a34a24f2808080a0800a2a5b06e8ae6c0c7e2ebf9adea7dcafa343c4671d7c0a26c32e230092595180", + "3e10b1fdafeb71e1dd31f7d8cab206066d4c40c44bd91f3fe76e2059bba1cfc8": "f90211a0f048fb947cfbb117dd191e2b76ee648df0dea92ad3a3ee0e1b06aaf246290f61a0f87cf1de42ce407325b3f0cf4673c7c795ab329b49a3af9f8f4d85e640cf839ea04e4133588db316f671ca012f6730d2b6cfa2885fbf44d10ceb52ebb8534d6440a0fbab0a519c7d0fa113b70ff40a755fc01f71ce7cdc1a9bf9b0ed9d9dbf682d31a0a8816150ab2b71213ca709ec93bccac2329ef3a6b8ed4166a3b8d6733e43800ba06a7cf49cb514cae10bdc567541ee924b54a7cfc7596f22fd07f9973c54ed0f27a05494d18a48ebb156216acf5b113eeb52dd3f91e61ee626e1e415c4992cb072d0a0518675ad01e281673d4ea985d13b40f1e76841f19b9d72accfcfbeff758457bca0068fdab22ea07c60658ba3d8cde35435b9eea250409af363915ba94bd41f23e4a05a28436d62c77d9db05211ba59c3ce91ffac1fc711a5f0908a8250e48c3606e0a0e0ea26a5a67eec2338093a9559e6605e65b539e895f26e41f0f3cb56163d4b15a0824d5b736916472ffe5938dd302942fc92e6190a2fc6a14ca00d99867f140726a025ac3db51866700b784c8c00e8d9781180b766917eb9dba8fa0941171f09c774a0dd169ff5471f3dfdf894322342261793bb1a17329dae12fcb6bb27c223069e6aa0f9a9a358ff9b051bb648b66c985a3ab37d9e2a5c2f5dc142e8f949eee508317ea0a6ceb67791b38f55ccc0d46918f7c4b8bfc82185e4826ec6b8b6c2c341a523dd80", + "3e745a25b1f92ce88897f399eaf7ad3205b9460fcf0f9f9423bbeef20bb61d43": "f90211a00a38c42ee24a80dae2a47e2006797c7ea80db11ec92d12b9f640973b4fcf3e86a079fe33b824fcef9b333902ec60a1ee21e3f6d4f9fcfa81e305bc3a28da66bba5a08135afcad98a21e4986ed6843266f03bfa263db55b65dea84ac36b494c8e3798a056c37703afeffbe15e1b94a69d83a50e160d32586a8b78fc2d4eaf7701599859a069068bf9f2d68540885b6b9614a469e244438f07bcb42a5bd30f33fd6bff0edea07fb042b5f04abd9e7d20eb43a93ee5e4f6cf53eb9895d7d2a197858882b25c83a0c10175f876c3df6331e035428fbad9acd97b603f958782c6626e0aae4652072aa05754082b25891642379e93babd281c9f20765100aaacdf83a828a70bbe4b7c66a0eb083806a9d5abb6004efe7bc020de17abd5ad4ed6e7d482955b6d3e35c68693a0a2f32bf692b7d688475cdacc21fd7dc39e602c8c2ac022d0370444c269d4982ca09eb65b83436f844d348d3124e9b2c3ef44159c4947dfc8347f8837558925558fa07709c3c2a61387711e36ff2ec462395e283acc52c80b30e2d9a3a0290e6198a3a042d3d2f7e27ca7dc97509ea5a5345a36096d1dc66756ddca22fb3551c00eac7ca0f238c24879af1f3f20b5634d94497cd204298e5f1f6f1288fa48bb2d61380924a0a507663a262c9d9a272df2f325c25f1b7607c4e7bafbe4b400e87253eb36708ea05ad6c0f8bd7c85c4b8a40d46854836840ff43e46225c1e687dfafb2937090e7780", + "3ebce803130ac496dccec9b324f74c9942c394ded403dc12befbf920da3d343b": "f90211a07dc2c04993e97df22ab8a5680d4682003ccb194a9b2eaf620076c7059fcaff0fa0f492f19dca58365288f03232028f85337cfe7e3d13dddf5bc0b882d359f2a0b5a0db5246c7fb85d20fdd7697ef5b74a19f3b28f60e25ec87048d70535116f601dda05322f325eeaf839ef98e4c720ec8ded29bfa2f33e5757dac9842fb005c51ff19a0dd10e5269d9173c18a0d6fc2fdda32a944673191cf7148ba16013bbde7f3bf7ea0ce78b0a1136d498b97567ceb95ac1dbe896e4769e124c2587a930a4bb86fb099a03c8ce7981c254245bc9c0488b864fd55a47543fa81c339b5e5d899ecc41be11ba0eb892ebdd2792bf116ce97e64426f984bcfcc1ae87dde1a92129808f1f52effea0cfbc10471a3550c42237d64f7973ee5e03cfcfb17a0c3b04646869ad429ca228a00c69513d2b4cf4b62fc12bbf9d84ddce64dce165853c07b721db5295e8ed71a6a0d8333e00f44690a52dd806f27e3e7775fde6f72ef05e4b7ab6f2022590e82b66a0daaab278e57affc32e722a7987def9c9e8bbca4fa253ad06179e8f27795708e3a0167eb31d4ba684e22f8a14d039afb387da5ed64d1eace5b684d64703d511727ba0842436f4aa415683981a1841d9c339439b26e45e35d82449eb7b4985f15fe9d5a09d501b30850079e6a45444f3b7c292a2fe42a41f8ed546335f61df4cb4b86b81a0e904e8981e2f78221111e7907f72c7377bbaa0b594c06494f5a272f5ab6d44df80", + "40acae8ac67b44fb79a17c6dbaf0ccec294d1b11994f5feded8472c8935d2950": "f90211a08a81b14a2dfc4d1d1016522f5c2f9cee67a48bd4b5063dfb387d68c050cec044a07b6308c26ee534b711149b73f70a8c17f3d59347f7917cdb0d48b60f0aac8241a0cf2e13be7626659cd54237c1b756e762ead0c9feb45035f080185f3fdf502d32a065b8151dccb9ea646f665acbf7347134317ed3a2f50d9b7dc1c0cfd1f4797f7ca06e1418f5c9956919e489591e0ac656ba3b6d9cac188492b3fe5c18dac382dbfda0bb4e5ce2d9c4c53b71b19fc7b3f13255c06eebab89ecba1e552e8971c9b94458a0ee89aa263ff21ba93813b629226d8500bc60077b284b7b5bf0ed47eb7a813385a02115fc180bdeb0514f62cf7733c57ce3ae932329b2655b0723ad19617f548dafa0953ca1be32f71d97bf55b70e764b81919d514f846bbdbbc9253c75a4e25a9a23a05b4ef9bce666f89a3222bc218b67b404ac50751a4cd2225411aab215248b8a1ca033da2aad4b89bf5bedefdef836366c3931b19d3e3f17f9a5fd254929adcfa0aea03d9dae4f09762661c2f624cbf0c70d15fb90fff143f44bcff1aabd7f42297d0ca027a47e0914848264f477acea2be466df2965020576c16227d56fd4e150dbdf38a051b4f8ecf17f995336b11d8d2257c6b64b522f2c256e1eaa088194875f02840ca02e029fb42fcb83a29a7e19eb368bcba3b4de6f011b3be614e0bd352a82e41d21a0f130bdec7e26b0d15a52a72d20042001d1af2ae0abfea018bc5c6e27d44e7f4980", + "40ae4d08698d20dd478b7a5313f033a5a9976fdda23a6b106ccc6c941caff1a1": "f90211a009aa224e7988e9f954ed55a0d0e24ec650ad0b88f1ed3b03e48b7e54e8a0a6ada08a4e985018aaaafa79bce08e6d3e3bfac2d563387584f18e04ced05ca3bab265a0e9784edaf4b46f553743853f41e36e9ee342e185b20fc723b5f14abde8763b7fa0e089a1ff25de664744ecb1e30e977d9bf3fe2d6e85fe4b5380ece22388da8432a03ce9848a03f46346998366b6463b6a8b7292a11d9ca88e7b09180414d3dc862aa050f0fdee12b49df08fa013c5ef2f7bdf1505cf61b6db540c7954b8a72de8e0b6a0b34b9ed39713c1f3ff56b2083cc7a5214933aad83a6378514f1233f3f951370ba0081f45d3825d168a6479b5f3bdb6d06d694cedd0196137e5eed6f902af71d135a0a9e3be7a0da9853e589613fb805ef5f0b3c94f9718cdf036fb45d56b2148a8f3a03377af2b05083b18b0d4db4fbd1426b3e1f93ab7776ac474495b2386b6faa11ca04aa82c3fd48ebff32e68afcd305bc5d2b0ba023921a386a6e5f6aa0c5bc264c9a0b399e1f0bc99cfa0949a7620265b0db30e18b674c9b293e4977e79139b91d6dba00932cf3ea5e36f7fc65757bb400898d033e3fc86080dfaa592aae8d892eb2475a0b3e185d9ae735e522d1086c0359c1fcafeb9afde22d06d993cb47733d32b7111a05cc719f556d7654181ad34d7e79c7ca5c45b2992cc68bc5490682665f1f0f55ca0151bd74954cc44054c432698e77cfaf449ecd1d456cf93e353e4b9fa89933ec480", + "40e6efd8aa0bc63817019e3353df6a5cb09e4b814570d10603f594eab130125e": "f851a0f0b5ed88d92aa883a14245fa7da521d044c68c7636aa2de95f5c678049f511078080808080a0ad167ca515e3462c878c5f881151193d47da4ace9e5152754e7fb6f436d124ca80808080808080808080", + "41aa3667291d1a1aede4a0d106750f51d5e415504262411b2f34ca35637dfbdf": "e39e3e06f1f07c45b9a6b2d87091fd8b6829f3b0077495b8c6c6fb5143da4bf483820801", + "4244dd9f96367c3df36102cadce07bf565fa939742928d8549ae16433551272e": "f8419e376498190028c9aebc48eaad5d35db68a0ce586dc0698bcbaf462198121fa1a0cafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabe", + "43133fa8e729d429cc930c42f073ad308b68fd9feb1621954115fa8b7543959f": "f8b1a07f74333fb5c158dd04c8e308f282b1d0be051bd81974741c5d031ce91d945ae6a0218a91450a5d9b0eb4e95ab04c38fd641e565878b74026ec4f5a28a96a896375a0e437793e7316298827a8219a3b3d9bfdbd5268f0953ea6d4cebab3b93af02bad80808080808080a02cc1f9f3767c07965012ebaed1d4602a1b3a4b1ca0e6ca3a76a79aac1a12cc7580a0e35df76cf5b89dae998bb45c85a88aca6f9ebf599a96f7c4777c113bf0c10fd980808080", + "43e7c78ba174dd20a60619da5e1d34625ec653c153c339fda9fbed93e1c9dd1a": "f90211a0997605a9fd17c84a0fb7f7d7f82bcb0e110b1ee2caeb346c7faaf6eb6747f976a0dc2ac72d34d1f148f07eaa350a1c09f15efc0054b4b0d5f4a29202f0753e68eaa0526a7f1698dad58bb8424c15451eb19ad7b0f1ba8bb52d85dc4db75e4c3eb68ca08a5d4301a6def4a6960b518f022a2417977e66516875cbb12b5e2e1713059878a0141534b037e1b6f78e38ca397005946cf8ddf047ecccdb4065c35fbcbe5a58dfa059086c218a2cffbc29ecf3b698bc651dd766d010dbe0b1774b264ca1de603fa1a04f6c99d8febfb5c58b8031b99b65e0be0e35ac0fae8d3114e4c75ca84e1030e7a0260a6b78103fdac4264414378078434c38be5751bcc429a81e98c16393803c13a018c880d68799a9f167e759997692cd6aa973540877bf22adf656feb2bb6fe7dfa00c452857f16ee17b86532965a3e569ddf5cf0b82f10eeadb47f3dafcb445670fa04a70fa2c68bfe5f3ad8ab343ea70ba87b7df4372dba140a596508444efb4c778a06d364072533d279aaf35e0ca06ffd6cae66a9f975750b5962471c52f76004391a0a30c7aed3f564b2e7cc4331fe1e7b57503ab71d52648587cb4d06fc7e1478bfea0e72ffa8bc8e24c2e4ce45156f9a61d4871896c1886722ea41a9f57b7d1eb1cf0a0be3a797d2026d43356623e86f0c8ccf5955ad90bda021571fa06667775e29ba5a0c2ebee2e9ef4b2f76d2ac7aa6a3c0a449b93cb3b75d2b53e333d5dc279eeac5a80", + "453cca3ec06cde57ab5af155f45886f1c9b61fabbc16ef7b668420a2c154d39f": "f8d180a0997e07ff40800c3c246df3b2227bce4247844bfc7d00de38df3b0f205944a831a0cc1e44f7a040b07e8756d3b3571e3eb4b909498967ee55712942b40a48dffb96a0bf7664bc8053d85aef4d20421bddeb6d390788bd42808ba88382486a9c9534c9a0aea20816cfe01ebb8dbc1c8fe9fed466ee664ee935129f596276ef98fd7b7fc0a0750ec2ccf819d3a775773782c0990f067db0d99f5fbe48b53b063221a4a99655808080808080a0b5723f571b144658462e2a6ddfb204732c55b704d0730f0b11872f54fccaa0ca80808080", + "46c2d54a8d8a3da2146056b7d34ea3faa0e411d09ee4b3b78dbf6d8a23dc50a6": "f90211a0a30c806532766775d7a1498ab662af9850c53595d444e492a540ec7bb6ff2a3fa01304e42d011fa6195d6308b3f58482178899b7420d31dc19d2a132fc344f4c2fa0682742fc3b4dd9162f00050d45dc5aca39f6863340b3de371dd7ca0ad288d019a06c7a20e5c580cf3c0ad8df02ddaeecb303acd6a46d29d0b440cce22f1fc3e996a0a66677d461bbf6adb253753e53e38cf6317f3c7334e5a63a14f708fb532600dea0cdf6ac23206da1eb5390299e7d4a496513d40a21dfc32fb69e17fd75b835a36ba0c4304540c7f0e4d166eab23c30a49812bc89f94914b8dedd0c531ac3f6f3f60da05ca34b98fffdec21cf5e17fab7472fd990dd7a21f47b7e2b1477db7c6cd1677ca07c7ebd793ef47c1d39de0762cd8d0f6125536d965a25efda82c1f07adbd4f25ca031dad6f1a75d67696381ec2dd7277992ace7b3ab6d6625e6f7d398a975a82cd0a07ca86631ce759719917275ad805c64783450a3995a0fc2fd002eacea845a040da02909509f448b0f9f9de6d93214fed95bf098b41183ffd0587ee3fd884851eefea0362e79225582d5020a686b4da876772569a0737eed44e3a916bae16d9a161056a0911f4dc5f31b69f295dbb6227399da6a4209ca5a5ad9cd72ea8cd61e97e70a74a077d50d6f9f595a0db56ec8d6d4dfa9c857319dec7974f890c882397916485567a0c8f090014c762386e01800687edaa33a80ab40e7c2f3dd48def4003d8bbe39b780", + "48376b10e7dd81d7e813cb6f4a8d36978eb47e7353a6f6197b9b7b4de6a0588d": "f90211a02e73916747bd1ea38d34d5e4a7533c5aeb1c0f80b2e070baf23d9ca9996dfb17a09fb6786e08ba3b04cf821dcf0693c788ff4b55d36941ed8bf3a443e5ea3cb242a04f6a9436cfd85d3a9c168ce655fd3dff04dbf62cec998ecb55292564db496823a0090b07c0a0244a382ef466fd141d726aa3c80aabb82664c6d263c74d9c1f6eb2a08250f4f9aa977ae32ef0f3ebff2ef9b913f7cd6647619dd7c03bba56f5c4e178a0ba0efc02e6097c1e099074bd4dc4e8306c2f51a9bd8111138a171589a70e1977a0bb26f3635184edcabdd44fd72442ec6e617cfed8144f11a3c756031c7068d649a0ce3c68c7a3da8c478431036ee8ec8460a663dca7b30a0f2943eab4fca2c45033a0d12e171a753dc1dd8ee041dbff0b3a0cda71eb648d87b465ec1a47265b57f94ca030918625375c49f396b96291f10f4c29b285e2923cfcc6ff963ecb85a7757857a0147312cacdf36308c90d8b59776a3f1cf059cde76b85cf99382a0d14aa8f7683a000f493022e2595e2ae4e7f3200f3227c21890da2f6b41d4a7ae3711d33728e38a0bc8552350a2538390333646fa9ff91890c5c3812c45109a9d38175a2a3870079a05da0b9540887740f719b5918f7f0789ce703dede81fa04f4327333075f13a6bba0fec2b272ccc01f11d1e7721dbc228b66a96983c3cbb3324383e5e09269caada2a0d69f695517b8359b40cdb5a9ec85843478f2d256f7a588ef7643e15d8ed0cca280", + "48c8682b93c11babf440c77f107e1cbdd2f0771980ad3417ec12a9a58a5e12c8": "f9013180a09afda2a0e77480a06e11d09e9c342bf240450d9e221a8799e233819a4f4547e7a0bb28b10c873a8be717d4142d7b96dbfcc1ef7c8d6f10c438f30c416a96b298e3a02fdabaab4e280990e13425f924e004e01fdd62893fe066f1a710f6d325c37a8ca0a4432466ff4a30172ecf841857e07f8a4579ee34ea2accbbde104c381692cd7da064227f467b812f1aa41f28e98ad8ee0dc8cfeb8fc0e088a688ebaba4fc36d0b480a00cad063cc7bb2e7240a5167365d3b6f618f268cb31cba27ae8d5a2374c9519f68080a097da69b641640af0717fdb0b3b55ac7e93b5917904e9cdd201ca4310d74a6304a05b2e29e5e3f1256fc1626d6cef947c681c2ba97ea5f4f722626c74a9d4c9e3298080a09381caf8faf51929b05e29d333397fe3622f77cc1831ed1258a1c13103e5a42c8080", + "4912ccda03dee09891c6b41c336aa352500763319963d6f4c4cb07980a009663": "f8d1808080a082c5dfe325222827a12ebbdadbee2dfeedf96d9ce46d24f015622f3589808d6080a07d94b1b8c6bfc8bea71aafc1723865e0e8eaccd1b0803215676c0e1eb78b9c2780a0a92dfe16ef6bb0f0c76657e05fe15182ce0336f8b40879548b69b1acd1f4eb908080a09c3730c278b5dc52038397a36e56314e7acf4f8f73b4125a42ce685a756e60fa80a02d41f50687bf6af4015c34a4e0d7ffd4947f5bcb2f942e3f9618c1670de3e7d580a0c9307ea5592cb8364f1a63dc3d6738d1d8ba570f7111868755255eb906edd2098080", + "4a80bf00747a6d7552ca2301977516b493acc9742fe0deb2263864ce18be979e": "f90211a0b22625fe14ab8ad808c0626410a32a68bc96471d3117247fbf06408747d4060fa0c21806ae7d1baf6aebf9250db5f950f91f635e0f51cf0b22c1d2905caaed9ca2a09deb67240c6104a9a9624598e2a7e55e59b229c8ef9a0cf056bb732a97844a9aa055b1b3554e08f3981eebd786913e85c9f9b903ea2318c625ad125dfb4c3f4b55a0aebcc8e4eadc88923ca4d53aa778e062504260ed5bfd16058eff660c0f1f702da0671c057afeb749b90766fafbe83daa8b0a97849ccafb36af3882598c2318fba9a0ed68b82ddfe139752d7e4cb427e48a340dc9625a6ec8c525801c8b6d93238c92a05fa1ca26438e04946f09b559b2bc2befb175a941c88aa1b97692457360d022a0a05573893366387572db13bf9cc77f1f1ad89640d557723ee809a22a1fab0b3556a0a8a35f8bad4594aa3ac1128f02cba7de80486c451a559a15113f3c990cd98355a0c2dcae4fb914d0a909ead4e63b9068e996e8cb321bf123712b02ddf8853c197ea0d990f3dbe1dc84d16f17bf8f856542642a91e5b345a6aad3d7ede8c3dea578bca0a40ec6b1c85fbdb13f25e039c270bc87154e277ae2b4d4965ecc1cc25e4827aaa07a730290e40a6f113eaae9549ddc4ed398208c2d980549584267832920d18196a024b6c9618f4dfd8a74eadc7bc7b0d4749eb3ad761cdc8d22c2f959e3f1874845a0577f1f6787c833d16b037eab7205aa6714f4072b55c94d0f76bb996732b9ca1780", + "4af102b2fa3689d0481dacb746423b534615291bff4e45497a2ab27244566a7a": "f8b180a069f573908e8fc5e27de3bd5a7fbd61c1b7cd494ca0ba4ae86721811492bcfa4880808080a07297c2f4086417ce48454b6ebf8798ec1e1451f5cf9526a4e30f35607fb7754ea0ea72222d7173a1fa190d8d2549691ee1f27c9ec950b8568f73eabb4d4800826e80a0c36642f9f506b63a0a9e89cb55e9c804599241eb429c8e4227fb503b60ad96ef80808080a0eadc924c27252102387ff446a4b4502e375438ae22b14be8c7f86006d958ddf58080", + "4b35e582f15c2bd913cf035aac7d15090035b0482c8f251a9356f34ab1c9dcce": "f90211a00e4db1035b04655db35f57b853cd6fb8b9511aebd1d72dc339034bbe2175a120a09530637001e8fe5bce4eacd2fb59f0f7321456d808284db0ae0b47efbcfa0fbba07b3b8f154a855b7c00ebd0a6d39be77b79d23eb330f5f174db38aa9dcba71965a0ba1a317160d6511f7c7c07a43a8c835e075b0f5f49f3fab4244977a1530e6b3ea0a0d32f84b5f7f3260bda8cef349e39e79cbccb0fb6ae64df72f1a987ebde8bdaa05d442ffd8becc204cf4231cc115c4519e5eb7e9804ce314996ddad62efca5e03a0af7a421a3f3f128d09d801350510cfcdd9d576c2018e6b8843bb113fd8743d8da04a18ebd6975e30e6e3ecc90c882e8461807bed5b244a1d106bbc1b6082af52bba05f79f37df995cd796c2c97ed9420e68bc83bcee92d36bcf79177733982697b75a09e7e35310f859d75bbeadc72d51134c1cc6a8cc539034a789c7fda75ee268d4aa023269df298fdad07cb9cd26e1cee1439717f5144ae7dc3ed5814b885a3ffeda9a080eeeefa37d114ed34c4910c52163e137f2adc21c000d49b74aba447bea38f15a09a6b157b3bf95c77ff027160d3f589c1f49f05589d4a4d7aab106b2232d2b46ea0b0846221076674fcddb287f65c4a85a2638f1b1537d58360daee74785b76b096a056b7991d25fe5a6adbb15ee7b48bfe7ce7a2de83692b3eb86c67ba3872393f34a07a61af2c13e4cdc8d4cdada1d964fba750aa04cb1fc265d346c45f453f89d67880", + "4b8f98f7d3608d29e7bad83389b1ded13df8e0cd496ab2afaec15a51b810d68b": "f90211a08fbdc5771cf39d4c604412f1a80304dcbbfdd287f4c28e4d876dee21035df36aa00a85a25c74abe9f8ff3825b5b85906e5a2fd714b00e788fe0e953b109ae5a837a01e83793d940285498087857e7c4feeb3e086ea6c33fadf543919da6564fe1c3ba0061f926f1a9ed0cadba5b067d85547eb145adb2fa07596ae3cfac20d43497543a0efffe8ada26b778d15b0f2c5a66aba4da47d48cbfef497e1d0b2735f2db2484ca0b96946d1298b0e049fdf340edf7dbe4a7748c76b5b186f84ae3c207f4d0a4a8ba0b2414512e643998b67b4c35f0b829c682c48bafee1904a25377796a81c0fbe77a0833b339730a8a85537ca4921a55e32bccdbfa07b959d0280f0ad35bda468ae15a0064aa80f7649cc440f180fdab2530d1bae5d058acc80ce7d8490d0084efd318ba0675ef9c80c03ebaa4fdc25cda815a72d800f73406ffd3158dc0ef6d061d8c2a6a02420f75153dcda0d2e86104761323df65cecb61e5e45790adde728ebb091e5c0a017a7b079cae6693f2b4c95d5d336cd590d9cd91ab54bb1a583e0f6dc6911b26ba0dd2121ee467cda4b7aeda33b9b38287995371cd9cb803b92efb6ff8415fd1cdfa0d12dd9d51cb18cbd21c0c00816e4c7889ea54bafe9d08b3b6e6ccf28d767ee25a0bbd507a5cef34e74acde372b1338d17cf13e1997a830fcc85139da2fea030ce4a00c390b9f877d78205b725b580212b8551fe0d5c28fb9dbc4de1f500ea53e150980", + "4cbc377795a99dedc57288023f3ce5e6cef68b26a77987cb561bba4d5d829995": "f901118080a0074b7957d0955f1f9f5aee367a90b5e04aeaebdb9922b92d06c195104ccb5ac780a0525bb08fa7a6eaee3e63fd7026e76d5b0b2ee7efd1ca0bc4db6b2f129f21ad6480a020d29324c13264396666ab3fbadf56ee67b9a201a2a3454e43ee9bb2bfbee356a04ad7a50b4ba56a4099dc38f27e416ca4c58e17c688f851e590351db71adf4255a0e4273bc56ac68bc6772925c5ce68b518fa92887da4b8035f9c79702d8dcc251780a00102bcd8f7875741135ab0e9bb19a7ceb17f4802a174d16bac82175d85ee725fa0baeab809d8e04b47ed90154a804d478952febd456c30a6c44307460f3ce7d694a03819ad799ee26c82755eb9a1b67d357134a4a893d024440f7dae334caeddd41180808080", + "518876e0f325280ec3ba986c3c7880b115a9c207373a627320f39490c22ae7e7": "f90211a045dd82509b15cc00a737e00f8bb3cd55de77d7e5f5b707a6cb7a65e40aa773b9a080084a2f69c215f1a7b49a4f13ae100e5ee059f7b3fe92615c787de6f588d067a06c1b42eb345210e1da445d7659b6aa60a17a0f7f04194e88be8b35e752908c9da071e319101f8b979cbe3c2ce0dfb6211df342288993dcb2f5ab148605e441cde4a0332be9a0d2b6e34d855e227bd47e2a3be4785617ab1571ed6b23906528b03d9ea0e84481c24cd5b58b3251009d714726852a4c0800637f09cdd7a8c62988cae67ea0dc0942124b9d4e3d5ef0209c7c62d48040875901cc4bee988380b51ebffb015ca0a88c1c5458008ddc71395603bb3a871ab4454cf251603e8ea5a15e2bbcca7641a078b169dff2f1236f5da7dcac619b5a99e4b7cbc10c8b83c20d39f4ec89c509bca0b4b4f09c9cb49d3c2a93c8f8ac9f0e440c8a230f2c3cbaa29a75bb9aa0d5e1bea04e3adf0f409c74da026d9b0bb5654f78dbe3156360aa93bdce2f640c6730930fa023e42cd5c5c408ebef83e47341512ca3ade30b6d1d345fc20951a263a907f826a07c6cf01e9e8529745db59ce6135f5a442b63af0b96ef2041e0857fad60d0dd7ba077e6ea63e6350bf5f925b8ec592b34038f19aa9e7434a491f0c80d9a7e420cc7a03931d22df3f4743cdc9190debbe32510264acc26d68f1e04f3f3421e2503c759a03f0c8132f093ec2a413b32b653cbfe46bb25e376193c5eb8ad28f0f0a5c8a76080", + "526a7f1698dad58bb8424c15451eb19ad7b0f1ba8bb52d85dc4db75e4c3eb68c": "f90211a00cc293a15cb63a3dac4f0555aeb40d10745fedc7ac9862b308ad044081de0916a0d0dfafd2b3f4860df4d325129fbfe8e80a5cc016246263633ebc3e3b47fd4945a0d70d61e3e6e536bc555d97f32fb7413144f4d3c5c5c9e1182d93526d19714725a0f473d925f476e47f956655c8b2a3b34e225543d18eb073b4b6d995b7340b2114a0f5dc519a97102405d4125eb8b450978419869169872985df9124ee582533095da0ea689e0bf5392d27cb657c6717040265b9758fc80c76089f4e7d45bbccd3ea38a0ccf19419a0b4fdc371ab67fa4d61ad0a65d1a9ed59df2f0937aa0428ce3aa580a0206787b88e74eabb6174d3720a5c3e8bff7175f074b8799386bf604b33ec4a9fa05a1e6746cfb6b2abc45ea7fef1a323821bd13677353b11ba1d33151ca4c9bde9a0a28021206766ccf6c362a479d78062c6f7e08e87072387ccd3f511f79ee52080a08c30e5239807f0b5981e6d2fc67e399964d48dd61c8624223fb5d30681967e1aa08d0f19316106e736367545c22c092e975fda455f823b9c31452244849106732ba0b3c1912d57f95fb60ee7190553df044515b9b4a515a27963f9d255727c45139ea05995ea374f77c082f8a1a11e172d689579a24f0b30b09b9afdcadb288ccd4bfaa043133fa8e729d429cc930c42f073ad308b68fd9feb1621954115fa8b7543959fa07a166b74bcb18be0380ba88fc09b516815e8cbc1b7a2f8b506870c71542aa92480", + "52abfaae552517380d3072cd87ae415f45305f4d42f8a4918aa91b76a496aca4": "f901118080a08d26a5e8227c9e2ce48abc151012518cda9ba6b875e3a49b66c48235058c4921a0c9928efbc5442307c3b51d5d1c20a78e8d543a6362b7142c266dd7aa46db917ea0e8fa101db8a9311808076e0405644852e7a45707ac57d79212ad7a385496761c80a0ec7101039c64a4cc3fb093df41d6effc8ce9e91b3ae14b53043d91aaad5c42e7a0b7623015aeffb524ededf45dc702ecb5e61e4aeec17dba39e5e8938834cfaa0a8080a090f0d3e9518598dd6be5b14154b228a886ccd347b85c6608819ffc9caa481b0080a0e7df9e922b8f5feca72dab09bb086d9a3cabf0cf03e4f95f9c7b9c57066c66b48080a05d997e56d4be69a4f4db0906e03aaf04db963faca8b32bd1717e119cafd6910280", + "5311b8f01659626cf832f995300b736c1bfc24a43c72d2922daa0fda935e48be": "f90211a0c5c139fe2c800f05b95ed312443537c69dcb246098a9f16186211c84c365fc1aa030512ec0b6732cf6613547257201a09f917ccdb14402def14a5c32f3172f85dda0263cd07ff7dd1cc508db2539cf3293f9a2d01682800edebdd9e839c9d091f25ba08db307c8372137ac750c62d3bb1e34451f71974f88bb34cdd4c13b5fb78d2ef7a0eca20a151ada80499afde8ae740dccb0aca77ff53c3c1f6fd5b767779c11dd19a0dd7644614cae4a6a8ec8fab813ffde552ea3f67d37fa39f1511c0ded6be299bba066217a22a3556e32c90887c25445c2668413aa9307b8544e17707f868c3056cda048c8682b93c11babf440c77f107e1cbdd2f0771980ad3417ec12a9a58a5e12c8a0064f7027b911b948fd2c75da2e863ea0eb725b582bb457b17c239e4b3c966007a0e9d982e035d7dfe79f2725ea924ec35b8cc5fa32f21e72554ad4e597829d649aa0e1081ea707a660ea5d33210344f099e8643835d1d5ad69c708696b2f56cc1069a0a8bc8092a8bf6f29779e58169ef45de42537adb401821685aa884b47dd51df83a0e9fd09771895386ba628f7c3145fee467f890b5ac4d6518b9c0182e6a91bb6e0a0812d44f57ba1e61273564c4b0545402a3767fe782000494419b2030779b30042a0018e7df5d6e71e975433a45ee39a40099048f924a69a364bffbe29d05fd4c46ca03492077ed2d7456600fa1dedf4cea038b38cb4b12fc0e8d7fc71377b40df717180", + "5386c6fbf5d564afb63b718caa68eb7265a74d6652dc7bf7aa33fad554407457": "f90211a0d1044c5c73457b4ca87ded35848516d95f8e1c3bb6afff915b2c2a03606c27bea0be61a3cae35934dc9b3dd7f92b15a2ec50a58d9054a0b4d8ec40c5f0182ad7f4a0ed34872238341ed7972779c78db277f3360126021919a1c9a5fb0184cd6473c4a0a5e7f6d696b0e680979d1db5d6cac842abdc860250167a14de6116c11f223272a022390e4a7df22622887ea7abf2a7bb069704f740d8da84f033d75298a1f15af0a0f062c3411c41a41ca06a0dd2b5aae5fe7b8dd70d8f4fc8c7d80e039887f54b70a0521ecfa38da1ba4caa12b09836b3222987ab962a324654fbdbe3ad87eb998fb4a02603f2dfd2b20d5e793d612a264ec42c6b710c4b8f0b6b345e965a3b6a2974d4a085a48db8eb906dacf6c799a2ecff6cb150424448446d62f21c50145da78edda2a0e6ee1dad9b150ffb92036ca07454c4fe9660929cddc386918ad5ceb68f67f1d2a0e819034f8b6c3b1511d60fea5335e8a1c8130d639258ac8e41d8ff583a46bfe2a020530e188d089a82319e4f58a49a945f7482a7baeb37acd19586da0698caec7ca08a4334b25721cae1f3a70dd94bcbb9058b6089d5e0e358c0da30467499139c9ba0e8bce9226ef9a6728fc172145131313760b3ecc8a736e741c1cb8c2c250228c1a048122994102d40472e7d4808ed477d376c4993ca4de034de9cf56a969b779018a08b14ab82a4267fe7875b5dc5ec90e82da9970d4cc030f4a95396c632339599d180", + "539bb6abe86c897995685b00b9499580a23ae7733456a9320092df93f20154c3": "f8518080808080808080a0beea111a520072d3d236e49da3637088a4dcd4c5c36c5348c55f9b4516aafc86808080808080a0622becce00e4bd7e6ac45477725b9af58da4996f36d60ff591962f487beb712f80", + "5494d18a48ebb156216acf5b113eeb52dd3f91e61ee626e1e415c4992cb072d0": "f90211a0e25c2b7149a40f39072edfd4138aa49cff6e1afb73ff63d620205e9dd9780e2ba093f3be049bf3b4284e29d4c9267db5645a48c08837955f37a90d9a250cde9c0fa01f87c09a84e529c99fbe03e65879e892862acfc8a645f21ef754b9ccf354263ca01ca5361dfb1707639a2bab72bf04acd64af0910a25e807a99607fdd70daaad73a06fe3883447164aeeafdd1cf3d5db510487a7f34e875e30ad94bc5291acdf40d7a0da90fa36b0960537b63d219ad17a84c813ad55b7a7dc56c579a684dcb30745e9a00c8ce2adb22de0f795ebbb7c1777fa22bafe853acbf0f8289e0a100f61e29fdaa049ce358613feb163cf981acd5b03f88bcf5960f2d67d42c22829a8991f87bd20a092fbefd5c29c5a48ba8f1cd54d61c7950856c1ca65c1a24ef290729aa5ba5f97a04ea31bb6b8b6bee89d2223fe917d5b296e3c730caa3c07542094bbe26a0e9fcea0145820cc59301cde4af3f3326b663258b26305fc8e76313ef096fc07c3d0433ba07dedc5ddc6c8713d9d45e35981ae25c45006357e89d6cc7fd4395e94b6ebd627a0c98f7908307a282142397708fac6b55ff00a57fa889e3cca03eeb5ceeefd05bfa0bf6fb4259da9400376a4b223a86d24aa714abcbe76f20408fb8dc95030ec07c5a0d3dc523d6bb01eb2747a17841e44b49d721caeeadb8d152b25bb2d85c0628527a0f61ebc0192a353029eb25f03fef179041e081ee3c958d285208734a9d0913ea880", + "54b5b7a05f312eb11239ca33d57d07a7a8c02a090298187795104b4fc3577da5": "f90211a03fce32647fdb83f957b74f1363b6f4349edf5f96f435daeb6637f7140c85706ea05784f4524b0e6fd843a7692c9435579dc0db63dd6dc80bcd34475539156b098fa0093d1ef313df98db53af4dcbe9dd4280858628602b19164c106a146fb5a19b58a04b22526e2f06f4873eff75124b6b29db64513d9054ec7bedf1c88fa665bd6f2ba0e6517b1c04ff2f297604b90dcdf2d26eefb5b6c183e23e47a0bd1a98f15bd462a087f54a1a156eea72f3dcbe7f54a4f3de634c9e84f521fec520026167ce42252ca002ca2e85b40bf909f92f85fae2d468ac18e9131c3b610773a731dc12b8271d07a050a01e95e440f59a4f30ce13ff7b61a0b8e4579d56764b545180ae4d81ff5bf0a0cc90cf094d5ae1122de60afe18049d16b310c979a8170a07498d3cf5e19a044ba060c56f26ac1db7a4c15ca253506ce21c8d6af1273fef8f5d15669902cae031a1a09dc9e6d32abbeb4425089405ccf5b0793da68618106eb5d8b114b09ba70c0f97a088f363f76e2e0a423fec25a5e7f0f72ab234776d39f56edfae7711fa7abdb968a074bfbac46bcf6c9bb6aafe10080c70327bc61ddbb82c39982e0b2e0f12b04fcca07cf7826507b6e95659296cec1ceae75db3ceee278a7aa0c0936b83bf989675cda0028bee3ad0dae64208da16495a5798421175da79db81f1523e134655e6ee7c11a06c624a61e7df14cb75a09a4a7bc4ac87ee4bf0a8e5a72323bad4f0690185d36880", + "559b18f4b2bc206ab507131fc345b00ce8e02b659d1ae94d6235e2df71b03ef8": "f8419e32800a1213e304232efb47c8e7d833b6fc73c770da17ee5dc21f52e1c33ba1a0cafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeaf", + "589b2230042938899c9cfdd0e63d41f8623b07e195033477f127e1ef38efc4de": "f891a0439d20d949a0673a672050afa2f2d162ea871d7fed46b7866d4e889a6f4d21dfa09bc7d67116e54b7680af768ab4911d6d6de7902022362bb2143db522a4c61fc680808080a09a201772b848a2731ed6c7ec0901c2cb3607a9bf67dc92ae651e0418fc81d8f2808080808080a066e6e9071c5f5a89d8b19c971bb89333e64747d2bd34c72d0514be3b76999007808080", + "58c7147ba81e83310642bf04961c3c86d78d8083b0b61b0de364ff7806bdbfe0": "f90151a0491bd4684c746d5c0c55b4c2f765dcfe7068dd484824df57679324f15ca1962580a0ba207f6c4a2b8aeee05c1f07db1090a24a8400b12a1e4abafbc7e8627fd3a08e8080a092bc5e067d52a5d08143fd5d61d007221a3a438174c0f80638b417fb082a64cc8080a068a58599246028ea3b7bc22cc257a92a4c9d93a7b4300a4f9d50f7996fba68eea08c3b7c185ce814cbc05b41720b9838f3dbdd5ecb475b4bc09af96c3453a03dcfa0c3a8f345dda4482ff164f60c90de6986a2c109e333a4c88dba3c3a5affdf4899a0855acb118e7759585a74f3be53785867a1ab3b80f7b2a0f2f1060d09f4762f6aa03b1823567c9d2bbfa40d868b1fbc6cc50aaa5f68b5c1a9bb18b99a3e9c8601b980a056c63d8ea16d0ba4ff3203b2231736716d18136df900245ad194ab2f4cb50c35a050b96b28421a43b9581f62e44ebcbbb8a0d600e0de0b278944ab34f08b684c3e80", + "58e24a13e84452e9787f65cd823850a33ce73355794e9b166c4d2fd4a1375344": "f90211a0eb5519d63a3c198af4978ef69319fe72e73c747d74dbdf1e4210070e5cbf300da06f2f5afa81f9ee9f8a6173c729597b9b2bcd7de9d9c3a6953e74e69bd0600227a09338b3f075f76948e5c950ee173a66497d6d78cd5b62f665e103aee9c6f9f041a0daf85ac10460b918c58401187ac8abdacf2c48f928e32717b0ebd8ed18f9518fa029dad142a0454b0f7547f17eb674a47a413352831c1c03b4c0494ff060021380a0611f3aa464a7b897e5358366cb7b72b6c0d3bbbdd2e82bf31ea08c802867d92fa068da8bac885860d34b07e3873291f94827b6936913c13d001b713359b86eacd7a068b6e4f27d774e94a3fa0b459b40f871a37c04861c86193bc73b526d5a52ac85a0fc020c83d11c3d97cba4a9c3bc5b25c5e8b2f23b8f81844568f640e6127d8ed5a09cb38377affedaa847f00cb59fdd07e8a643f0beaa8320b9f0f4662afe91c9aaa0872d835f976505a1b621f207dc3c7bfcb93c59d001a62d4b5c40b2138f4dc361a094caf3b5d84a74040ecba1fcb27ffa101a25954384f51e6b6c9425668e2668c4a0662757e4c03dc5c51f08cebfd6689491066c8ab88d8b5fe7541510cc8bf8d9d8a084c3dc717fa59d329f55d5396593f4394590f7fa91ea71a52f787822174eac5fa0a25d976773353f17ffbe2698b79621602af32d546276962b4162145951b70b2da0c1489d10a0c6aeb862e253c543a336e0c8023defe300c927e801b44491e084e780", + "59d47af9c489bb7e4e66e703986f385ffaf8d4a49b5ed81562d84bbfff7e88f2": "f90211a06587e0ce70c271162507560f3fe8357dcd9abfb922970ea0112773b3ab181ae4a087aae9a9a4190a9df5992b87af64a5fb689ce7241250a7ab13c0ba9fefd0d008a049cd353b63ba8c2de15bf0c6a698a30d62184cc9035c9d321af1533284cb857ea04c685b56e82c47ac7eac221a0aa7f471a00eb13bd534e243e3d361c6e636050da021f919bc5dbcabfade5deabb5aabfa25016b01714207c3dab7aa5d313a1d8228a0a2be317a29a338e58f63e18be36197742b1eb56d5786527a588b25553f8ab429a04539385b52397edda383f91cc5853ae137ed91919a6c6dd1d1842a690ea45065a0e2132382e995c7150086a0148b106ca87c28aa544181274758d1fcce0d65c06ba02d3c6623d5429802bdb571a7c57f42c9a31f6e94cba541c906503c997c505b83a0977c9ffe44413eb6e390cbe0d7de17be6bb726177e64b3a0aff0e60eef3ac8c0a055ec2b071d2df26782d0ac326cfed5a2594afc9182e77c8808c1cf27632cfc74a0b89321d9ec2ba39e9167137be346dbe9132f8d3cc5a025bc48943b11e9040679a0f9731da5be992bdce76170350f290d9d754195f3926fe8b4b65d2f9c051e9a1ba04fb7e26a66fa75da7b26e158a7c003231cace142c8fe68917924dae2380fd1f6a00c77001d6d1985ae2510982321997556e53e955e662c3ec60cab494de0edd6a1a0eb11aceaef2407aba6f846702f2795ad7e9182e1fec9344943ec4f4a2f89985680", + "5a4100b75834827fc8a55e32abb5fd6f5aedf74d5b1055c12743700fc7a18206": "f90211a0d3bbe3376b92b6322993da253aa69e39d9f5344732b705422dfea87fac649f10a0a29b4ae49fbe59924168914fbd82a6c61f6fb574aa43d2afb6f8159e111bf5c8a01cf524682b827b31fb2321c70a969366763ddd8112753cf0193a69c3d600462ea03c2c6b6895188b04b1601c6c70ae0ddb9f2e1c1e1579628e16855fb95c6e56f2a044925a8294aea7a4e269d3ae853be02d947504b8389f611a24fb6cb7c7a11dd7a017ada36fb657646e324fd8a3eea0d387e780c704a7f305107c4bee533423450ca0b47716d1d566bb445b41cf129322cefbde28de6a7d98101c83cf481e868c28f2a0f04c1b30b08d02fbf08cc17156f930ccb09938832607b112ba09c1cb64cffe12a0c05abe971fb1959f86d3d8b47ab6c9ccee955a19c0ad0316c2c1b403f9851530a0dc5aebcd769c01a865da8e5eb48aef9c02be17d9267c207bd1a105d6fe3a3706a09fb728eda131abdc60edf9c9cf4a00bf535bb3c913217c2b43bef5731a2fba52a0689fee743e2e01a9a81714d3524c0aa170a4163241b9c0061fbdf66aa13ebf1aa0548f261effa03ac90b56b7e970d3e3c9dad33cd9d72faea04b284a0f6bdfd866a01c9948d151b07a91d407ea823084052c3f4f78c564b6b3bb38ca75ba007db55da040f59a3dce51501a8b5afd7e222e4b1b3bdd9429cf3403e5e791043d8c7b532aa005a38abb278959fea63fd4452b436c83e402063bc493c12e6fe56fc0730993bf80", + "5a917fb3dbd9dd806934b82b250f1cea646f4d4ec022381c97e0a506b4c73b1e": "f90211a0706add3c5d7bd3dd79a7e4ab0b5203f0c32c52181d8f5fdf7fea4daab87c6b6ba01c70928f08cb19eedb842436d0013a7b8b013002c9994602834bca6a7f581f62a0231c0b517e77d1c5e743e8f6a81ce899a6728cdc4b187bdfb2d6bc005b547c11a02a00caca7e5ce0d6eb5059d6f592cedc5703e2d6a5d99ac078b9006d3e5cd24fa0aa16b58aa281969af6e13987ea62cb2df75d5b2eeb06ecabb681ba555bcd5d9ba06ffbe55bb2478df414a9eb34102e28e931a52b168f06cf56b961112c0265ba80a0f48532548c579ebef79f3ef571d6e03af5946fd51b2b9e1217b73caff101ef68a03b9fdd211b405516a2d58d5b9fa30161a318808b79f4cac8783f1a80e7669fdfa0feaf7db50a77624ea0fa9a52bed67af1e624c342a4e1ba6e67de936f7dc17cf6a0f347ed5e8da4b5a0be39dab68e6ac20c742dc73a5c82b7eaa2f7ff61646aae4aa0e7c7c6621e55803152021a4147dc4a1928fa9effb5abd23d3baf1c9bf0cb0ec9a06e9035aba6e69156dd5276b9b6f7017d872047a3ba65e2afa397020eb25e6ce6a05cc5d050b03eca4d5c17f120be6cd1dfdd60008e5e6dfb620b58a31e496f7070a00c3b255634d85335fed60e7746eb2d425610107489150291e70e8627f5106e84a05c78250455faa148c2cb9d97a3c929cafa3e7c0816b32270a6535e41bd26018ba0e9dd79c8801ff3374c753d9f652459fff720af298a8b7914623265fec3ab994480", + "5b3d2f49cbb9d1c5912b4427fe5c9093494b1f51742491c68908435be7f64a7d": "f8409e3507912a1fc64b16e527119c3941d64e6c1a0190e0b9b5bcc3679de1e5c0a09f0ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135", + "5b8026fb6d9565b902fb36cc76a2e42520af3cd4647823dd43b821648adfe5c2": "f90211a023895ecff945cf18c67ee281fe470ce88724393f30ba3f2bd8d525f21f735b95a012300ca909454407a97d6d0ead7ec82789cfe61e59495d9d0c547de291fd9ec5a009b90b18ef6c3ba0d056d6f4686e55dd5a023f211f4918027425258902b1deeaa096387968192aeb51b9191930d662ffa30cb09265ba770e67762869d934d94505a0a5a23e921964fcd395f822cd13602463114cc8ecb3687d554b9a26639918c193a0cdda3b2eb952a9ab62bfd102377d10acaa9a3bbe5fa840e250e064f1e16be525a01f22c169b9f4d827c0d5e6c63cd9b1af2d1eba6e7a5320688c7f7c1c17a33811a01fbcc29eec852e0a5f45aad7a2bc7423626c40f130669a8724dcdc30c82a7dc5a0e6e23187ea2558fa4176653eeb457afd7786ca98a415b9a04872f15f7f48466ca0917aa551f69402acec8ca30fff4700b423eea909a5123f105f169c424154a6fba0d7353ee8bc94bc999e2a11e432bcf8a4d9a1e068f5e4d57c29e88306e460936ea0b79811242d6b5b05530f5ab13df4ba3288c729127a334da034bd9f8e21b7f4f3a0c7295f55f80b2bbd067b646fc228af7f24e2c3a13c24278e3b235bc7db4cf2ada04ad57bf11f356611e732b326b870cc58d5a9f83eb6689f3fdcd61ac21b3ac53da0a26117c6de217cce807c516ae7dc07438e7dc00035a900f1269f169c57e46bc3a093edb0e17d36cb5ed7c303efa6437a6e7762b5a8e748dd4aa25d6aa84a89c61680", + "5ca34b98fffdec21cf5e17fab7472fd990dd7a21f47b7e2b1477db7c6cd1677c": "f8718080a0077e9d8b31d0cca8f6c1173321c3f7f544a948ecc722a7d9347facf76d0c5f89808080a03c65e781ed7063e63eae50321fb0b3a97542ae989a6503a0f6ad61e0afe0b714808080a031f8c65cc2123e5094b65902a4592ad4fc981bccebb06e1f3b5679d380f6f3b8808080808080", + "5d28fdfdcf1f717f9306d8b47c1f1783fb1145865430f1c81c9564886ea09f62": "f8d1a04ef8478a52dc8bf1a586feb63979e45b030cbc9f032bf6dad837571ac825f462a0465595e21639901aec01b531e32ba4242c654c9b98247b19501f2226cedd90d4808080808080a00061d728d5c92a4c9900923f5dc512bf5a6e826b0b39691cf7116c57807601498080a0aef8eb2aedea9399a5dfc37e8a8af79229f3698a6fbf852e422802611464813180a0b7301a5693321394c88e56fc8f05f471e0b4529d5947b6afb9d2208f53fcbb0080a0aa16118293f352200f19021d58f11537434b443112579e6ad36ce374fa40848480", + "5f70bf279f3576da619dc1809a9c2e5e114e96bc774109bab9973557c138315a": "f8409e3cbc140ffa848297c614161e8c79ffecd6f41f11a82a0e9e62a249865113a09fbab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaad", + "5f79f37df995cd796c2c97ed9420e68bc83bcee92d36bcf79177733982697b75": "f90211a01453893def0532a0bc5efbd0c6022910eb7f755c0a7017dbebbcb8c611d0ed5ca04e4490c5eb12a9f9d167a2d6a2e62660c542053a2a966ce80d38375da1b6050ca01d71652f8a93211117cf33ae30dcc579ab1a7d654000b10070d224c58524a78ea042d9c4df3a6f6a87853bab7c3602c2345092a081eb3aacab7057491c475a3b95a08ba642a3e29ef5903bec1ab6bbb98f408a6b2c9c86d0bb0a5d750b8b4cbb3287a0209a6c5f554f4da4479aa1bbcc364c32f4456f5ac5d7503a8f67962717cd8425a0e455c9e9c13f83104d5b848239206ea5cacb2cfd5e04cdb6eec0d869c36fe076a04676c068b78e3c1fcb50caac9dd0076a7b401d4d01c9503de8664a29bc22da24a01b7a118f30121123bd4a7b3d1342ed48108420e8b8dbee33608f970fe4f84869a0407826ea8b225304103f31999bd42b1baaf317a32ec763b3136055a6e83dd52fa055116cb6c19957b47aa2526250ae02b21b979ba8fc7d394807a2af9cad87fe1ea04d588cdd79e60140281aad9a52272aa7ebf8af282290b23ae22c39c9a20aad12a0ad3237ad2f7a197dc36506da26f684c85d3a7a745dd7d64d067557ec5f47cb7ea0fccac1597dbb9c323776eef714bdc7e013d0abe2d23de672ee20f1eda5846efba0f91354ab58a5db0df65bd0ba6fa05163bff0902bf84a493bd449e9c6f88d33d3a08643aeca1de63acd548c24d64c37ce0933e6fc73e4c48e35eb6edf3a9f0c03f880", + "6054510ea248ca03e66a9c30451faed45c5d72fd8af1eebd88ce6572da505ab0": "f90211a00ac4a7c23587a9d868336e2d81f876bb02da0a00c0cc8a18c798e0228d271127a021abcff76a755696a8c4540529459db6e843dd95fe69a96a02c2f168e1c5a30ba043047d0185bffd48f3d0f12cb108fbf3a37cc680733431fd020d80acc86c0941a081c1b66fb93ed3bdf7383080f30d1e46216238ec4e393a36ef1fd5437e2c4ea1a0237d2c203ff8a97e419f8ae28707cc9e790ea4f6ec9d2af6695003ea9bf662b1a0ffdee49c5a0109eff7c53ce7c254ace02363105b9a17baaca3db3f8b0949f1e6a0f118c6405ee680ac2c222ff2368b66c87460ddcc033897df266f95cad77b7997a023ecfb1745dab64561aa6b7d1578d55f1de5deb9e1030baf4247a51f728bc7dda0056bb7f5b1bf88613fbf745bef880e6c9d1479206714198220b0d376519f7802a0214f83acf9e1544e645f554b4de7ad61cf4463e1d404a8278b1f493924a3d9dba0fe02cc23f4fca279a0f0a849be03e8c9ba6514e7e5d76a7fe80f8a900222df30a0bee118d1db9208378150b3de47a6ab000acd40f5b55d26b82e6a4108320b7a4ea00429cd167a4badd884e89568dbf0c0d32983a0b006d89b3b571ee7ac7eb00da7a0585e15ae02b89629267ab0ff0f7de957b948c68f40ed85f4bb84baed15515f95a0c86a0140e4a86164578e4e16cd06efd0e8837190b7bd16cd6072bad07c399f66a01501ab200855812c702dadb10e90c934c9d02d7869a4adf69f7541362f9d87b480", + "60a9dfb7064ea5340ed5cc15b3e3f40a900c8353a49a2b6fd16e437d05e273e8": "f8d18080a0236a53ac6f12ef443b721d7589736175cc26564bf183635e4d2cbc89cce7ea218080a0f0189b215ca523d2f5594a18e5621863d7d8390ed611a8d68978e64e32a6335f808080a0f3a50aca49ff65b7e4cd6950ecdd24be4b5c2967005c7db9e931b97d2fa7edf8a052c7704cf1087763aca4a6a61d1d2b782b883ee4d914150a886cf8ded4de5059a0c25fe80a868dd8a8305f376ff7e9148640364081caa676849e01f0b7851a4320a0312931ed99bd6fa9a8c59aace89e16af131fc8174648171af9fdf752b35f688a80808080", + "62577f3664a5b2a2157a2bee039da7cba8ec8fe53c74e295c7be5e5a5d87432a": "f8b18080a02624a8325bf9a75a0918e486bf9b2acf8c86fdababae4fc6864b23815917b7e980808080a03cc7ab48175454c18cad5337245d7851a1f26b7e38146a18336d604569791062808080a0234edf61e26809525dd4e9dfe7e9f51f06c7c7796d00f714ba819436d30c2e9c8080a0b1f1d01488e5a7b27f449dfaa25b1d068b2fee46573690edf6826214bf89dab4a0a281c879a3e839025195c8412ba538372eb31752a332b3128a45e492bf45069b80", + "63f85c72bebf49533806c997afac15e419e28275a0e6120cf41d46ba54e1d287": "f8b1a0cc04fd687aa8b045ed3f19cca9570d2156d1a0086fa93757bf288f44738d57dd80808080a0ddac20693a5bd90b652e8d297f43ca7cae39991d7616fd324caf513050d75baf80a0aee440b996fd1dcd3c5f1e0ac8fd6de9e2dfd72ba481b8498b2c1606307268d7808080a06ac202a99af6d72d39e0cceddebe0fb7fe247fcc380dd3dac0e6a58f6db67c6da08a9c1ec1c1d40e30fb0a7f7f043be480842aba2c910e515700dd28ce98a96bd780808080", + "6662e3cc8a6169d6fb3bfc0f649960ab09305e01f9b53594e095af282aa82370": "f90131a0f87f6592db5c93caa57967e06fe9803e7adf2e9e78c5761bafaec0bc32cb9c13a07939779dddaa24b3502751e031877cd885900f1d73c2846c9b48d85e91b18527a04affd7899591ab68d58ae8288641ce4d5135568d2d1d7ad1f058c9a45e647b54a0478c946cf37879a2ac6a26cdc77387050830b9723c4583986e6aa535cc22796d80a0f8952b96a671c10c374759fc85af1adcd8d93ee3c9fa5f7958513447cfc2a88b80a0c01c724de9f3184f28c38e6bdd66ce7582aa110aa452c85921dd3ad376e3f31580a01a419a5ea698f832224c8a64df8f7d632b6b0f6691a20803ceb604b337fb8aed80a0780e7c9ed97b5280b829080a0a7bdd33ed9022d4f7baa693c3e7c1486419af9380a0608dc83fc8375921c398ed4489f1cafe45afb806cb80d64925da6a8338337f04808080", + "67759dabaf844e3b0df1d3d6bf5b938b975881f74035551b4f7c0c1112024dca": "f90211a06c56a3c53cfc3c2d37a3938b789e2810885b82d054b171e7e6ce2f5a47fda600a07effa21f4b435d9fb68013d80d53d2dc58cdfd88b3b25532efb0425f4e8bc34da091d05bd82009f99569ce5caa068a10beaf90e4a749b9772d69ca63f84bc9e6fba089afd1b9457008290ccf0888f42b039c6fdbb2f47df1b323c231e321415df659a0f8e2547cd12a2a7e1829cc60245c5db493740d1e0723202a103cf723af9443b2a076969b0736b6b474a0d2f495d5499f6ecb5bda8678b3abe3900c05340cf93856a0fd0ab259aa106eec091fedcb0d6cd920d6f263fec05d21c225b8a4a840ec6f45a042dc57ed247a5960b118e25263ef52901d0d395f09304d63a0ead917e0aa20b4a08c4ab351daa371f04926abb76d8617ff1ae13adecd7d9154405c30b4acb70af4a0d1bdecf9f51ad6e11360a457c25fe0c05d4bae175ef1e189f5664e0580a42740a04878f25a3b582d86695557c0ef9c93e48957be17c202a26ad1bce0e72c9d1c30a079e89416d2e4a9800624290f6148b0104ec923e66ccca16347b51fc5f5718e7ea0a111b357d8d1a6003e96c6019dde23dc73eedf13d1482935b5628757bc12be37a0ab1801fff9c660a96bb53a4d488ffc8587d3cdd1977257b723d3ff229c3e61faa0082b9fa31a7a5b5f90c153378dedb9e84f66d0e00444b2227184761e2a0ed1cda0b9b52c2b23480fd435b810ec53e780b07f89e1cb228d849c30c6aad542e725da80", + "679881e250d50de7896e20719f546c1cff5d86e1abfc4cfe79283f7364ee43a5": "f8f1808080a0f7d023f162b4864b06ef11e3b9432beb1fa5777bf3639e9d9f7c11d1cfe1f3e98080a0db3a76fe49b6563bb26101bd52e046b417ccdfd2f25de3dcc63f435dd206942480a02ecc984217c0f0cce06f4ce9c70046ed025486d69f9c4d0cc6d43d7b6c141e7a80a00f812463e43922a0e07222fd8ea3a0408e55c7a5d4f888999d7b25228505cc1580a0a73d6b7351f50a8562418933b00d2fc4ad609ab55dbd4e69715d5858fea2118ba00fd60a306fff11586eede21771c7667c48392746d9133b8b12e28b00f8b12584a0bf1e3e52731ad105acd7e687dc4960e657d31b3238a56520558101fb3eb172fb8080", + "68155b38777ab0a56c106b8d342e56cc515da6a3bac1fe3ce202430d605063ac": "f90211a0b2d9099274ed8d90a4aa7f34c8d4bd979c5ee280471d4d163e0ea23550119f84a043f96465d05ed324f23ae33210362af4600f0d0e2ff4a4374b0f42a8b96d37dfa0e724ff4de1b3a05b2746df02918b4d180651a36e6d55a9f3b3b977bbcd4f3c18a0a6951f9c97133b338a0c06b89a304b5d2677f41ca830ff4d6a386f9299e21854a0ac5ec0ecef921f06363a72e5b89e609ddeb83f8ea5aff9a77cad0be567c9717ba0f9fd8484d1e7296dbb97eab2e41cb0c13c8632e2ad93042d2b30de90f360a37ca00bb3cd4edc9f905f387e3e5492793eae344594864117481c4867c57490084093a0f58cc91afc0ec243df93ea02d30106e8305d44259502296b3825e863736c6f32a0d3c44a703aab27a6bd4b7face4b7c9a4ac0ee3442cacb4de9f115c56206f3148a0f4084a083de7f6428b9d75d184178f52fe5343ab62d05854f4a77c8146891eb9a0261448377b90b66debbdfd5738e5aa8f1b4068abf933c22907483684e00d61c9a0eb8d36b40e4a7d73a976ad73f621464649c9b92318faa888929dbdd3c1ba3919a0901cc26815774c334fc1e75ebc15f39ccb1c61e7beb2f61dd2f7581df27ba437a05c862778ae63c399ab0e48696c1b688784a5769df23481351dc18091e41d0601a025ab85e795788ad54af4d292f25cfafeec8b6647cf159625adead509028ed51ca0afb26de13662effbe2f8dd309a5580206bfffa3b79654a3926552ea88053836480", + "6a7cf49cb514cae10bdc567541ee924b54a7cfc7596f22fd07f9973c54ed0f27": "f90211a03a5b71c5f4fbcc2635a9219144675f20ee72226b0d33f4e928a733c46479d846a0570cc553a8b1ddd4e04555eac7d15eb7d7fa611783922ae140b51894723f7f73a075e5928bc5dbc5fb661b4b23055add26b907a86d3ac47ab2139723bbd0131955a08d25f3acae606452ecee2294429b57dd54d3897a01fa3c19d536d079c881084aa00ea7186183c1e1bbd52f8081e54c196f8eed8e4fd6e34e704e33a12afe8e17eda00c74075e3235166755b8c72970c98a072eb74f6759470ca1e0ab6cba8355ad30a0146ed512f6d9a718863942e69a3d9eb76b994ecf19d8d4acda5db08d44a5e4c0a009755c7798c429bc45871e24a525aaa62d9649fed091d557c2252244495007fea0225f34b5727b15c6dcc648ab65259f7ba2c2a8dabedcf04538d187ba986b0214a0edb0fc804fd72117aee1d83a4c48a762d2aa78f380cbf3ee4ea8988750311e67a003c1841e894b2a28e87fd0b8e85f55d6bfe44d7ca98af7cdd07b286c57994776a0a2efdb820295ebfd180faa85c2b45ad9fcf1e10a31880ebc9cc3395defe23770a0d569da6cc43c96b00e79a01edb794ceb882a5460f0e4d7b5b0287dcc1d7e0ed7a0a3523d112e6d4f0b0399548dec5fe9dfda3541d92c5886391c6d11306e6ba662a0786896ae90751425d9872b3b824ea1a24ec84243261b13decfd2e5458b10f740a0f9bd43040c4762eec1816bf24bfb6a11fbc3cc1fbbddb7634580639c09893ae280", + "6a9714986e00640158a455c0d49305d24575160e1da41a9410feeb6b8fae19ae": "e39e37fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace838248cf", + "6a9c283d04396af907812ffa7d28b4f06e332a2d23b4fb766c7b78669e0f1bb9": "f90211a0c46ba0d152f58f060f5979ec848e23a5cb7a3a2b50072bc304e35073d80e22d4a04dce61b452744bf5fcdc491bdee1d98c02cf7fc462505f04c5d79bdedc68dfb5a0bd6546e2d17c8c6ac310b26f6408b8f64e7abf9a0fa2dc3781abf78f6cb24247a04b53ef8c6d1219defbc70d0e02187753fb9d1ba27266e60d7a2a297c4963e4ada0e1dee92014db8abdc10208518d2c0da5ef2dd3166d2dbc599d16795de85b3445a0d6fd685310b5b9474459b59c39ba22df8ac0d80cbc05a81d569333d7c0eb9fc4a07f2cee6d1d7cc4f0dd6b4d1a276ca3d41fa08e6813e61618ad35c968c08bd7c6a0d0195dd5d53e37b510c8c0ddbf4855b56503718e3c6b047a761b8a34567c95d8a07b871e348dbaa1a282c71790778cbd16322a21cee52e3c5ac3a75b3b6f790f26a025092010bd9a6dbc54ea577fb29e77ee502e61383e7f621162ea407a3d1dd32ba0b1ad3b8b183dbc21e4fb4c924e56918a7e55d4bbbc4f738aaa031d46e4cc4c60a0f1940301d48d682c95709a15b38d5a1b1ff9deb46c1b32d1d5e1b5dab725bdc1a08c96459ecbef21ce485c8ac96225e1f8991addc388887f08e449a10b6ff8eebba0452acc1076c8a2b90d21c99d77de577ec00632bc968e2e787a9f316ad2303cdda06702471596edf1060297c5463bcead1ecd28c8ce231f94f83d3821459a2e0402a06f9ed4c01c36e7d7760c984f7c9dd810c95b0dd3ee002b5c1a64796150d8fde780", + "6c1b92c85bce5b7393737f0348e12b829f234ea0746c421e3a48974e4f2a32e6": "f8d1808080a0e41f6dcff340ebcd225054225efcd47dd18f89f40284b5c832c880ad9f22815ba0b18398fc7cf3dc531c3731dbce1333d531424eb82a50127b41cb8b319e716e98808080a0aacc0706c288329ef421934f3a2a0bda0d110bbe551e16914c19065ab41b718680a0e02f618bd92c39eae7b2ed2d4d830de5ac73fd6e690332bf85129fbefc175535a0559b18f4b2bc206ab507131fc345b00ce8e02b659d1ae94d6235e2df71b03ef880a05461ab23ba1709f929b3bce72fbc4322b94afe8ccf55e5ae03d606e5f1e86259808080", + "6c2408f18e7d22a962804d27dc31b2f66ae084c67d724589d69d3d3f70b2871b": "f90211a0e4fe8f1a84f1915dc8af3b800de132031ce7b25318626652194a13a98df6723da03e30c33835d8df0bffba182325d9de1c97cf4d62ce0ce922c636235b7528b9a5a06f1b0f3ccf191ac996f295936455b555647959b3d8fc53b303adb9af884a0700a081ce8f68da8deb1df56f994ae1c027c50366081da770f6e4adf44251e655507ca0ca85a6defa44c0bc164d8a92530c3810e97e6b17883d8fea2db29c5541587c7ca0cc471eade157103c4a1693a6fa2a5b0ad2f143e3d438104064b841fbe84e3351a03692b0218d13481b658be2fbb0ff37ce01e009bdef1e012634a3b5601bb74e2ba05d3ab0ce212f1f0a83536b648bf178523b7fa11df3c40c8df6444c01566e326ea0bff655145d28ee93ed7f08e7625f40d004cce0a51901d615be1e27f2181585d6a0a669addef22ac7767e40d6999b0c358fdf6cd8ba46cd1f59aab787040f8fbcd2a01c556f0ef040bd2cfe5b01113b711720386dce1e1b21aea51e3f5ecd85e4f1dba0c5e4787dac75a57162652d49a6c423a2041c3c1df508570071bc5e7bbe5c15fba0dd8e912bd9dd03b37858cd0a7f76d0817a3ec510180bb99a9d4529e10470d87ea0294330fd8893d75fe006a781f86a99fc94b2429434ebccdf813d43639fc0fcc0a0845a83472c2e6e1a5270d88fdab952090e0bebdcdf593e1a5a6e33d483b09c6ba0146a0b037d811e2a66dcc61ef1d552fceeb7b086d607884b293015c6a0852bd680", + "6fe3883447164aeeafdd1cf3d5db510487a7f34e875e30ad94bc5291acdf40d7": "f90211a012fe117f885ba44a47ead5b2598c1a58355d0afc5e74a26f29702774d1af6610a0f3b1230c6b239ae5fedfbf2e5cf3308ca97a9e7c59a952e091622f4c9f5ae62ba0ff73b73d39984b4482ed458dba0dc2d7f582a51d50bf8afa171e18b42d5ec3d8a07a82bad662fd8481a055cd1f6fbfd0b81a5c5b12c01d73994c9143289e0d909ea0617730a5ecf60470dcd4138e4e7634042e49737326c96bf8255598a0bc364702a0ce40bb6d2876169d2920dcb793dd74de492b1f2d02f83afe8eb699ce0b338dafa00ee4ae9e8b55659a0648549c9b035f18c7d4435fda20f4a513e4304e8ded003aa0cf46466ed63d8cdee49753c6e51555468bbbb538b3aae10da9d7638b745c10e1a0ff9e51218e356dd242d747c8b7613f7f48f37a52fed96ab815a558afc4edc991a00fc708d3e801941d2f5a369019f4e8126d6e16f19880a467e37cef4815af0e18a054cc666991ae1c525ef21f07065005b3c91f2bf8534af2f2f8bbd0ac4afb8fcba0428b081a94417ebaeba962a0b896802eef99e7689365d974cc997afb7d202dc0a031282adde5307e899b3b21d93a54994fcdce8c3a8320cc8fd55b14d270ba95bea0949d42353700f91eac2e12999d67e49d1d07c7aea0fffad02be1afe33dfa317aa0ac2a657ba9337ee60c6bf83775e3778166d0fc6f5db557ba1067dcb0d06885d6a0b01c9af44fc9d2d372cc996c7be08814021f37d090c2cfb446b3dea84d9a8a8780", + "6ffbe55bb2478df414a9eb34102e28e931a52b168f06cf56b961112c0265ba80": "f90211a0baf2b28a6a27cad6abb4bed6e5de7230c71de4ec14af6f53c62d0d9d0e596853a0396cbadd566a7188a2f3da36ca7b18265ab2454113ca0e339ac02bab1cf6c7d8a0cc84727abcea7bf8e56435d797657cdf143e9ed8278e38aa19aeeefd8b65f49ca05c39d961998763557e7f6f2ee04b941bc3416c19f224922398b7ba0a18661bfca0b09acf227040d30daac7b9d258edfd3dba8d98ff71f0f64b928c2c5e3da26b7ba0bdc92e374d2f792469673a0011e76b51a2a39ea9654a78fc0a3cc1b957e92a37a073ed66654e7c4c186d83c326cbd050c441f1282efdc56d9115d97c18d5569ba0a0186f17dfe735180b96c09a84a38098951d5c4ff8d8aa8a7380f7a72577a108caa05d0b02dec2f5e051b314f90ede5dd42052532f3808d024935bf189af11e99a42a028bf83ae22a5f3a1072a4cddb0f14c1837d341f10d1c7fbbab20d1f01cbbd035a0cc5dc99deacf55ac3d75a56942c61df8fab14a7d58ac5ed051c0b180edbaf1c2a05a5158a3b25cdfdaae8f315133337163ea1a0f91dcaade5f38df01a4a4e01104a049e3adcb4c1ef3cf130ac2dde1baf9ec7a0123717a29d1ab08ad1c6eecf7b2fba0fd00f73dfda52da297067f8f8821d95f3d777a2ba14f262ff9348a5733ff7258a0752e7eac9c60a9cd58c59e75e913317c36cea80cadc124419fb4b7e1909525e5a0502be84f79218b7dde943b7c3fa264dd632fdb0baaa67a4093f0670e31e982eb80", + "71229f863681b7dcb6fa1b011a3ecb551db477782a2da44380d05d66e3cb2b0f": "f8419e3cc36ee8235bcb4bd76383bc714e7b0cd4e6e439855daaadac13e0d7c2bba1a00b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabe", + "7345922d5b77934f54986728a7d9f45a8eaa08ac4a8d3748e4ef036cd5d29ad2": "f8419e3e8dc505c565004ff0c79417ccbe0ccb936617507d43642c5da141d0c1bea1a0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce", + "73688f1853da9869f39e9ac69079ae097aed51539b44c9698f2e79fd9c9092af": "f85180808080a012b39091db6c15920e4fa4d011b49ccd95583a07d40475b446f97bbf22015a4580808080a0649a9dcf72af375c8a8cef1d3dd946a59cd674ba3dca52ef6c049fab9e12176780808080808080", + "736890168847fc28b2bb10bac44eb5010a7a2d51da18f0aa2db63fab2e5ae5ef": "f8d1a0af0d17837e8e349faac4edbf0025cf2cbc3309eabd3e121e240ecf9155c26cbaa034fb87e29438a1fffa11b93547e8d04758bf5efb223a2018f23d7e82f89f2a4080a03c576bf8cf3354c18daf2a8a0c2ea1e06ee36bb991c18e478115e2fea70f5785a0fbb671d7812bb1e5b321f925cf5c0feb9f07e6e9c51b74b701dffdafb41b0359808080808080a03b75383d80cc8337be3eb2ef685f24e2270102f9a5cead245a7c68a391f6c6a080a0a00fbe746954dda652f57e0697e781cd7fc9f7ca842c21d57df3f48063e744d7808080", + "736cca1ee36169cead591cfb85bf3193cf3eaf0618a8e2fcf0a30bec5eed727e": "f8918080808080808080a0008c842f7d9bdb97ef01a4ed5a7240f1cb289b17fcf7226cbe90a876ff0331d9a0a975975a2647a60e9a4699dda7a3245d595e7dfd03e39492a03d9d989d0b87bb80a0de5c9be9e7106d79e67cc080b0e769d3b1649501dbf6aed00e26964b867ed90680a03a1cae0f0f4dd1c6ec3cb204c506ce8683d20aac191ac1de5b7e225dbe541249808080", + "74b7181a85d773c8f24663cda8388ac6df8f5f56cf9229dc97f7920ca39fbc18": "f90211a0b5becb50edbd55ed62f7b8440a4a590fb3954f73a76c4991f7622e0e412fa236a0df64e4b9404e985cc0af4cd6503e29aea305e504b59eeefe52703a6e71afe421a0c04700525cd0a1d86454ed97c41757b61dabdd9e2638600a256304164928ce05a081c04829c1a1be727e31a218277cc6f4fa81194ac187bdce597be58c4c95cfb3a0330d05bd50bd3b37e309ad9b2dd9a1f5464b13760bc03a5a6343dc7fccf72eb5a0f4ec1e678469e4424d59a5acd602d45f638d52aaffd744f011000105d4ac8762a0eadfb0149a5d30729dbd0d70ff94bfe45cd757bcb122356ece8aa151eb1e1a76a087aaaeea20c93567ee07ec8360304fcbca0f4880ab6f84852c1659eb6dfe5024a083f81ae990e593ab5c396cd54d79f13658f9e93627b063c96339ed0bda558ccaa09b0329c81f07d2f8bdacb6ca51683767e974f26c94467274181a5fda52e9f873a09e340c711c5e5ac2d33c797c3a0090c6706313e1af8ec16fbe4e5a8aa8894eaba074c3845aa04fd27788bb27836bf4b138b2acba8e83b2238555f11c0e7c668fa9a05a917fb3dbd9dd806934b82b250f1cea646f4d4ec022381c97e0a506b4c73b1ea0cb3dc35fd95666fb836fd4f275fe2f8e0de6b0f4cfe5cd2140ffa7105ed1071ca0a996f0c0f7a430014ab94072688eb7c1d3d6150b55519d71e6d633aea01cb26ba0e6da914f0eb30efab6765c983d587081bdbe7ec95e9633afe1862df21c853d1480", + "74c1aefb3b0dc4105cbc831b2380889af471739d63190e9f5d0303f87fe12e4f": "f90131a076a1cfb5dcd3a2b8b184f28506951ee16435f2a78ae3e58738be444b33d701f4a0ad3aca1c5880013fffdcd73357113ad0baf5f0bcfe82f0f96c1e3b416ddb045ca03543b0ac4269ca559a8b8bec2e2d468188fc05ab29d31f48f73fe7dbab9c5f03a07de60303c5c86b10e445fdb0a96c53add6485de77cd3e5f65eecf08f55a3314a80a09a2d5e2ccefe7e5e487b1a56cfd784d03f4a74ec0cb6970a5c4cfa8f523e79a7a009935b3988afd1ea1babf786e785a8606e210f9b148e8e73b4c7d295dc920dc080a0765736b731e4da2e99bf0055bcd28745f7fd48793ceb69e3b7cf93c0a0046a658080a08547453c9ce3c9407da13d79821fc88c5fe60460c10a8a76acbc3eaf2e72cd92a0644aaeefd86245507c1e26bc80dbbd9b25e7ebc6282a5164a6872d0e290238cc80808080", + "7557c94d2d3164e3e9ff6dbcf53392292a8ad291737332cfcfbfd9732375b7f5": "f901118080a04cd66d1c5d124150b115bbbff434a07ec6cefd54f5e7d8a764007f67c20be04a80808080a0f18d5aa1e12515dbda7d0e82a36c4268ece16436967482f952b8dd673d44b808a045478b827a770a1b4b76d4fcd876daab328be435501c2c21612d3898b1090165a0d1c0414c52ae15a2a4f170318a617e0039155adf696bf6ed5f434988b42910cda0f14b3e405427c60a91dd06294e81549c23960eb99354e79cc050edf05ef4b7b3a0f4882736bb1b9b8df6eb40f5c955e45aff89dec5a74161ba284b1d9102c41beda022a437d8b2571cf4c3d2b2bd42b4d896610cae228573689f17a7cdc26f54f49980a04b2a7aae369a6b3022afd09b441c9156f81526274accb30b7db7bf799c3d71078080", + "755c433a56f18522cd8f0a0310bdb1c4c8251481f9c54fbfd95c94b8de5d6b57": "f90211a056e59523531d067eb78e624e5726c1b6f5fd358da182d9d158e2171973c94dc9a01c228408d5096b0d7981112cb19d091075afae2455c9efe4184c0ce920cba88da0c4940bcad4d98c735a243864a3205f3a376d8fcd680810c2f0db4dbc348cb117a055acb82ee48cec1ccd8d34cae4bbe23215042caf63899eee3124044c3a1f0300a0564b7ebbf7ad387632c995837a6db290e8f8b8efd24eea8b251105b50a62e4b9a0a0ceb26f746c255af4ece54c60886148fbe4028544da65fa85551dae38a88e4aa0d9a4f4fab214a55e00f0023f130749dfc7ca0ea13b490d7cedc4c486ef9e4413a08f7fc94c386df03ddf511d5c895e4fa3907b924b6754c7f271ad09bdb5e89448a081f8a92f1954d137e2ea3a262b951f1b0444253946b140dd3596ed01ba97572ea0423e085028db8ac11f1ea2d782df30bfbba4645d75ed5028ec4142e525c7eff0a05a3d7b5af4e347bd3418b14a75f0ea36f1d3d57c25671353a205288d4b923b2aa0be454dd57476c823ad12466d95b99e10a2839e25200a0ac0ba12a968d9eb253ca0b48c00a0928e1249f862c2f29eb998471f685a5b3cae4e4aec8e3bca13a097bea0d54a8d15ddd0aa4aa4099b33385641530f64b5a61e419c23d628ee0966b1875ba0b339eb823f8bfc8ab8f198d4ed19d4ddb5ce3b41b0c9c0178b399aac76715954a0fd2e8eba75b0c3d5193c7476eb6dd1b3bbe4d30783c6445ccb5e6dd1c5a2845380", + "764ce32d1a586bf7505d0815efaa9dc8b56b084e9c4499e3c5ce98a4081c4608": "f90211a023d1d53cb8ca4cf556363d4e7ba23a359feef8d4ca26478a3eba7614dad2dc54a01ce1dfb27f0e7e91829d6546cb94cedc2cc9a251d0745b132bee44fe1023a884a0dc2262ac0cafe5ca810451e64ce444e7b387358bb84a8b077d504ca4a3ba4f63a09835402d3489035116f956e324335bffd241a5f82b91eef98b6af7ece497db70a04114768837b66885e30402ce3e11e74f8fa8a836538db2f8d8fe5c30dd443e0ba0f294569b57edd4aa3d83bcc69bdd79db5706b11aebcfbeafb1e3df66bf46dcf4a0ac465f2063b68d167cba3e4ee5c9bf7989675f46db8103a38e4e5157fd3bc21da05441a2c290c22aa815ac8967d5441a0d9026d6dd9d0c56dcc8b5bdfb557545c5a02a572fe4e0fe565a49901c166d61f65d5d23852cafdb4b396288d40f0190b54aa0fb79ddbf41bfced108b8090924fb4f5894b94bc579b72187285659eb3275ee95a052786d16e5414adda2b603890d2b94dda36142d19d02c6b114f57f1a39aef5cca0755c433a56f18522cd8f0a0310bdb1c4c8251481f9c54fbfd95c94b8de5d6b57a0aca141351b47c5530f7b23d4bad49389139de7392478a9cb2d4c6f031059cb64a07ff8aaade805a20624e5ed35cd0989171c3ad04f9178cf730c2d288e0507787da0abd9d3ec44bc5d2068826517627794d98005456ad6c30e22eb9550c6e1a2ddcba0ea0b5fe9a84ac21f1e5eee73679f9d641768a22cfa95424b5c43cbf098d19dd280", + "784141a1f17e9dfa79ab10c48df5d167645dfddb05daba0785f001e58284d2f6": "f90211a0a2b233eb5d444e7b2141b1f335683e2ed100f32f9b43787b5ab6b79366e5bd83a031f0be93927dc594c89d24086484474b4fe8a67ffa3d5a9e7a51c01d7891d9e9a0d8d738e127563eb592bcc2e492981e2a54b1fc2a2eb8eb1fa83158609828067da03e0f8af9e9c7bf8d1a4eed4ea541ed39e3350087a366ada761e32f15c838b066a0204df356bc5041369aac0c46932c406c1cf0e2f8da6f279ecccf0f8fbdb33c13a0d0a43bbb5eca93be28654e3169694b1a4b3ca98da06639f91b6644123613c58aa019815d0e795674d61df9193e4a1f87d6b91a564d57525c02e0cacf2a7c71ab63a02d6d8e4a0ccf938d5747bda9f93f901ebfdbf2b69744f50db346de84375f1bd7a01b48fd9aef0e568a338d2b1ff4d78706abe67ea2971972554926715924849aafa06f974400990a402e1fbdc6273901bec7a7a0815bf2207fba70a784d30f781a70a0af280be0be5b6bb8c3272a3acddcdbdd75e4615c2c3f5c7b2ac4854a1fa3d0a0a0d1c498d35bfafdfc1b86bfc79afaed0bdd875383cb5b105cda9155dd1d81a408a03595c32bb80a00b9517b4481091141355ae77e8a81811ed751db9be5f699db3ba0fcce16a42ae730e0660e22bfbf4501dfaeb0c40f28e0ab6c278e1adab478e170a0b082a4b3dbbd0c45a33c0af47dce3c3b7f2640c27f1f73d5fcab88dd3b066171a089a7f1ae49abc818fd35783e1f11841204a1eef679ab0b1e23887157aa795b7d80", + "7878f4859c33a0ef095673ef7b6a818d7d523cfd55a051fecbb4f6aae77e42a8": "f90211a055c7267549b6e3171726d8b1363c9a8fa153a8b575a84841bded1dbb0710b3faa0bcf934f350e0309dd0188a7077a40cb42afbf169c186231e88114a03d7c13181a0342a51013ed54e26f78f278a438a9814b054d0273306bdadd46783be10c6d783a0964bb24d9794848c141b15ee8f05c217896a9c8c443160e7855b3d4a96f50792a02897010cc08a86c7e5c7f73773412002c57379c020501109651f35be8d46c6c5a0027152b5b413260ad3aacac46b0b9f0ead1c8a7e51ad040fafb61e97407ec45da0f256e8bd06d5083788121d2115e6ae4ae4cf969e5b67e0e23e181271997b63fda0e0760601147c295da27cd8936fc25bbdf4a288855b35e2fbdfc528587fa4e6a6a0eb05ac041df17cee28a856dbeefd9e220db430eee470ed015119def96b2bc80aa09586c7a2665a3b38c3ad63e1fdb0f48e7144ced71e8ead6e1f25a2471de2ec19a03626920647169f7ad3b7134095c839841ac8d812369b4bfe5f65f40600e720a8a0fb49cc6e4a739bdf6cf1f2d159485577383fc7289a29dc064985af915dd207d1a004ff10360efbd23ba2c1d0a25dab9f8ff7f88a6aa545e294eddbb3a3a8879b91a06a552338153b1e69b26046d44c2dac9d6dd310a3f8d211d41fb186b2711f29faa0989acc32d5a80a6135b90f65561cea67082aa560c69d5b609e27fc02d0180c89a006148280c6df9f5d39b7e6c687b4fae70fbe889b8c3069e3dd79b7a2b94ff3db80", + "788431d02e7da5d3471a412a4772a44e561e2ed990510d9a021ad715978245ee": "f90211a096370a289146721a3eaa479da457333f9064b77df0f9fea7a74794f128888f98a0976cf3a85a039ae53fdbe2026f90aa5a4faabf723623553b587cabe880f59c45a0d2ed7b116efc5ad7d400fa446ff001294dd9af31e8ed3a0000ef4eb59bd3c506a0015d270f3764bf8ae4eee0a546ac8ffd49b0c9ee885245df980a0c4e182563aaa0064ea4a6dc422bae4cc451cba5206e1899e3ebc4db4c837ee964c3c9d4f083eca0bd5f777c97d4551288facc0981621537b48117007664335d380576c77323e177a0046979e27086accba57edbc41fde47f6b531a8f5f1f8b8c01ec2ba1c7ca15638a0e17427f1c4d2e656090a325a3cc1b3202b630b9be971ea1650bfedc60a4dc0e2a0514893b7f39591ed78724944a477d3156d7987ca38a4cd5603089c4c432be4ffa054d5a95591c88b693c68b066ee9bceced8eee12f74a384ee539108f23027ebc0a0afa2abc2141448a5b4b14e98d1909328965249a400d7b26b9965c5c4d375fd9aa09145968967b9837513ec76610f58e9a2820965e49ab639974d32a9f8033e1949a0ab497fa5f0e759cd565fdde5cd5e2110ca598b8da2a411e9fdffd3383ef608ffa0554a1a759b5d925d17d46008936dcd0e6f0af04289d221ca63f7875b1ab7ca34a011dbf4aee265f1cc415dd77e94584d08cd9fcca80c6d776db6f8311adc281904a0a042b895ee1c8f0cedb1a3254aa29e7414aebf82b74256ca8e5d247b3cb3228580", + "7ad75d94848616268aa277bad1582dac2f26f94d028321e58f532dc66369f602": "f901318080a017a75f7eb25e4e4195a57a01ae89d4d0772056f381f50e3072612929ca659f0aa0bd89c4c660ae2e5e8bef949ac76130268ffdf1ea660d74c142ad82d4538fd9fc80a0b5f08995ba21a777f717394991cc29e0a67b093c56e784054f27374ab4f7c689a0c273b8d88f71529384131445e3c5600114d6eea9c34229f0a5dcaca3f0e42ed9a0929a9ae10229a1a16bde3c9b9d67152f081870419d8bb675bc89d525a1085252a073f72600f8263ed5ee503f36b588fe35b53afd44490a74977ac477ea3c3b384a80a0a6704c6275e7c435e6eff666508e5e15eaec072dce82b9df229e950c8d757d2280a00c434fdf46d9fbebb3ca3aebff154dcb112cabd9303e4e09fd1488f6bf07bd2e80a03414f256221a45959f9fad9c8278a732f7da0415b785fec3eb94da733ddf7c048080", + "7b44c72886f3d3e96f257d1265972ba9616177b5055ee45835ffdc0e627d4ebd": "f90211a07acc1b5e0f1b6dc1e1894b60bb6cf50621054545d8c1054d23fac917b335100da07878f4859c33a0ef095673ef7b6a818d7d523cfd55a051fecbb4f6aae77e42a8a02e176bd85ddd115919c1a12de12d9a38f1c1adc3ecc27349f10761dbcf4a47eca089a00e4bbd52e2476308c9e2840f60fdb3ec22b67377bc29a99547ee8def5806a01ac47cec70bc9207cf87911d420238cfe9a5411a4aa8edf3e87553c97260f33ea0111f842c3a5577cee4d5c1e0955c79ec083ff5f54cfec4c6a5b8f1090afc354aa066300055b6e104999853c24523cf18cca94bf832943a4c0250b7b758e7121502a00d041f59f32422f13840abc96cd49ca3be8cd0eb60a761448effb5a9646fcb79a07a18521ea6fd9a932341c9c474c068bc22c21cdbf17650f851e0982263319e5aa0c47a42fc07fc9e984ab0ee07b7d6ad984b4365b78fd90f17ecb32030c88c70c6a04a50fcd6d85d0cd18f1d9d4ab83c6a3e4070579b50793a96059aa2610bc97675a017d901df3ff12b3fc837d57af2c34751a974d52001512fff66a9fbd51fa6af46a06ad50d405c81b9cf58b427ba3699fa3d6f8f7013a866ff2280cdcc76c8cc2ab4a027f5f46aefad128ca2a1d0d3e6ccc1c9aa28da7a3f64231d276554eeda5b4c20a0e33c449672eee5fcc36b061665f100b55ca6a77cdf5c75a36e65bb7519ff0c01a069025195a19b2726d66b77268618fa69f75d14faa4eb8d23ce77e010053366e480", + "7b9864f4d865fad4c3c4e247fb0b8d8abb6164c25d12d7e64ce47f6cb5c0127f": "f90211a0f94111f1d84fef29de3558c85ded6e0c16ebd3f04a09115198b1e0db52c5024aa0065a6f0536087a23fb15a438f4ec64e8b9d9bc605b257be527533636a8d9aed3a00f483a6d0f9ccf7acadd99078376a7d65b7f67698bd0b3f6f573cbf06d291ffda00a073c71d1e1fb6846198ec5d93aa007018cbab03253fc9535da55183e1b593ca04d54be375ad19482a470e53530789671f174c77fc3f23ff11ebd24ca80e77ac1a0a463feebfeb38eecbdcf3eb2201348ad1e06d6eac0d1521434f580fb3bec757ba05b6b362a57f801afde9006fae514c9f6334caaf2e52fd7cc2d8bcf2d243e9b63a0ea09d0da17792075d7b128a40ecc0e1c76be7f544a17033b19329568eceb91f0a02b67b0f29076310fdf4427222b304420e63b4ef49bfb764585a7a72a6c734582a06d86236473e8839f3ab311ebf07241ce0b33418f57eac70a37a87400fd3ccf00a07ac9ebf3fe5290c272f7635d094efa03dd90e52d083e693dc7f12103595f5fe3a0317b5edfc605e415412f22360ae801df9b034d784668b1ee8852bc9f54988098a0266d8cf6014aa76f86e2fad4f6eabf7a02555dc00a0410d663db3f67d6adca9fa03399e0a85edbd48a6b8fed99985e9acbbb3390d0eb21cf646a1b98cd9d4bc228a0b6b809a7bda41fbe525c9f19a6184e565a7e7bff7520f4f8ded00cdea697f833a07931ab684cc3568e97dd9cd4eecd410a08e1205ac4c0c58399692ef7e0ef7f9680", + "7cb69b6a8383d8995ec6980b2bc70d81c3df0392a01cbff4d63734ecad5535e5": "f90211a034ecad3eaca98a098d0b2ff9c52f4f334450cf9681782559a3c2e3b161a45944a04bdf6a36a0b9beface46ed82298b9750c2650591754b7bfe804c5e3edf93ab67a0b39d0047584843b8e3c00dfbe2e192bf7b66970decefc373e121408dcbdbaa54a06a0548cb0a033398e76ff9310c75139b5d197ab59e6bb876c35f4a9718b9f5cca02076452b2a56867e5b1e8c9a9fc3a75fdad6dc6d6672fd91e2e6f557ccd46608a0838fe35780ef5e57a47c1239fb522ed42500c70f485341d10b86099ef978f256a0358f9742e7e5a0f46fd6c1053fe485fcc47fda33a8bd2ffbf837d724addc389aa09a2d2a2721ffc7179eb6177e35083b989787c5a360aa25c857aefe34f44485c5a0160423311ccb21ead7476e44fb2dc89680b4c8b5d48cd7ec60e44e12fbb2387ba04faf6086df14e26f9c40dfc949abe017364b3b1a643a6b6ba9bc64d37d6f7ef0a06caa044cfb11133a54e31f65ef7e87e3736bb1dacb94e4a4bada3cbd04405301a06a7f5f8bf6fdd722c2181613b96ca286456f1a7f27025b4d81a3b0be0f7821e4a0c84068772913a8ee284e9872b0e1a8f27740d7fd1fbdbb396f5c8955daa40872a08ba08d3d391c051c93be77599ddc7115c093bb2f76c37e72acd60a2be63aca4ea051eee52e4e8c2f17f1f5caf1fe6c3a11b1da1f1e76f957a3ccae3dc82b215087a01a502db3b3427662cbfafb9d3e38927cf67c5080b17babc7b42c0b72ca5f14e780", + "7cec599952f12641e7537e2e25c874393701b133d7980be66f4da253705d2770": "f90111a03e45fdd08931efff294efe4a778f9db1ce4b6db8391925e0d58bba08188917b380a0414b84cb26d8bac9ec92eb7b520aa021e67dfd16fec2d5ae1b0c7a4edee81a4d80a0b05b9b0832cc7fb5a790075484af256fdd54cb44c0433e7a5d6511f402231a7f80a0d54c0750a92301c779f5f33736204b35a6827eec183a852ba586ac34f632d47ea073fbd2e7b046f897c03f768acd887f7e97d06fa7aacd3462b93d94b23a3f98f9a0a35ebaf1e6cda39232e51763d48b9417e3983f021a07cdb59c5a7cd759486d3980a07fcd40d85e4a258797ea716265a6a2c8131f219eae409314cbee8a4bdca5742d8080a07f7aff7fefc4b0a67fc7a1e5ae4afb3473dc09e11ab6b4da1e602afccaecc8ca808080", + "7f2cee6d1d7cc4f0dd6b4d1a276ca3d41fa08e6813e61618ad35c968c08bd7c6": "f90211a01dc351f4234dbd9d1ce3d693b97c66587b96f586b457da3ee3ba4f869c47a416a0755b12207e8014906b99ac7f28f052c1ed89f3c05954124eed36a8b65b52e526a0392df5aa7824a9e316d54289469654644794a4613f5a811435d558ad03599a30a03b01f891feb09e964b45d6716d66e05271775710c5a19228c99bb4186627a0baa047b7a7a08e00662a54b7f800e19874a143e0e201d46839ccd6c1e60b79646fe2a0225fd60a6e72111b2cbeb00b0207a4dcead31f2deb4f5df6031eb6e5ffc19597a062c438cc1d026ee4ddf51bbc913f571e4d1a75c6eb787a1ae811595c679863c2a0dcd48e6564ce3f3e50d4b94ec9aa600bc523b864e60e12773ba3af8247fed0f7a0564609ee6908502a8be7d70f86b35f0cdc26804c088260806a9238ff71fad3a6a038c407ee099396fea70641e034a9adb064feb55ee847cbdd16efb3088ad0bfdea0122e6c155ca17a5112bc43b32c0ca0e0176ea7ce6c6feb23a843ab496a28957ca045ac40d09d7dcd2ca9bcc74bb9e51655578b4394cfa5689e06829b79c7dde34fa0ab653347b84f9f801b848cb435e3d4424abd56273998151d8bc6839a9adc4264a0a12e9ada6b074bdc0aba70269f96b0150ee70da4b69b0e0869f2738e7c0c51eea0649529ef72e5b2ec0cb5c0a92e08333f6b49f43d70b32e58ac085ba552c2f1a2a0034e6a255bc75d3cdfb7fa7442f9c273fb4caf3eedd01283bd5247d616a981a380", + "7f5ebcecbac751b51d6f159a5594407e8b6132efb629f1b57c2cba239767d876": "f90211a0b287237f150c5e3c9842cc9507c140f5a00041f91c35c5ad391a656a52609d00a06288d5452f8163c682cdb1cea1bffe67ae9d01a8e44539262d0241d3011cddd4a00e2fd6d9c79ec084b41823bd8b5c53ac995c2f49ed57e4b39ceccfc9977ccc2aa0eabdc12d588977612b934c2acc600a0f2a3de7203c9c6d8b8999bd861867600da054d6b21c6375aa16580a33744e56929b13b123505e36fce62b58504bf672bfc0a0e1a68619fcbbf15de03d03cfc922ea9f48e8eced39ac60071fc64cdbb8bd8c66a08e22c309926e1cf7ac54c56bc72de258f1dbd0ab2f3a56e3d7377d957f0ab26ea050c705d2490718814000dab00d3d6d345523ab068608b862abdb93bc7227bc19a0041d4818e2fd9891b356a1ef8384e600fd983fde10fc399b51c9786b70024bdca0243cdf58e5b0b258ae41ee15500bb4f6478f93f56f7f4c6e960a5786f7100b79a0736890168847fc28b2bb10bac44eb5010a7a2d51da18f0aa2db63fab2e5ae5efa0559a7172603b7557d096b37eed94be13653f19a701648e69681177395a2f113ea0eec66af29849a60fca456413822efaa878297ba1fa7cfc61e2070ff3a86f0f8ea01b246b85f01db291b7a9709e7880a364ebb5adaa726f94ac65ffb9bbf468e06ba061543ee2c16368246413f4fa4762303e3ded754cdc29e5686b0532d6da54e25fa0a5df9772ba13fb96dd6f128959f98b1d28d7c1db9236a12637db91207711d29280", + "7f7aff7fefc4b0a67fc7a1e5ae4afb3473dc09e11ab6b4da1e602afccaecc8ca": "f8419e32beba7beacb218156e8dae090c68a2df1991741e3d730c8ada8a0cf2876a1a0abadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafe", + "7f870fd46ae70f8fca136068a10eaa74ff756d067acbeb9c5174bf31804d5595": "f90211a0af4ab1216ffa07e5920171e914dea4cc6ee9057b10ccbe9ebbc522bded083572a071405b161909b12d9d929827f46cce512c7f2d399c905a393f158fa4632da365a0300e323ec41b6bb5892ed5a4ceb4fbd3acc623ad814319708354334b8ed78a54a0ef5a162b77400a3a2513a451dd761ab2ba5c94ac8286248db5855c2e2fa788c0a0918644935a06f5393f6e581fe5c8c04bcb74f9bcb02ad9a900eb60e1176bdf18a0e0ef4d63e8146dbb7efe00d3eb0bc652a2e25e44297cc7e1d9d6cf229975738ea06d9ab805ba7a9267d02d74160e144523c0657f36511656cd4eebe27a9df7c86ba05cea72786fa51ce63b7051093155b41026370451518b20d02aee4b5bd2c94e3fa0d7c05c4f6967c867a66eb10380b3990fbd0455d512be308ed375ba1cfb6570e8a02599c9d2b361f92baf62556e565a1c107563bf69b1d8129a28f230be6a25529ba0b79c6cada83ec120f23e4475ee6d876c4c109df748bd23216dd94ca20e58d217a0b43159e292a79427249edf04eeda6fbb5c45523acfd309659222872a0d28ee32a094d8f012749bd6888bd490086a172ce1a42785f8f00cb2bc3ab468be591be8dca06cc3da8ad4901b7df96d9d8fda21f14719cdc3c09504054e14e11fa68f84c778a0cc11af0f9118146a2a79da861d02353e3543a9736e58401363d7fc0079ff5c01a0a0f40d6b464cbca560013bb4fcc9b1d7c8a74e2b1a4e0a29e74cee3e4f10464b80", + "7ff8aaade805a20624e5ed35cd0989171c3ad04f9178cf730c2d288e0507787d": "f90211a000567c7cdd86650bec3c336cc930aa05ac2b63e92fa726b295bff1978dc6ab9ea09efb481badba4a830f2b99ff41b4123330cee175530e7b039fd0605415a79d16a0c853594ab9eac1ead253644192396929ebebde637676e5a1e9a12026d20cf0daa0351f49b334aca2a1a88f1774e8f5f3d4d5aef063b3ec1d8f77e26fffe13884d7a0dec3133da333080d08039aed7048c4a4e85a1a008d8b353e287f5fac14c2539ca06e06b6ce1b9ebec4004c1f29079a510c9202f784ec457e5fee503724fc0b4203a0ca74a882564b008ab4eea3c7e0e4963c66d17a14e7acd7c6e05136312295d3eaa03f1117e6b45eae49fe9affed93cc525f976fab88d7f50b414ed077ea02b96597a0a1056d1e5ea1332c57f1c5819ea68e0b59161cd7f28d877cc3aa9662239b3382a0e14638a9bc594915518631faf7fc22f7eec60655c22d473a52f1f0e9d5e2b913a09847efcdc3662dffbc18c90f9526aeb6fdae49ab7c708560fc20f5bccb02acfda09e07c455c3c896fb4d6f4b8254a537cdc463525b2af08a5a34f3f874c3ea4457a0fd37cb0d4cf8abbb41923af02f4c929bb0a8a7b0971823639dde10f18a7fe9f8a0b646e6ca09dddf4701fa175a9518f55aaecb55820ae2e4661f0d7654b1995672a0301475735d079356875c7e1251c640bd00054748261082d8525130bc665a16aaa00ea4c48eeddb9a2cccfa27a76680309ee89dd1a69588861403c565a41d785ac780", + "800a2a5b06e8ae6c0c7e2ebf9adea7dcafa343c4671d7c0a26c32e2300925951": "f8409e3836b6940b9bac1d844615d99c1df521836d72784ca339ccfd7a4fab5a1ba09fbab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaad", + "80477121625573a0171f2daa2f688e06446e142fafc61f03ae66fb38c533498d": "f8429f2012cf6cb19f2ea37c60be63f5dcbf7ecd86bde7947c5f3507d22578234796a1a0d0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11", + "80926ba0200605c6e1cb0bb853611924719373e99c042eb8c9f50edbe5424210": "f90211a0a529fc6a22fa3e716483283bbc1ce6d2afe62025483a667e183440895a073f53a0e3f965d6e476976ae186a0622b7cad7c91ddd3495f51127d6cb8205d7b540a1ca0d1cd727ba27d0d1560347abb129c8103578ece7124dafb685b2b79353a9fae29a045de8cf1515b62f9624f9fcbe2fe364482d7180bac7c551b028f09fcf3a31744a03aaf6b815b0d9c0980494cf3a78fb95f2a62d669c501870edbc4b5489938b391a09baf901189fa058449b7c8e47bd36877a6f08a578dd4c0e5e8ff1d3681037676a021eefb9110fcc210e09b5e66f24797730e51aefd5c8a5d4830fed2404981746ea0e4834526dfcdf201276c9aa87df65db72a50b17f9f83bbef2635c023834428c9a0d9b1808f9ffd34eb7006fb7f5a4229ea5687298e4414b9c4b886f7db84d49f8ca090dc17d5ed39fa1a073c3d57aae32eeb284ec6e3d1693e3b787b1d923f2245f7a017164a8c66aa73efd887b514dd98614198eeb016d88ee6408cf1c6902139b612a01e2eb42105a26d5a56321a53ee8e0f722b934a909207f0ffed815430cac051f9a0312280af6a249b287b833c26839ab32ff925405a569e07ca2bc1167b67630cd8a03842fa8951652c9a103c2e9bd56ca8ce3ebc6b74c1fd4c5aa9fad04c066123f9a047e370e89fc5a391d92c75f8d1eca96f0c5435172f207f1a62771d16bcc5525fa0ae639913eb7ea5beae9b57e8cbd619fe46ca0f863cd0ea87f177d1e63e062bcb80", + "818b80ef1b6284136a81181b9d19fe1cd8080758a8514c4ee11d5b1d4e7e1ecd": "f90211a0244ef721d4eef8bc47d420296bda40aecfd0368d5ba90123b017f45d5262b479a0a75bc7720177c52f6b0909629cd155014ab8f43e576f16282ca6f90055844948a0dbd48f9832391df49596ec1220ae9f68e4ec1691748583bb9225cc29e3271d55a0c7b0df678c466229e7508861e97c11cb0a805bfd6b95b7b162bf9f41f56c8e9da0b259984e7e7a337ce590fa1da63e771026237a8b36ba245506b4942475cf3395a015f26ab0aa7e5c9ef92f5f9f2cdbd6b237c13d9e79b277780390860b83bf41c4a01d0396e06998d362ea361523d6926d0c5b1aa893b414a84d8ea6720152c1dc52a00f30363087ee4d86bccfc1617235d97d4fef9e424873674f04cd8a7544c32767a040671e20c81ab75f989e9b36610c5f16c5d9d62fa8ebc25f831bfee8c1e6b1b8a02867abbad3ee3f49be2d6008cf7f7e5e9994922b5556e5ace7d9e2536882ae7fa093805f0c83197b20464b314bb781911199b53f0de1d013551497343811c34890a04342c8d86be29cda6b29a2b7a9428aaee851e4290a92aba257fe24e87e81c824a0600d563b53b2c1a35b3f607c4e456254b8e70f5b52b15d356fecdc12f74a51b5a047dec039d260f09e20097f4754feb63b5eb3c5d5435fd4a19d8891bf0aa1670ba02d877ac02ddbae46712a26395934c8f012d796f0e29dbe6ee071572397f1d5d4a07435656496e4246100a99ff837b5ce05df01efd1685256da651b3da28295cb3180", + "81c04829c1a1be727e31a218277cc6f4fa81194ac187bdce597be58c4c95cfb3": "f90211a07806f428cf0f984d74495625fd2eaf9c7ff4adc588853a14eedb3a6bcfe37bd9a02a1cda3a8ecc27bdd5dc446f65ab25ad943c60ca9a29f1c4d33be60c571df278a005373d9bcabe6efaa085239039f022073d0aab5a2bb42a53d32d0f81dc525c84a041e883129a5b288b18044385885713c514af8edf7c372531cbed5ec05738d988a020b700cc5a23e6b3d8cecd767f2ab7055a6a1bd54377e83c8f11ecdda1555514a0decf9a8359242cf76929f9936f16c4fb295ebf58cad9f46fc73a130a197c7d7ca0088a8253f663929de7910fce3d124d5e6eb981a4999e68c143c44f858e53aafea097c6efea1738d6466ed56120865e88cbf46ba69ff3562d5caa4648539e659a14a03ca764223cbfd74efbc6cc0d377a8ec2b44d480163aaf91926ba5b9b638901c4a01430dd0efcd252aab8dd5541b422d926567754532d7dd9539184873f0134ce09a04a80bf00747a6d7552ca2301977516b493acc9742fe0deb2263864ce18be979ea0fb87593a6f84e4f92a7ca66fadd88420347cc6bcd03a87e7f59c94d55deeb1e8a03dc85afe3ffe5be018778ef1632df1e2c9aff48a1cb0f294880a84c7d34c26f5a08d4d254738befb9ccd61007a012ba3a95a64fafd75d646d76fe88484ec76e181a0560955d06eca635eae0d0db13ec1b5a9392a8b1caadbf430ba9cb2532dc9ebd2a0a9778cf179786c0860e20ce352063b6625dbe73e86b23f0c419e2f052bfb237a80", + "8250f4f9aa977ae32ef0f3ebff2ef9b913f7cd6647619dd7c03bba56f5c4e178": "f90211a05fe2dd0119e46b98e63dcd03a75c02c56993c94c5e9e8df3d700561d8e40617ca0a90cfa8a7764b75cfecacbfb58546c950d734e53ee7a491f85caefb971686607a00f2e11b6e65ef0ad5eb5d91f42514c94e5809f5886d61154ccbce5ddc0ec9e56a00d3b2b3a3e48bc00281b776d0793faca63d878e86822eda6c6373e782574ca13a0885c3196c5ee3a9784228ded1f05ce0477d4dd3d24cf823e5e77355301e80262a035d37574f3fa9dd98c9ca077a043ed67e982d315707956f2642b639039d1bfa6a0209ab8ab27e648ca128a82bc4cd9ace947e2798e7ee0d2d35d3f2f538680ab57a005123a49bb32432b6c90b68feb617409bff3a438af54effed9c9cc192e32b756a011d8c37c3d6830a33a101a649bc28fc2fa45808a55d83ac7d077cc25ee227d46a0e6956db12014e97cbd305770512f5bf4cd903867eda68437af45fea244864469a05b79f26be29b9cf4d422eef737aaf0cb5fac47741da937a6d2116aa0fc0be2dda0eb82588f24f0900c61cef7fceb48d65c0d98ba65b5ec56a3c4de26086349429fa092c5976f345988ad06ebef47d64d763e2cc92b2569a791f7b1678a2c66468fa0a084a6ff615642b4f0381c1d1c21781e25d8fa558e990e09e984fdd095128d17d9a0ae4ed5b1ac8ba52df06975fcb95c83244b46c38ffe0feb71dd49e41e251e4519a07d45d6777e702e020dbfc992fd3559f20340a6a5f7017f3d944c2a9439fb8eb880", + "825c1fd6628db8572adac976d5a460a42fa3d07cdfd2814e7a1ee1a99eb7aeaa": "f8b180a055e22d74116d3eeabc319d5c627c8a8378c7883edab3810a6207a4ebafe1cc21a01a259923ae527e266473882ded96de0e2ee893e2b402639361102bfb48c845e8808080a05a1039dadf538f3a3ed3114d41b59d85512df6c2accb2a3cc62f9c3f13cd04bda0e4190438c89bb34ce09021d82a9265f3dcdeb29fc655a67b2070fa102f9d237780a0d1e200db0abeb4c881bb58709f2eb5397582b6a9f2a9f090673b6a1bc6704a0380808080808080", + "82d9f35f03a655d92759de441ac6dc6b8a939589cc53c8555a562ea59f4b0b6d": "f8f1a0a86e3a450ae186f46384cf031ec446874153457f0b555fe8fc8fae9a0bd8c3fda0403598cc4c26e89f73429609de527dea1e1508ed04df9407e884fd77e6ec3aea8080a0ac1c4cc9085c6c54164fe64ce93e8674a0078168bf0735327f0ef62b3bb89c93a0d2b031135e6f2ab2c0e69e100d72c4f10a9032a537ad33ceaa4e65ea637204fe808080a01ab0dd993c713053c36c46a8c8205dcbd56c75ca8af05e234ac2b10dc04ea901a0e07de1cc829fb173a63f887e0e22566d77c71f293c321ab39765e33f7f7b601b808080a0c9d7e8685df26d2e8beded49094f3a0c8535622d27a279bd84d1f540b7ddceec8080", + "845a83472c2e6e1a5270d88fdab952090e0bebdcdf593e1a5a6e33d483b09c6b": "f90211a0a3bbf5b3d7200cb0f990ad966bde240ae61015b761ee8dce64cfccbf0018173ea059e473b157a738aa49ade075d75e678bdb0691b0a8f1bd1bf1c4be5e921e2433a027d3363c778e7a3dad5182efc9de710d56414441d38dcba35e08e1b6bf6fb6caa0feab0453c302be628b362b6479fc10814f7bd497c8a612968d9ca555dfb0092da0950c6ef67980843f6e7ad09bd673598335bda07999376b1a1f4b863e1d1f81fca01ddc4abdf6ec1d65ef79805bdad42b4b8f636e9891b3e91a13772eb54234790fa099020d49a1177fbaddf71edc16e921aeff53e90ce95f46875a55388b7bfea428a0018f9928a491da94b1a45a649d76cc1f712e2c1a507d17860b709e30bb8c0501a09f52e585f3706e360973ee279ecc0c0d70d611cf745f31eecf845fb2df14018ca01981b718aa912e488f6ce1512e53f52c3b0fda5e83d239088633cd354235c5f7a02b386e1d0ac6a85060561a2c72d57de296c1cdc2aff2e767235d2531bcfee7efa05146e4869598ccd093fb00d9ef067e393f5bf687f4ad42488d5613ce1c151691a03ed47fcb9bc6dafe82a55ccc9c553a9c16040e5d86f5cf45e84b7646a3101d29a071b68ae03f96bc0be43d0250e855bcf6f553a035052714a3d5941e9472cfedc7a063f85c72bebf49533806c997afac15e419e28275a0e6120cf41d46ba54e1d287a00dc300a23fc00931d881b34f91f83571205b6981f29b386505795080a3db624880", + "86d6e35bd591d67b348101bc3b87d40f8f81c78c60bfedc53e87b7ba4c1c432f": "f90211a0eafabce3b257c3957f2f65dff3b414f25156c65becd85a969129ff7c268680baa070b8bb355e6bc7824e2aaf2502c388abb6382ae46fdd6ca617f61b7c546a2d49a044170b0b2f904b74ad679cfb53c5ee45c7b4c3c5099c595d66dd4164942c612aa086e98a7aa4831f6a9c305bfcedabd55b39ed5a4dd143fa0797100724d876fc0ba0a9889b77088ee3d979b817989cc34c2eaae58319612502c2b91d86167d46310ba031e91c73568fb2f157cc9924a1dd361bcffffb6c0ccbdc1d95b4c8f0d7517a73a013aad5c238c7caa6ef26c914ea5f60dc4aee82022b21072e9250028701c7aff3a0b5333424ff8f3d9b2d1790e829d27fb07c43e0a7410b647f71c7680123c71eb1a0b4c8fa352b648d5bbe28baac1122e5a913bc7dc9951c93e48fc10bd172163ec9a0a161e0193e1b229db9b2bb586810426794eba3b4fcef324508cad6a29760b526a02a62f90dbc8a93a11d923328df94528856ee8546cc3da3e1b9ac004cd92c2e4aa08dbdf0209fff987a6e7e9cf577a2fe8732f92704a5ab01455375663019d98eaea003a4a7aef7178fd76060a5928b21fc6957f84fe78b331e32a063227231d28911a029ca6c14c96f0b14c187c8414b515907c5176018fdb406decdd011eb5afa1cf2a098b746d6b68934da09e8e96868dd768b1e93947f0940d1560e018be6420d1e81a06096ec0d05663f76780fea2ba1192030b6d3ae0fa33f0fbbd28106b28d877e0080", + "86e13736582a41648e65c6b25296a7c8bfb0790c1b60b0c9933e47693a1f21cb": "f90211a00feaf17708ef6805766ad6ee353d960da748b079d79e655c3aef70f403f24e7ca07aee31aa053d15089e630260e777c1f06d21118de759ac7154b67e346fa85746a0aa27556cc94e8ed338010370548631321b72808d786a43293daae2b8f06bda1ea092cb0750798b6142ad968d811bb6c4f38f06f6b85efeb20d626c65c33d09e53ea00578b8afd40b8d1c8ad4ef60ce03c778c357cb63287eea584e03c153eda1fb9fa0e6864b9874664405d167ef15c4a0d3ca2214446ce2e51ec7d3fc07ee4f7d3be0a051ac8cb9f8b39839ceab32a0b9500e97bc64ec3740918c1adc57f898ebb13ae2a0fe68a78ac2105620b432c6ace732a3ca8c61cb094188dcdf5b5161dac65d962fa0358eb0c86620d5e0a7a3ead0a4e8961d55f5fc207f8a55d60c33b7f00d7fe740a02a6a203cc53d15264bf4fa33b1091b5c54a0f8621260129199a6999e3c551e38a0915f4c5b4c2567406d58be20d75eb55b25ffcef1ccdef48d357f683f47c2ea0fa0ddbfa59992e79e3abd2ea49a86c2498641a020eb360b1b5d0411375f35ef4419a0253f8c2568b195cdce99a70e3e87aae59dfe7389af80a835db1e82bb148476e6a015b3ce458d9148e5839e276d0f10d9060a561512b3c0f651d46b73a3a49906b0a01cc6562f9d6ac28ab42374daae4a12fc86b8488be924b4f5e6f3447bec450d0fa0ce88a26244dab0b8ee3d5bf6544913fac5fd71cd476d42b71dc0de18e2a9c8b980", + "86ea9ee23ce96ee60791d95f015ca41fa875248a2affaefd993819522f236a8a": "f90211a087a2582280b4d7a42227831d9e0ef1187cb4098b54b1035e9e454679bb107c92a0332a2d4456016702ddb1006f41648e096166eafb0b71d99a7d128cb3eb7e2235a0b8e82ebbb3709cc5db2f0916f967d88b5d552512f07917b845ff1b3041838374a023703cd79bcfefd97e1ae56bb5f5b4970a13e4669bad768ef8cfaa4dc3e9e432a087600781e6a8cd0ee0fe63da274d3a8824e682a7afc85d3807b261699d02e6e3a0b71accf4ce12b30d091958dd90dc85012bc6b23e4984c3bf6d63cd73676f7279a04dc5501633e8ccea1e372cebb8bc9cb6053f4049ccdfbab6bcdcccf1c9e5da8fa0bf9f04bb04b49c6364a2a9735d689436cb90a5f76d148e51cf4ece560036fd80a0fb0e59fb6fe6bbefa3e0cdbe856f3defdc7f77d992c60fb88c169e98c5c0acaba0764323337e773fa70a10c28aa173d2e80f6533e0eab84c08d2e14e484224445da09710d37ff455f62ef438a8d503171e82b2d6d74c976c243f4a85a71a0ac21d4ba011c6fe452c323860b77c228724e2a77fd4efef526f48c64d8834f3de7f602aa7a062577f3664a5b2a2157a2bee039da7cba8ec8fe53c74e295c7be5e5a5d87432aa0717099ae6f3509dd24a1da0a4a4efb8d9de236c825a985cf704d06ee04d1b78ca0ead3c93953d0049429baeb7ee0c4d70e672e2bf0309f13033e69b0e88db699ada0ebf36594443700c61da10b6bfabd87a1e47ffd1667c1d130acd801409da9fb8580", + "872c0395b96cda5cea44005467ff2e43a6fb00b67c3f4cc392ebef6c3b561133": "f8f1a0fc35a151c929a2ea5332aef4992209198d624abf9d6ea60fef4a50e66b80faaaa0ba0930dc348e55956a45bb218e12af8513bf61932679c1c998f71d38e8aac38b808080a067a4237ff83cdd358771da016a468372ea7fb75ae12f5537099d60f3ddc07959a056e6db01a228318cd077fbc352fd6e7ac35502fde595793c8cea5fb0a7d91691a0ccc6a372fb84c554f5b7238a6349102fa2d41af1679fde97f13b0d15766db2e5a0fac7f24b0f53d51ac134cface512b30975d6d3a7758fd50af4bdf5188d685f43808080808080a0681d1d1dfba32841dab1c3f0fff41c4659c94e07f2b2ebfb48bd75f7674e11b280", + "87aaaeea20c93567ee07ec8360304fcbca0f4880ab6f84852c1659eb6dfe5024": "f90211a0bafcf287d8901592a081d5b62d5cbfe012a66fd6d69c2a9413629eea58ee7a9da0432308718fe05dba9fdafa2510ed26e50598d0806857c203a88d1948bd777a8fa089ea5b11c2f6ec01d398ca141bb0f3a1786eaca6c457c7a7615587d85d10c9a0a0621c3e437c79bdb867ae51d7ad65fd5031c4f3db890db042d60013324a003021a02ecb6e6e2f87f0f071fb2d1668e875331363afe12ee84d85f9cf1635dc69667ba0c9ced6fb7b40088b23285ae567282b879dc6bc6de25ffda4c9d8dee0a69dc4afa0d81e37dd3361efdd6e6dd2b4ff16d1ae55dae3ab63545e0e839e0bfaa43dbd5da0369d15591c0d4e3dda41fc4f6f2074c27f7a54c52cccb4c63f9dd6703e902aeba05f5274de6587ef211a03a0dd013960cfe0739d96565e617229deeb10029ace46a0223f122ecd9246f7477aacafb7f30415a30e221ea6e18d26ea01c7d83f4e5b3ca0350eb3d74674e0bb9a6ba7ef4bfc11811819f56cbbe4d27c00e726ffb4392022a0a527b58dbf64bcd7bdfb61d1f38d7caf8e319b1833636b8c85b525d0396030d6a02e42b5333519cb0d22cd91fcdeaa031c26a1f5d6feeb94c5a50cb8a3a7b5e2b8a0a4a9a9cef2059a39cfd949aaf29a1a740f311cbcaf6db89a5721395ec855b17ca0e28ddbcff15233b7a501a670e0c6949d6ae9739cd896acb662fc637796d8b7a9a0ad27b97802f2b54b375194dc064e8faab3cf1a460ac840fd0d9d1d824590616b80", + "87aee177ce76f33974d5028589ec418f628287b45b8747a0dbf0552fd72bea57": "f8b180808080a00b3ccf856766cc501baf4f5754e552f3aa59b65f1ea00fb3512f77adff784906808080a0dde3dc4428ad3897f6546e98c77ac4b2a82a06a976d8abf4009cfdefe841d489808080a03cf2d8427fe4d1cc2ac40b138cd01392b801d831c952b8bc7cd6cb92aff92199a01e9b2124a58b14436f814f23ede5f1c563bef156e2cc6e4da73ec84814fb872d80a05f70bf279f3576da619dc1809a9c2e5e114e96bc774109bab9973557c138315a80", + "88b89ad5006e9cc3e3053457b82dfff5354cc5d119159b6f1f51e02872182f6b": "f90131a07b8024d99ab8a2d93f38bc1eeb6147abcee9aca23ea8d7c24f4a2019c6b0fd8480a017ebe6512a1c49f6ae575c9c24ebf44b31e57f22fec04fd169a50aa854ac1bd680a0a66d18c1e708306086d82e2aaac60f0df82069aa5a68458b3316b8281e8f8c238080a02c5725f31f8ae62abc5c4e10567af3b7c46ecdcfbed5f49228df1af60f60bb6480a07228360fabc04ab28564402c438c4c5f8a9c41ea0bed0090503ccf9e91e4a9aea0d505ed3b98d2c10cce023c5217eca97fca14b81e545f59467e50199a13407811a040ccb52b21568223afa1f6766f4566296b0b6ef8dcb889457827e31860348b5580a0816d60b1d68673952c75d57a6e60a471f71b410b56aa3b5d1830b4cfeee51cbca0e215c92a13240706b2d7a567d424f345e59fb6c55e11c5588e464cd90a74b51b8080", + "88bc1bdf852671ef5f6248ad95d47fdb54f20c1ea213465b5f18f3981cdae7f7": "f90211a0780a034ff6b9d2e844b35c1e7f72716b8e733428befea051a4e9daa1bde7e772a0c57e29b9e81363387c0fd00118a632a6271762a9f4dc76ec9c001c4d5154f4b7a05f7b1103b3c15677d2cc7a1d57569c6d9911185251cdd0b7b877f748dc21812ba0bf01ff16c937f7a5a63646fc540f9a264b11c42856d91d40f8b0f7f2603cdc12a0a7e44fcdd0099a6ba1b386624fcd1905360f42e99b71668176fe7c9630ba61caa02c81c06a579450c70db0348bc217e6ca5e80ab8c319cca630f967fc40a3f3c03a0de6a446b251c0750543bc9290d7d0fda03fa7b85bb543e68e9a3775250e04ee9a02e9ce91e3d50c9cd363a7a7021274e02267c42a0c181a9834c2ad60bc5f8da8ba053c09b5cb8ad05a39dc02c57ff7f2dc5545ea0b86e9628fe4805529ca60b73bba08073e09d525e7baf17e447ce3317f5ca11c2bbcf58f28a560f0d71c08314a485a005a792ebfd5005509cdb75646ff73bd2c4d0be30a5091ccafaf4b016480b39f3a0545b8c19d7bc126a3fcd37885f81da4727dae1b276c8a67cd0e2dba4fac93f10a08452b0c4e0f9c37690ffee525cc6cd30db7c96d5e6cadc65b192be13b0169c17a01982d864f631d92e271746d5c3278bf491915f545bdbfd34b0f965768f14ec85a0e11e13b5335f44b71c9df3e7c086f592f43d5b07dbffcd3625140ae5c3b0999ba0fa091da37feeaafbee8f9e877a8f380762fe0b86c815a5fa7536605f92d4c0ca80", + "8945ccf44f9c4870af9c5c3d7eb559531e13700ea0912692a8a348c7d671f2a2": "f90211a06535eeca4aec2a5c096fbadbd5ac6d26f80a308facbda680cbb8cf8192c751e0a0873ad61417f43bfab98eb62c885191c84ca387f7ea835ab8d69b7ddbe8141024a0376714cd328794981fc74b9200e05e812e043a435d2a68bb25f7c0ce50e90810a0f7196a25be0817a316b4df115f367a24903d0f137ac368486a68ee0517219724a0658d1950e56ac045dfbf4b4b29dc99d8a8e8a64dd041ee604502f1ff304cc7dda0e8d9e8af23629b535b2ea1324ccbb0973e4b6537cddbbe49dc0a09cca836eb13a0b252dbd427cbe1c1c0d0ef59d21baceb1d0f630021d5dcda33bee345b4862718a064ba688e7c941cb97100767ca3cc8c11546a9c2330b4533d079ea73800896feca0797c5188c37528965406084fe9da1abc797037b0b52a076c7da0b8c55346d4c4a03378f1e2f62b856c56ef59a0c6ed0fab93527a810c82b5fdedba113dd93b6191a0b1ba507ccf61219eb08ae4267632e91d60b35b078be6504c458efc70681f8cbea0a7ca736caeda8f647c791edb32bd245ff75f2c3e2c0ef1bdcd466c3a148f8696a0ad29439acdb6834df9467480563bede98b8441b9c09495a96be4e27baafb93e9a0bf10db179b682d8574cd855b409cce3f2b4bd7ed287e64c33e89c54596c05887a00bba7e8c2bccf35c1f06730ae28aa8fb2a5d056a2c72a36f99698863387c5e63a0e6dc146d048f448f7e6e52e63fb9b35b1d36f40dac4424aa789b43434f9dd89e80", + "89a7f1ae49abc818fd35783e1f11841204a1eef679ab0b1e23887157aa795b7d": "f90211a06204a5c42fb08592f7597417dac1964b78e78ea419b768321b89ef62c8712468a03c887d9622f38722157ba99b7fa4c295228ae20c3e36b4ca4328d734cfaf8f6aa02294a7edf4c0e3191a66de67060ac20542c574fbfcebaddc8b37e8deb811f791a0483e00ccdc953f42698574c0a25aab56a37d9d059ed7e744ae4100a341b98bc1a09c167eaf3af02fd89365d44c00a514b303faefce0cea722bd597121981003c80a0deae42e7fd83263b7c4576f08ba3ada5e559322ba7bc2ba1fd245c76914546e9a0fbbdea86bf51e19849a7fd048093767c4cbf4e8803649911ecc6c53bcb90b6d2a0f9b6dfabc5e5783fad593c36510427d354e202947af66e1c8f0a39cd69a9f23aa090ff1a734fb3b0eb5f5d8f3cc3d88572a9cfe3e7542cc617d14203d9fa88453ca0e7298ce3e911be4733802112faf46e2a781d77d6eb5bbeff12a0187c843a24d3a07eb1690351200ed0b50d1e531f326e0c6c43725867728d90adcb684dfeb62a93a0f4715214f5f145734acd28b7a4abdc718e39c5c50458026e3e0443352c5ed276a0ead14b1f989c0b340dbd91d2e64f8a119b8c2c87c5e3b35e72e30869c77d4e48a0d783c0f3ab85e061d97cfc724a4a5e3e9e3c0675be5ce0230d8f00d303ad9c52a04e952e2af712dc2dc3c3a2b7fdca3a471acf6c3ae484794dc24e6e1711966825a0df4c4169921843d4d6ee7e5aa0222dd9c65ec61fa7d6703939abc6f5a2fec67b80", + "8afc6793f1d7b4c5aabedead8546e16d29ba44ea8978e6669055c5a6d61bd2e3": "f9011180a09006f5aa004fac3e93c08dd10d413ca3c0b3693e8b687b5884fd01825835c71e8080a0824eeb7bb94cc72c8e37fe457fdb996c62ae1244b9670c4726d4be32dc37ccc780a02a8d1a63217c65d2bd8c5b662230255aa00c5bd9ee4b0a7404916387a281b4e9a0562b81357aeda4ab3eb284b9941428badfb24481599b0274df380157f70b1a4ca087beff3760caae51cc7da2ba544d68cbcb44283afa023d3a7f8724bfbaa5b4328080a06e49a3a90d03e4a14979a68076271f6283a342a300c03e233490a8e7fef826f38080a0b48a784b7667a15a736554ac055447562101d402b866526ff83fba7817fba712a0c46029d343d14ea5fb3fd5a99bd7436f7286b655e110fa46b650880148c3aee280", + "8ba08d3d391c051c93be77599ddc7115c093bb2f76c37e72acd60a2be63aca4e": "f90211a0bfce9e1629c3f810533ca17440c874b4f62b72c0fa1e7f6d3e889e908bca8e9ca0d3d1e6bc371ddf75585422d2a59aecebfffc5ad02bc522d0b8e60bfe8d38bb19a0b646e703d93fb7657ad4376efda74e4de990b5d19ce182d8caf7ce525516cb98a012eba93fd67e28968821b436916e4995096b643a21dfbabb09e908d9eb22df6aa0d228ee05bd099b1b5e0588e47b677b58601ddb6ca13ce02f3aeaa8ba216abbaca036ce78f085c517d5ca10830811a74815e9f15ecfe3383aa4a2868c8ec2534682a0ba629ff5b91ac284dee8de77d465c3039f6c08e27d9d3f2573e9096110cfd9c2a09209478ac4b9a50c51d430fc71bd91a2c0fd17a83c6786397ac2627025d7acc2a0f20203db7c0c28908c05792752426f72e219b8cda3ea5d63fe446f658cc9391ba0d7f76b0d9db6d264dc0aa280869c109ae0a2255674f71f456908f893772816d6a0eb744cae926da4eeccf73fde8c8b358b55e8a707614750314ac320ce3f83caa9a0b7171124506ffe71b2138f547ae6d05b7fab8e13b26e03f6d4cdd8b70c7be828a01bc2b3f2165a4dcfab9613c0226cf7180fb84f31f31c5616133e6116a27cfb54a0433a861eefba97dc44525c8770d6358d26810d4d8403c0ed222b2e15bedf6ab8a06c39d2feef3aab1b0b989c4ee7cc17204825bce591235e74a0747dba8c3ab7eca080f8f5e28086155e14b049a9883f15166d15c3350bfa4a70922b94cf7b099d3680", + "8c4d037248f1e876b855c0af4998d265dca626bb3ba7ff58262373343d0fc09c": "f90211a085b82df22836ed4fa9cd266265c9c85ae4693b6604bc07777efcc7f888eb3aeda089afe631a28219bf1e8408762701067f374a77c88dbbdd46aa47e53e1ca282e8a0fd26b7c101746d96c96affcc91978bd0e987366511fffc882e509cf86a3e239aa0cf4fe3f76708518f9ff59306924248949d28da6c61344beb669a472c0eb4ccfea05a34eeb7aa2339f1b5606868e6d2238f0079f887d36e5b72aaa26ba52c7c66fda08b7937cab71e763fab265e6dee3a76c273924fe51400b463ed1ac8e8b3c13416a0925fc98131e5bf1f8d1004a2cec60703d92ae7f91422ebc6c256e4a51e7f1aefa039d5016ce1f67b7ca560a67030047e4b14a91a46dc63afcb2d87bfbfd0fec14aa05386c6fbf5d564afb63b718caa68eb7265a74d6652dc7bf7aa33fad554407457a0c68a1fe318f2aaec4181f91e31f60b9ff68f87e7c481b39fd8bb4c9eb7ead91da0aeeed8c5ed9dbd4a1518c30b7282813b955f920af32a7408ddea4e2c5aa80696a097616a55965215addff9c1f48b9e509eeeafa03561656e3f478322092cc87057a01f150ae7e2b80fe17fcbcc7e42ee93d648761849108a5cd8d6f21f7d35e527a9a06d4d703326d36a7e45511cf3e376ae05e04d7b6ca893c2e3c573fe95235c0be0a0a6f586a4eaa381247fa85cafe1f54838d20369a2983531c059ed05d1f3ca5451a09d78beb2ea85bde4445e6a1df43f9c8afb762971f94a12e41e76ae15c91199c480", + "8d25f3acae606452ecee2294429b57dd54d3897a01fa3c19d536d079c881084a": "f90211a0d25419f2a58a9fda41834fc15a5fa5d26453fbae4f5eedee58ea8ff1cf8fdae7a036364455b524367c93c95386f38e1cf8414c9d332ed2b7586222ec64d5f08033a05a7346c131af8fb746c11834a4e017e26bffb4bfabef3aabf5f26ff114682467a0ff370dd86a67f140e52a6879dcd0de7f838c1c1bb1157bd4302af03f460eb8f3a0930402d0d6d369acf8a475244e8a9b8373400fb9f3b988788429cfdfcdcd34c0a06c7ce32f2ca88562d5edba35dd57b6a3117252b3c0c809a1b888156e547fca7ba0d363257789a336fc40bff0d8946377a657b319877722d3d9b090670bc7a9fc72a031f1e4e7cdb6b3a78caebe3a95fdbe45d571104fb57393bddd7f786e6c6b185aa0cfdabe3168c8abdb2682413b6622b06cdb60be09d2699f1932201a5e2d33af40a0e809f71265778001315415f392fa26261ab2a7d19bfcb29e6f86fd842d8beeafa01730a3f6840bc084bcc3259455f4f1e4570bcd2492298cf0cd6eab7a2a715844a0cb56df6e9eff972cb1cdb773142bec1687b001422db0def8f17643596b685890a0fc0e634046b2e7eb019e0b98e852fb4f65976a42a2fcbe07850bf7ae9d8b552aa03da6b5578324976ffc79ad5ed8da300205093d0144c5228ab10f95cc0236e2cfa08c4d28996a6d344bed9c3b9a12812f1f984546dc12b573cd528565ff4713e67aa03680a2634e181efc0ff1829307a459d013c496ba049f5f3f15ce518f2dfaf1d280", + "8dd682f2190a96ad9e62c4459a96e275077a365300e8a94de3a1b9aa7fc1ab1c": "f90211a028445a417b2985fa1add35a618b2c08023562a6464f4b32826e56262b0893abba05d2ad588dac4ac021aae9638d69dacfa571d0227c2bda5083af2c67bdb550596a0e66e5b51081996b5fce0761d226259c47b2ca22d026ff42375aac1e94ded921ca0213cda86f44dfdc6e0fcc7d1c587b740cca5ebe7f0fa1525f27b94a84418e27ca095a6e8fd7a7432e7d49495e101c560e44785e0ca042823ed4b4d66e83f61acbfa0ba600cd6a494e1360233d62b03ea812e09e3fd8b5e5d34dc384f62050aa4f350a0b610b5984cdc7e9bdda569b49ad4fc19a087add17cab54d41b68729ac43e3d0fa088bc1bdf852671ef5f6248ad95d47fdb54f20c1ea213465b5f18f3981cdae7f7a0f5c86e0c8837ee359ec9543e72de446f2623176e0d1c4023cb9686fc764f8891a04f20b3751a1cb6775b3f3c980b6d0201965f7ceb3c4c50caae4b31ac49a79887a00ca563520457e8180aa348459645f75893253f29a2194c9fb5bb4c06101b3d78a07a06847a30fd4d22c3ee35ae8a7d781b6578adcb24604279f9401e29cfbf2f72a032a8aa4eae262d2b552cadc763c68c8428ccdfcd23faa756b9818678c1bb7d56a0d826860918247a8103e3d3bbb99a82af5cf37af038d18767e5957e4dd24077b4a0d26b2a8ba4dada6f8977eaf6bd17d0bcfbab102b5202682c110aabe62ce2e6e5a0e897dc018f2d1cb460021e4adca189e98a87c9bed48f024eb93351fe2243167080", + "8f7f62ee95216530263364614b74c2a1ffba4430aa4ce64ea1eebf2df64d1a8f": "f90131a09d5fb578cec8dcf55c9291a256e4cfb072860ce3415a74ab53f235b61567b91080a01aaa1b2b63c6f42f0d5811c8dd5d8562b03907bbc9de9ce65ce01fdfb6dde2cfa02b4cc1b6f85c62919d11ef193261d95de6e04d9a01a538f2ee62252aa51363c9a005e6115718929c61cf33b0a502a0764f630c1db48d26cd0c093572c4cef0e8f5808080a03aeaa8af90737f8973b1950d680da880f199a7dc100ecc0e6b78656b537df153a0f0250031acf380fc8242f2e69759abe1db020336cd441cf030a40593a3ea31d180a04d1a6667d3556ef3189bbc246fb91a07bd26da9ec8244d3dfacf80d86d6f7814a02ade0340017f57afe5459feb8a904de3adf54202356b227d186fb0ed01b44c758080a03ed6adcce86912376d85641697bb3271b43460e03b6d72543613c8e50976731280", + "8f8e14f2e64cb740402144f02891e6337134bd1a7f0ecf3af6f8f6663b3cc8a6": "f90211a0daf0ef28dce4ec1e37de886ca15767c9473ced0fde118045809c3217845eecc1a0f272422c81bb435e4192dbe6a25467f25a1332e303f9f709d9d79a8564d3a2eba0233299e13d87f02f2909deba397de4f97527c217d526d15e5ba17f3eb6781d4ba04b83fae4d3b68abbc63bae2da4508a9281159137d058fca5a44fa39e6d8db9b5a0be30540a3d3619c058c5b4b737beccdcd3e7fab650e5b276fe0c9ea0ec0137c6a0a729ccb2117dbfb341557f6d21cd5af47d2517b86841c08af2a28afd3d9cf0b8a04e064849450665abc600a39b03c4b0936722114250f24106575066a2ae8dc476a07d3fe0c192e9a91aeb569922f0c7c6a47ab37a6cc8b8a7e959ac80910ddeb504a02a531350cd2b01180e7ac0531cd0f4ff35801f8a707bd656944107b1f658db3ea0951bb780516ab49dbbcde2c1ec9dcc07d1ab69f7ffb5cb74ccb6e94f3645fd30a0f1eea5633ebb06cd38babb380ed7e9bce12e2cabfec530916755794f9f675584a019205e5fcb7c8e47a704aaebdf329ce1895aa34b5266ef35b926f73c28876bf4a0bedabe49c9526dc2ff5757a31b867c6bed9e528857e483abe69d055c2493c233a0de0c37023a08378228e45798c5ecaca2534ab080798de28af8f6a203a0bd493ca082db9b864480ac9e7307efa1b854ff40ed67f61f9d64f6e65e73a65e430149efa08ba85f00706a71cb33d1c6c312ef1244f921add0b4ba1847c1dc980c4cec11a880", + "907d0344ed23d7c7c406820615cf6020b0c3b2e9ecc3836c2c8c8f31fac09001": "f8f180a093eb447449a2c598eb2705c6c366add2d0c476064ea6ce49c4c8bdded8e66bdba02f5810ad8b280463508c8135999c3c5a2c4a969e4461f01bcba6cd33f80b2c84a0b77bf0c0f0b75a9b33f7978a1f84a3605360034cf4927dd86c43de4d5c93e62780808080a0faf5c51fb4558e9d2856a826cf97fec81e0593ba014ee81d5f988305369cbf09a0b23f1363d47c297c3dc5f9430b4c724659a9d09c785b1f4a0cdbd5fe25353b898080a0fc99038de285bf03f55e4b76e9f87c8b46af5c4f9e3bb6105a5aee5e01bcf8f58080a02502a66cef76b8fa9ee31994480f92e259313a3add2598a17f7675e45c54679f80", + "921219934ce54b3d31d7e4a680a4f62205a92813829d522334d6036e1272de6a": "f90211a09c5a76331063fc7457437258ea25074fb6b4928414cb097660a3314cf13dabffa0eb4d0b967d56149d0f49f6da2234d46d228aa102c24250b9c7c322c65e9ec100a050612b9c6ce945308ba6498e8ff598987eaf89376c82395103ca2b590d6e43dfa0921f752673401964a63a94549de945734d8131195aafe7bea93b9331754c9b45a0482afab081bb5d776597d79b3d0a8a7c9f6ec22fb848b371747d0b95045dd947a0f3cb731fd7731ca78dcb61685ac2cc0805e9a30fbc41a7a2fad9cd18a91856cba043a1be596020937c6582f151d2d6561fd536800286033baca8d8797221109cf5a024e9363e3321a6e9e830f056107318e68ddd543a23a8affdcb431fec866712f9a03c5945e94b513e35fbdc690358f1a6d3021645a0edbf137528eb634622663a9fa0bcad688ad6a6d5cfff74a8e5cbffd60c8b0f7ab31912cb71a9d496329d9abd37a0577c8f7380b564841c3a38a1a6220694dc93f9408605b5d9b95330a1fbc8ff7ea06e9ff03fddda8dce60314dcc4317246a0ed5b5b4ce360321da02277579794e6fa077309e7c4350146c40dcd95d386505e641e1a0f0d13b5905336032a3526fd56da0a2908f93e3fbf791c5a4442cbc541396cd3444ed2bca53d5aa92ff8738041b4fa080477121625573a0171f2daa2f688e06446e142fafc61f03ae66fb38c533498da03b492b126fde2d36d0a6d81b92c2f84b6b34f99f40262e911ffe4b4a0f2851b880", + "92bc5e067d52a5d08143fd5d61d007221a3a438174c0f80638b417fb082a64cc": "f8419e393e231d8305993d740240a013f91e3efe55c30441f1713582772a5c9076a1a00b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabe", + "92c3b71e20fcb176526a884e0c7e55f5c0a2009039e3dbe9a5c3be233f98c033": "f9015180a0ba571a7d84b1a9920964157f54f15a32b1d71774af6e8f54916d44605c699eeaa07a54e8267763f28f029f6222e0a9d27fca090180430cf9a49bd99890845c1b61a0e4d3854453f9e75ee922f70ff7ddd41b993805013734dabe703438899e76091f80a085e80b2932f4e99607019c755c48183f3fb791898154e04b3357a9fd3e4d2baaa09a0588cea174d42e5d30c1920dad44fe0f609d6bd469d22c09b102b101369456808080a07ce6d8bb484605454f0a046f3dfcfbf481e2c15a1ecc250721b0f97e2d7a1fb9a0a0dd128fa1b95830f2744aff2dd02831b3660a5b01606f3f282344becc7670b2a02931633858a0a1b96644a3e290a3e56372d19e068cc5292b34877f3ec68cb320a06c5468894051f896a3c89a2ddcf3fe00bb716ea30eafae4df12a49bccc1b52f0a0bbdc38ea2574cfc1f855f5068706d0f231c3bdc74b621abf50d2f064f57526348080", + "9326457b0be5d597199f4b5a52109e54928a58e9d4c335399adf0afcfe905dc6": "f90211a0bc656172578a3665590f3d2ed177a1d082d9c8ce8a2e614907fb16429d9f20b4a0976b6c7246728cd5af194112a3d2297f9ed9b76252cfa942de864b15935a0b94a0c051e4ca16da64f83a8828d910c774746dd37a179025bbff744245706ef0cf4ea00aa40977fee3e51655b6bf4dbd21e49fc6b6bc811ac89db054f83a9d3e34424fa01b6e319c7281a03fa1925daadb1af671746bd59d5393630e40e8f6e40e3b164ca0b8254115b21683cc8e54fdb80c84a0c5bddf6198138540427b889e1291ced341a0234e2665fa5e05747df4c1acc0787f1f188d4357eda518bb05ce0fd72e7ada35a04c9113feb33fc70c5f9d6a45a3e37e2e9d325eeea39df2f47341683b628a1360a077490b850e74737f70129d2de32face4e6d876ff9654df84e1c15c6ed5b500a9a04e1b98fd8025712ed1a11f68be9ef8e08c575f5b89cbc7a5c5bce4f821652b4ea053e4bc03e157aeccbfe1cfe95a050fe5f8370a36e5bf334e780addbcf410b403a011b88c102d25f0e65959ee1ac2d612b8416732aa4fd3b9a6f671a10a21226ad4a0fefda4deb91de6c34a23e891862451f16a9a925cb7fe17c5e0bac6493c962f28a099f8c5bf960ebbb92b0b005467c36618892082ed9e5523b9aa1ae5d611f67a03a0adcfcf75b3b72291737b5070d651fff197c9b4d3e3f9a05d1d286ba7779d6d53a0ea7f46bf22722a54e1012153b84038d28a084ffe870f53df448a43ff43d76da380", + "9835402d3489035116f956e324335bffd241a5f82b91eef98b6af7ece497db70": "f90211a0fdff4add4bddf1334831ce6cb5b05cb6a2ffdec9cfda5a48d56a404a1162d516a030a33120b92da29ff74cd474f0ea3a539891428903c9a1ebad30ca14538c04f9a0aed324fb9beddeb4a5bc28876d550f8700c8a5198460041e7d2113680ffa62fda0ba24766954ca1ff765b9ffc641aed61529b4792572a006fda396ca5f3268e2e1a0b8db7adfbde439783b3d69ea76d29894ae597e5ba7e0339d538da7ff7d82ddc8a067d4fecdbe4c21f6066cc12e43514d5c0ddc721fc2dcf76d789ebd1393edd363a069f7a3e92b7ea7bfcbb5968434511b12972bc0c20c00a557a47a8316a66d62cba0ed1fda6599600f47b9a8eee09c1d264fe2c8c80817f828bff6cbf6821c825a22a0d65f51df317e4bfd98adf88794e0b85647519d84b30fcbf40808a51e6ee6d797a01fcf805de8b727419bbd1a27170d99441970ce7e165c0bb9a4c0a85a25ebdc12a08d3479e2a5849df3e47798dc423d6a6a6f5ca5e759507c883df07882329bcbb0a058e24a13e84452e9787f65cd823850a33ce73355794e9b166c4d2fd4a1375344a0ea09530cac54d8858f2ca9e0b731b66a74cb1a5bc127a124a312f3bb2310ee14a055e26842778516198f78fe470033a4a0aeb6928e0cc98b3a2a8b5c1517aaaa0fa042a3d6031918ae9735dd3147bf68c723acfa66aff1ce8c56721460b8ae234d0da06ca7cc5fe9908761ec67904a0c842a08da2158a4a5b031e6ff9415a42ddceb4e80", + "98eadcb283ced6e945ac7e1384f796a911781adf30380e10ab5c99d0af6c4176": "f90211a082d9f35f03a655d92759de441ac6dc6b8a939589cc53c8555a562ea59f4b0b6da0506de7fb69f6bf9995d8671cc412dc966215ec1be0e5b1a194278e2553a849b5a062c513cf92130dbe077fd9bf98850d68ee93ad63a4e940765d55eafc5643bba8a04bbc7b5a259e3da27885dec12c5fe070260d42fd2797bca97c010d3c4d029deaa06b818bfdd45041c0cbceacb5cef1dd81786e3ad8862b285c8080f88145950fffa02008ce56d3627a99e0383dd47fb73fbd4bfc8e97f707e5d5d29940230524b018a0f0fa0cee58223ca2ff91b29017eeec65abc8b44601452db8f3c515e20a326066a005b38cad6d97d8e505040f58351f0030e4ddf5d4bb4de4934091ad90db631c2ba0298c556e66f30514ae41122e36b8b2397a6a53976df85b150e4345d95109a043a0b05e699364603253d85bbb46dece13efcca657c5e76eea7a2dd34e0e69c821e2a02999cd17dba82afe061f46a026056565a447445afc2df32c0b2624f1b7ca0d58a0c8a996ea99006e07ca8bf785070b6e3e4e857c59287d167ead9f1f63718c3488a04c7536e7b49c60051c5d7e09daee46cf1e23ac5f153546d9cee70cf2e3b9a424a0939d0a4d1f36642915fc382c1c42785dbe873c0f19c4fba9c6bf6e292d341dbfa01e5f037717a17292356a356591449bda46a9573c50fa95e864ea623bef2bffdfa0a89f38e6e7a95a3fcb75c7a983b2cfc9237bb67a842f0f15fca8f6b0c7b75b9d80", + "99793283c952f0699d67041a524c6237d6ec6e2d03190b2a35355563ff756544": "f90211a021c0ad58ab35d65b3758f5f3998ccc9c3bc01e0b876491a6e9d420dfb0287740a08dc9692ef239f47ce98df42412876eb8d6dc728122add4876597aaa658747e7ca0f8d9d9b94b9f9c9e6264da69a1b0a5ea6ee9fafe7ece9f4a36354ac08535fafda02f1c2e09cb0fb588c0c74efa9465fe1fc436f21fc29dbceae439f6abff22984ea08575f79945b4056eb6b5293b6219d9579afc4dcede34adf98508cc48c905db24a005687bba44e7e444ab611ece87ff983df6211aec05b2cd24656aa42415601bfea022f36bb6475a8a25f23ba89bb4c5357dd766c054f0bd4cc1b55b24de3175d4eba0ebbcfd18d4e0c046230a06cf70ea44b8533d00c6c96de46a75642f92b56e70c3a0dccbdd9b551476f3923258b30e1f0d1f8d171ebb490c5cd3622c6570541ec086a01dbfcdcd7d8cb88094fee842296094cbe10e7da0ac33a9f13c24ca14d0f004a0a0c464b2d744334c4094d2eae0ff9d3ee93fdf1959f6fb5ea762e5a6a17bbd6ce3a06d5636765cab50d7b7c397041c0e0ca875f7b47bd573efeb56cf263a7538ab2ca05e5c02ccccf19748364ef91d690478d026d7a57d5f0484cf6c87ee881782d7c1a035a749ebd1abf686ad6c9b1227927402bc11ea4235de5aad72e079207298de4da01719e904939d09b57ee0e0678acc0505d02045445b57c9f8276a369cf7ce224ea005b1260778079538de2e11261cf22c58bcab7122616088a45a2401e304096a4380", + "9a03b15cfd03fd8eba10b1263bcd49e3320b40dc802163f22f26e535af275a83": "f90211a0a9754c5925fa2b8204ccc3d2ef114507e4b1fc48efbbff707af64ee1c708ce36a0f3c6b1ae90edc8ebcfa211b6584a5863183e84916d910a1d9de857834b08e8a7a006cb1459bea1febd114cff98549c1b6ea3357113d39410506b98ef01fac7f9dda064b119234085ebefc3feb800042ea5b095db70ad30657ba7cb426afd25b41eaba02d697ee30aa317bd829ce5861684ef55b05e51ef32ee4636ffb77aefb70038c4a01e353cff6fc4f4ade3d5d2f46521ad5626b668315640ba5bcb1007e684820337a0ac30f591ce13fad6ecf219ef84d97e2de96057e5778f6a50e78ad6bb05a52ceaa0ada8a07da2dfb292dd536ea647684f3faa39f21848d34fbb44f28b005e4d2c9da07a2dc4b3e8478ccac78ff210203f523529d200454306d0630a0e930f0f787e88a0aed97da908f5f5b6c0f1285f9d7a1ed8771e6fc3fc4b9c14b9c8e9f3e39dbe7ba036c31989c19c67c9a1c4b610e1395701993f78c189bc84cc89a71573c8eb918ca0e30c45af08ee5230f84edb0bcce5d3370d65882c901ac4931e53c1cbda7171d6a0c6153e52fa38c4e2bc5715a51e6ccff3729b1af5e976f255d0effd5223aee0afa040acae8ac67b44fb79a17c6dbaf0ccec294d1b11994f5feded8472c8935d2950a0af1901d0c3b5ea744f2abdc95e2d0d3751430e2470dd030ededa2d2c106e139fa042ec2cfbfbad1210a6fafb527b966dd5b03a74b21b169b23772923fba456bc2780", + "9aeec713f6502b641c10d7e153ec1418b342ce5e93f3cdbfdd2128cff5e70248": "f8419e324d03a790e5cc8435209fa13ea2efe0dd969c21fd5bc84fee475a053dbfa1a0deadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10cc", + "9bebc1d8760826b3bdeaf111cae1f5d3793bee1aea2b837b6433feb872f79d59": "f90211a0ca9d7066a008f45873bb651610e549e5c3467014acfa5988afe95a9d51bee7f2a01c83c850b04c4831e00c33941cc3086bacba3ebc39c838026eb734e2dc390e81a04080cdd6db53c0baabea5f12597f025a5390bb98b54ee84a38aa35c3accd5b66a096d8041fa4f569c9d67eddc02e4efc9d0497b3619b037be01175490e4e90fbe1a0d6b774289040c92f0ca0a9111b633548bb5752929162765cd2e90d471736260ba0c6165d79a4fe9e02acdcba2b528e2a3ed721ab17df6c0c8d24e4ee29f43da711a006338a8b9ea91eddb38de1faa04e4784653e71678da5f9af483dbd1e295f623ca0ef51525a1d41ab3308db68b24bad340a1e6a5096a4ad34ce1d777e1770597c32a0dc67281822dbad3723d1eb3351868a8217f0d2a6b921e2a1f116abe441bb250da0a25a782319aed531b1dd816e5aeb83b2aea9fae802cc1668bce919bcbef202cba00eaa4ab5738a4277f8eb227fa2c8af8aa97d633645c4bc261a3f71a52c2d720ea0ab8f334d4ab74d8761e6c011d2e85d9aa63fdae4b967800088cf7462017d05a6a0b4d2f8b7f1df61ffc4fe6ccc3a7bb9ab0a76e0307cb404495f434576e48ff4a6a08f8e14f2e64cb740402144f02891e6337134bd1a7f0ecf3af6f8f6663b3cc8a6a0784141a1f17e9dfa79ab10c48df5d167645dfddb05daba0785f001e58284d2f6a0524dd3e79c66f67b29706af94f573a9b64a96623b84c4fa0ee96671d77d08b8680", + "9c385129b140428377cc02d4334d52eab433141470888ac66883e44bd64c946b": "f90211a0662ecd0c817b96c2bce45836e125bf826eb65256d4e2d4899ba7a05646f0b264a002e126ba9c57bd834cf7e9c61100895637d1f474e6a8c3f8a6b6288c62f5f785a0008d4d79ab8a4561992869cc1574434ce5dd45c3f666ae34b41fd2aaccfc44caa01f447445c3431fd0338a2b31d1e0ae49d31116a5e6f528b9c315f80de2545afba0b0244edb0f298b4e15f705a4b643b00461d4e1871036e53b32137e6a3b207bcda0daa18a3fc58dd3ee7a1757b04c1eb707b7b2e066fae99c935f0c491787c0cee3a0e412f626f76974dd0a0fa8a59645dd2b3af275049e4ca96cfb3710fa6c1c0322a09e3851ad6c4f2b6e5fd091a16597b23a23e4271b9292765873be66f275a94d43a0afcf40b6dd8281e1b2926926d7bdf03742faee61aa52a906160b61cd0e2dab20a00b280dbc3c33d7b51f70240ab01371ca210ace47ea77009c1b484f50402826bea0f442122f660e9ca203e11a1e099e50613edda675cfc2699217fe5813cd927207a01dfba633b9e9ed4fd88ee14dd334509a2610386dff2f7fd8be821ddb91ab830fa088ca387a9b28047853f94c8a96fdb1dde2b7cdca22644fdc6e9370b1ba99fe1ba05cc45dfc0498a1385ea307cef77c33685ea218dfb3c7878208c80e79cc810b13a0142133a777c99bbf34b3e5ccdfc11436cee544d239cc5bc5d527689d963bb2f1a0a45d95c34c2e909a57230ec48d290a7134946d27873500f0f97b5bb1be056d6180", + "9deb67240c6104a9a9624598e2a7e55e59b229c8ef9a0cf056bb732a97844a9a": "f8d1a05405d028fe613b6893b034a6d4de7c3f422099b1e275febc968cb22aaa79ce9d808080a0dda162cbec278f3292cd349dd8421bac2259918cab648792fd9fd371880912d3a0e53b9082e8a415d0d4fff2932d1652ba1b32bcd00ab34f948309965d336df979a043ee191f45caa96380deabf0ec8c0aab555ac109b3ca2c87bc6ba2e082f05d2a8080a0a8ad1c933c49577d8c935fcca82685968563e7e6cca18f47924981198a12c65d808080a0539bb6abe86c897995685b00b9499580a23ae7733456a9320092df93f20154c3808080", + "9e13769faf2ba1a5a8aa823925ed273803d71a2cd9997010866072d07e0c2472": "f8419e3ac6a6e0673d29cb74e62fc1609c73268b12c0ab41033b9c4eb6c6623846a1a0fbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c", + "9e7e35310f859d75bbeadc72d51134c1cc6a8cc539034a789c7fda75ee268d4a": "f90211a0b2f576066a65e2884867bfd41649f5feb9ad17e01074377a1cece8e0b3060a1ea06bf9ee89f7620e065ed26468f88d6c401939e918432d7841c9f4321077a40c31a075a4474a2f595c15b534197d59441ba2c0cd0a93843c52f8e7698abb68eb9400a0ff45142dca5da02b200623f896ebad3d1270e959998a258d31069a54f5712c18a08a6189afe908e00a08c060e71f4fddc55c6b61a161464eef72148cce3c7401c8a0891af137f4275f02c4e4bcb84b71a3806eb324556b16cd2bb9221d8060c5ba87a06d0e9eee3090da66dcdd5490683634616b4551a0b0515fe9f3e0696567df8406a09e5155295550a0873bdaf33e1f4a820b70ffdf77f82f9254dc62867f6d776f4ca04b83112744f1ba554b0692e6301dee4ab45fe4762636f73de939beac6fd54f5fa0ea738429885131b464c4d72bfccc4d118b126a406eec23c261314fcd146269f6a0968b04379ced9f1a0d6e83016e8803f719803dd6e8174c2d12e763241f9fad03a0b0ba2a778f5082b4bcddffdce767ad934b8d27a051165b50438110d1b4340615a07505aec445390d2ed08bf332976137aad8b85cb382e08f60b2dc8e1e7624de2ea05c08ac6ee585a303eb2f722861a38ee593f654b630fc6a094dafc307de98a9d0a086c87c93c851b5702b14180526f3b7032d9029092a14cfd21bc37505bde6c592a086ea9ee23ce96ee60791d95f015ca41fa875248a2affaefd993819522f236a8a80", + "9eb65b83436f844d348d3124e9b2c3ef44159c4947dfc8347f8837558925558f": "f8d1a0b0a42a8f578087614de678aa180122b2745fd15c0adcaac89976a9a4c38cdea9808080a0026a6d09c1f97f5a04c34e47625af46615b3f9c1984c99b75a8d356b7b5ab71aa09aec50c53cb68fe62fb55706ae13f2fb9cf70440ca432684dd7bd8a21312d01380a042d20835c02456b67e93f31a453a8490af69f84f18daed9b7dce4893be679c9c80808080a040c1d79b6255d5776bdacf7bcef7205b63e929aa7e096185c537c6bba6f11f548080a0c84486afd8131bf039615d8600ded2334c94a632308de277fba548e917ccee9980", + "9f0f9fd3c8d6caacaadc2c0947dae4f1f76f905da468265057b8a3dcd5d72918": "f90211a06054510ea248ca03e66a9c30451faed45c5d72fd8af1eebd88ce6572da505ab0a030cba20b2fa16674b4063e9958a82ab444f4f1b342df1b0aad139916a7224959a00a0e0e4961268408114c1df2764e4a6b8ad84ac1e1a3afb87f1cb3e722080285a02ddf54bc06f3e1618b6961043571ca20879253eab6889c1c76885138ee34b458a0ee0ce0d8d9797c07fd5e60fdea603078a51c2f6c0e060dc1109f60eb93113491a007c87662ac00b0f8d878ff73e2570e5e87f719efe3c0d7be796c9daa5b41392fa0127a3d64aa6d75abb47c80dce895f58f1395ed43813fdab7a79334c04e58839fa06cae6987ecd2428bb471e41dabebf82c5677a9ea2176f14412f39cbe5df42df0a06231af66f1381cd4388a4f6c0b2697af67d22d6a5d8ba7dfe2fe2b8a73e6e34ca0e2246feda795c32247a1aca26267764b54cf4d20f285b1e3d4b6bcd9401a303da0973bbfd48b98586b7aa126557accd8cb1f96eda37aa2e2af94f6c04e5a6658c1a039900e4f9984375e65079fb38c49961d0816cd612d9361da53326d4ba0fba1a1a0bd5456268c3e14821e9b9a23add9c87c7c8fde816af8ac69777e544b98cf4acca0c57d1d3f439d98e32de188f7d38f0729c5883935a43c298a6d18888a95245000a0d31a9915cd043b6cb9ebb25dada19686abc84bdc95ca846ccba885353c28699ea09727f7f3dc784ec29839300495239892c0f735944535d8dfb71a9043d00d9a5d80", + "9fbf100487cc3810607a8765e733294545ec457d91f203a7cdc2d2b4670abd1f": "f90211a0f990f5fc37f416b211cb15c30d1658d73e61512fbe29ea0eddc57aa024a0121ca06e3e356c219cd0246762fcec3890058fe1d2fc40ddacc467ee890ae06e6b82c1a08eb1a2140c2d1c48c4490262e8a79b86dc104a954cfd1e1b4b52f47a1ee2e01aa06c2408f18e7d22a962804d27dc31b2f66ae084c67d724589d69d3d3f70b2871ba09fd74ef2edcbfca5cc5ac770e11f605838fa4a5c53527da3b11496ff834992f0a0379cde075852914e1cf99bddcff1268b82db99f7bef98e3330a0c16f6876f0efa00f16d99b8149cdd636b00e3e5623f709399982841ab9210acbdddb06e1ac2524a0724d983542d35f9986910a8aac0fd3909c9e78f4a9450e20511e96803600aac6a0d8a798e57e3bc97885d079dfd7e4aee9526ce17cdffbddc30994d7e46d83a478a085a5c74308d06c4d2725778c384e74f64f5b99370d31a13588f966fb0bed6241a0161619213d417c5da4fb63da46b4c710b2826517e32025b92d8adb4a9adad6e9a0a867396797e6ade3c7e897a9eb1ae5b6d1ea58548ea7fce17f841555971dfebba0ab737af649406f1fb9229541a5d8d47f8541c2b24641a0424f76e0fc76bbd7dea0ce611908391933502f922626b01678aab1ffc5422e6ad39a4e475c64b97a259ca0a90b8f73d1de2507edf0cfc138637359dcef29ff9274699adb737bfb71946f8ba0084d01bbc325816f824a6a5cbe87962f9192be41c55a294ab54e5d282942830180", + "a0ceb26f746c255af4ece54c60886148fbe4028544da65fa85551dae38a88e4a": "f90211a06f4400044d6cd7ba46e2d7d8871225d707f7d8a088bae46caf65b123613c35e2a0540b2ac27db525ab2a3c511eaf47e0f0a756419bd55b44926b3e0778c5170406a0589b2230042938899c9cfdd0e63d41f8623b07e195033477f127e1ef38efc4dea0f3d5b43fd87af29d5885b00523d2964211725af1f7335b046496205e1025c354a0ef5a8f13718059121ec9bfb19d8dfe258c0ff2b2a60fe4f96a839ea679395615a046d131fce2822ef1c7d364d034ebd948435338d7edae7eacd1bd7f4c6b1123f6a09614d3fad0e0b8e4e61ae523321b24d8712cbed83aaefa0a3debd9febc6259eba0100d28dff963aed42cc0b3854bd763ad3baef21469afebac87533fa2d0397acfa0883555dd641fdb1ad00a3ac0db9070f95acf650f1cdf7150576220f2d5c6e1eea0aa966d86d1f8d50c2996158d1d4aaef9c017f2ec75cbffd78359b5ecc8d697c6a0671ca898acb09c2ea4b081e263bf931a6fd925a3c0f98a3426cad4d0234ad878a0fbe51669065bc1dd1477fb8b9ee595343c1d4b5d24a87e9adaa19085632f4c6ea0e4a30d4bfbf89933722baff5e83b285260167b58d349a2d541462e57117bd1cfa08a245742966cd8936a616e4a191d55e339fbe2042408798465af9b95b7a7fb15a0f1778e5a1b44229299048ed9f9018f9f86895ef1b824d89266289eb0e0b56dbca0dcd75f1cdc8c565c0695ff1bb6f2ce71570f10427e443c2cf3374e5e71cd05ba80", + "a1522c638612665b436e99f6b8893f30e6b1b38330a950bdbdebbd3810af281e": "f90131a04c0127ee026af7b877383ceb386a28dbc5a20d8850161a8737d698a658327d6180a03adee01c31cc04af9715fab15d10926a0d65132fc4b391149a980d18adc3ec66a049e310b589396e2b72d89336ce564c5379b6577f72dce51f36b00d1ad39f2a43a0d273288066c4a9179e388adaff674f5a4d46a2eeeb4cd65e3fd4d1fc37c86e5080a01bf07171e51c5663761b42741e474c98a8aae34b379d3307c74d70c96e91f7e5a0daa16d19d32fbde8635db7194857f962cd65163b62b06ddc2276c2c13555b916808080a0b7b0a32b025d35d821296c9b8e94a9835d103fe564d6ddf46725cd0bc2519211a0533f645772f254fc4fcc317e7bf55a3e5f9aa684ad5388a8cbd71cb7e102bbf3a0edfbbf076d9dc0e497939f5726e88eb23d95e05788c5de0bca82ec28f2cde03f808080", + "a15a461d184d3f48a58bcbb3172587ae8b6ed30e99bf5da0148ff8f460aa914a": "f90211a06985a765b8b44b91489b4b639b1db89a7fe1c29c8aa09f5544b710f3d8555729a03e40c2306fb0c552e147dc0cd7c5080c9ed303c98ae2e77ed4784287ece59b55a0ca142215e9f60f3903b1e15affb95a2ed238c778f3f419662d4abb8ee3dda877a0866af54c30650b7d14dc5f597a711166b9f9738ef5929a222f0ea91ba1107edda0b522457dba10ba47b7b81a176a39c6e19a15ea0b701a5da378a7b1d41b431723a09fd28c5a5aa223ed05e82692268be7fc8624f47a7929e24dbbd6fa5555fb1d18a0c93777e36763b2cd2ddc5694491ee19d55b8637258680583bdb584e6eca8fc2ca0c8aa39f87ab618cf6c590dd0b5cfc1640902ccfc6724274869f63e30b8637444a0b4f042a96d2044e570098dc73c67e70e207d0b982e765a020762282d34c3ee79a01efa949758a6fc78a82ac6ab910c57c6014013874163e17e54156e0b49e986daa0605a1dad4a673641adacfc97b5e0a836ab31f8c39e5c652e01ce446aa35c7685a05996a032f8544c6739744133931f7218a31054dd50ef144f62961802ad39ea5ba0b051372af79654a3bd581fa3522b556992f9974b39b981133afb20b1e03132a9a062b7c25373d2369c20a1a596d7a015bde3f08633fc28ad202076eda75dae1de6a07724c331f4d4a6f63bb7f54a2654019b903171a4992ea1241886780ba8850d50a01ddbd4506039724e4f186c474042a6c473ecc8e3b3e673ce69461bdece4a4fb480", + "a25a782319aed531b1dd816e5aeb83b2aea9fae802cc1668bce919bcbef202cb": "f90211a0caaa04234ca99fb0c8d481a62bdb442219d5016a6a5eb98cd4d122597b7e86b0a0b0a707c4b74a5ca998fbedfc248ee017db09176d6bac4fa1d1535344d5004cc2a0519fd7da0f2aff45189cd2253e34c531f840a186e21751084a0f0d8a0efef2d5a080926ba0200605c6e1cb0bb853611924719373e99c042eb8c9f50edbe5424210a0a77067d5385727a017030502da37ee8139b600d5dd0c40a253bb1a936a60535aa0d2d0dffc315aeddabfc34620fd32d26a69d2b1a29fb0b3aa5aa30521a34dc796a0be2980c5b60d3628a2fc3ae25c3559efa6d34c6f8a3e7811355b1229f2dec772a0592058d868b5105505e29546a3938fd6ac48f450049d8f6045b57ad69be44866a045ffa240ffa1c84ea18ae203beac4166f18e6f798e679886cf46ad40cfac7d4aa0461a841c8865022d1eb1709c64bb8a93471067d9c202c2118095c24f74d5b3c2a01c185bcff40e23d5ebd9de60322d6048b406a3bc1504c245be18cfe02c26fc1da05d26412aed6311ec54053fc85a35c92ccf3a176a421160ffe36506a842c8c4eea0c31ed6baa25fbe05d07c22edf254a4ff25af1621df818bfaa1f7c99ff4c0f7bea0a5d66ceb25428dd7f2fad7b6ba7982b1a9ca59e7f9fd0882fff3b62f3ee2b23ba0ac4468160a32e439a4b573de5146427f55f7669915cdfc28ede09abc32326698a05937e092eceb32126739feec7275864c5aa892236ed1082c8daf0fb929002f9f80", + "a5b9ad3b312ff578213c07cf92825266e9ced5adb18671ace9fc2af4bada0efd": "f90211a054b5b7a05f312eb11239ca33d57d07a7a8c02a090298187795104b4fc3577da5a0563134f703c688ef0aeb0e30be1a6f5f74c1110ee7cd824b25e84c910d838480a088aa5b3f0b69ab5dffd2bbe0fb252a16a1847b5f05c4ac5f3a2f0b91a9307801a0e5374bde4be096c791d5d4d42b2e419221b1b639065ee1434f99b2ee41baead7a03c67dd1c4b43d6cbe75356367c14a36ddb4682fad7bc6870c73b157161a8a4c1a0e4019c1ea46b674932716a91967160851c8b5bd84df75277900b96cdf4bdef13a05450f0c23d0c44a8907e6bfa014b80a7d067bd346b2ff1cd7b466a5303fbf31fa099952008109f2a56fc6e573aa0dec7284301a91e821c683743ea692c023464bca06785e19c00ff44309c668f2bff4fe520d15712eb7969f275791494611a7d651fa0818b80ef1b6284136a81181b9d19fe1cd8080758a8514c4ee11d5b1d4e7e1ecda080a2d2bc7ca4cb34aad776432a20fb21ff59666c348be7a62ee67755178056b6a0327d0684b68921226f54f0c45d6a67750fb689613e19202fbb4ffbfaadae012ba0f2de852c058f5f3169cbf7aff5e81730f10d17c0013c88113c0534a73f22014ba0dc7bea45bf94c64c68062646b870fd35e324b5aef69ecef78256c249e2df6ceba0182cc16311b2a2bd5b5074fbbe0110b6564f662a7dbb45bd0553c329c81796b8a09435b8e2a23e2ba181ce40ecbb776f0c1ad3161f60095d8d4c9ea1d0f5df700e80", + "a66d18c1e708306086d82e2aaac60f0df82069aa5a68458b3316b8281e8f8c23": "f8419e3fe3b7b5e9c0b5f9ab4156c9a3bb3f70101c40e7d0a60bb3051c93b34b1aa1a0defec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de", + "a6b31a088fde8f24108538e982d30efcb835710a0c7927446fda0c73b3c356e0": "f8b180a034d9f7fbb5b4386919f7f6b75502c1c4a08b8d02ba2d1d387c4f63a8b424b9d48080a05017e007e05e7e7cbcbf30d7875695e2380670b10b1e3db65a8c00efdc0ebd19a0a39f1c90e1eb352fd8c4865dabd9f7f83b7b7a68cfc32ebcf4af7b30a873c1d98080a03eaf958e2baea967a10b70c9388eaa4a72142f4c0a143577f8854510b84f188da03ef7b9a11fc2171f2eadcc5cbccc83f2eb9525bd670c18c3790923e7f214c4df80808080808080", + "a7f2ade61b93ee1069dd096a4febce59715104cc861ce233a3a32446584a5a92": "f90211a081d22ca0fb6cfb0dc2d996e379dcaad03ef4a19769972962f219e8a62c58be1da07ceae5bf95229b808084b8b1224824f0e9323559da650eb4640e9ca91810f3a9a0e92d99fec820caf4370b15f992ff9d24df20ad4e2b2ef6501ae3a6743f5f2d06a0582d43bc1b1bc2e9fa2443e804991a7d6601cbce9dbd313785905c2abff3e9f2a095b0daffa8cfccfebb36f0c5bb7c7407db90f41e4c7cd0ae47fcba2c11f85a38a070e5cab0558785b3644534a8c33d0427644d43bb251103b19b8096c1b7c09697a0f5658b024aa060cd251ee6df10d57463fdbc1ec29ee64e2eb77d8d63a0369c9ca03db13a12eb71d23b238d7c68c6daaff0fa9d996232af6bba35a404cd24e4e7e5a011ac11f4ea57192d871d84516e6179ec082d12be7cda9cf30c9051c3f0c3f60ca0c14cb5cec4e826e4a57d6491b0c9b294c9eb68f6ba810385b9c7ddcc1b08414ba05d62679d4ba08c2a20ac49b3a25228ff57f37bc9d68f0e0d523c940f638e1d18a017ec0364c26fccf9f1244028d15408a1a98885d808a1909471b74be5b240c8d3a0ccc99a5a66a3928de1ac6ba21996b17260f68a846bba51616e89839bfec051fea0306739a90ba655154a4ee27ef02151d9ad79be550343e3282de894c3a4b2dcf6a089b84c052ac985523508226b66ac9480fc9be2394107bb20baafc9f796cb2d8ea0de6aa6cd1ad2e90314a32f71f1878483523b2b9b26c5df94c3a8bfd44616ef3880", + "a95cc8a58a5468c6f2a6cf77b2e6214b751bc7361022a5cb7b296de4b3ac3e9d": "f90131a0c8e9065c9127aff6e001039529b6aa8c96b5ec70a708223e284ac3996cd20585a0c663bd9b0f912a5fee29c8b34f7d0eef062fd440522cdf1ab7fd3ef8cdd630a4a0dcc01c9454d3937827f01cd68262a72d1d10dc3fc94336f21853c300c3519a91a0f8085bc71d2a16d0b7dec13d7d9e4a4de8b86539fb5928dcb50a7e32e942fc0a80a00a92e9fc753bfed7c064e7fb8a4422448feacc127f2ceffdacf2fb9f7d53de8f80a0aa602959a2ab1165c811a0ccd532b3a6b2389e142ac5197343874c8274df0f478080a09b26c90927dfb2c38adb236da9fbdc287d65d26684d8c0d843b134a385a9669480a0bab4b91d34e8a5d7ebbedb6f50208979d6b590e791e72cc47a4775e3df53d32780a067a374108f70ded33129518bb2f2bba19ab25d9b8c9417301a8ce38cd8369d448080", + "a9754c5925fa2b8204ccc3d2ef114507e4b1fc48efbbff707af64ee1c708ce36": "f90211a0c878667754561165dbc3ce5b567c306d2dcaa3e821df7ed0730121791afcaeaba06f940f58697e8c7671e1bf20a28554adfed2ca7e781d90519f85a86934c358c4a0fca4d03f62e86d64280eb85cd80d8e738958de3d8beab8d9ebe349565cf27fd9a0c74250c0ed316df283f21fe4484133acf27107015fa4202fb5d5afd410931b38a0d8fea56522f7a124e42e78352e9ed400bea9de3d74996288f22e66b38da15074a01292ee74c1b3cd129314cee68b64cbda4aa4817645d96db9475bbc3b34328471a027f0bb50bffa70575bb1c1a81bf1acf1b12b014dc9d1451bc8c644fa424eac3fa02f19b6bdf88006a8f8d96bade41c90093f04e015ff73df678c6368ccc23947dca0fee24299429eee0c6c4b229ee4106fcf4eb9c09595180575edeed5183cf0e2fba003d785b24c1057a79d1ada09aae526948e48144cf46e7b432e2f4fca87f8ec41a0684a107b3c20380e63a708e04775e611605f0b7f158bc2b8ea31ca5a8e318ac2a033df31e890c7f10da97a88b2bc5a56292e0ea8def1f7ac1383842b1a0132bd95a08f5842e04c76dd97c971d222e4d4511b858ebca22ca04c630f30afc4472555efa01f03b34889f5d5af87edaf183776d1a1db0121b99aeb41a654ae63b4ca58cbe0a0093d5440d5bd371d683db761b9940fc49a78bba8821630279f256ed3ccb1326ea0ccc0691dd3a1080fea65a492516eb165c6ada1b55e2f350967aa5c0bca57891280", + "aa89e2d76747298c8584cb2e39107fa067d3252be2999bb413d7f750f6a9bbf5": "f89180a075be8e36e4490bfc5b4e9413bbea32aadf08fb546e557bff546ed2e334cc48c4a0fcb475af75a8aa06dd0f3a827955770c6059f56edb8914c864c218610fceda618080808080808080a05f1dbb342b2e0817db500004b70edc5e06117226dfaf68c1aa7ea363c78bd8048080a0490133ebba6dcf6effed7209330072e44d9c0190fe6c42e7c1564a9140f1dc028080", + "ab42b8a0a4ab70cd5edbf515b6f75b1558378e49bcb847de06edf9bf2d675722": "f90211a04c65f171f051157db613af85b48ec47ca272344a2e9682800df4efd786672080a087780dfe413f4253e74a9a3b863cab13f4cb59e521288240e15eee005a63c072a0d8b6b3102e04b0733603638cb5d11175b973e6cae9594c652cb2b9b4c6b90b46a0cadc667f0559276a697eabe4b5c7f6d0ba825c8d92f22963743dddfe9396ebd5a09de0c2b932d24621bfe5375ac9dbbfe11ad78150858538cf28c51fb10f60fefea0798374be53606a2fa530ee0ddfaeab8b2651cd0e415729b1363c542e158e3af9a0b46a4da81d111638879bef6b56eef44c94b2d74a828b4c5d775fceabcf7c7628a06c1b92c85bce5b7393737f0348e12b829f234ea0746c421e3a48974e4f2a32e6a06de8aa26d335ca365b36d412e8692c19a503720232f0ad7d01e6c47dc6419633a03bfc6c61d6e8bf3efdbf07cb42cf37ee778307f73f97cee36338dd74a5a6d6c5a0491ed6af3395c485ec5d530f6adc2822e004522e2f73c747af028de61935efa7a087eb394950588aadcdc7f820df00600ca00d75803929d7a9391b3a52fa81392aa094e82f5a816b23ab8154c5198b819f0fcfe3473884eafc933f27729f9ce6c57ba011a3ea8230d1bccac0758f047416c7b4bb0003805537405af8682b53406054ffa00fa9d8b192a42b69d92aa3f62137981ad4e3a05cb62813bf8ac25a4828153d42a07a4b3b26b7de97085be14a51d1c6824574ec65f9a260646e67778702751e677f80", + "ab8f334d4ab74d8761e6c011d2e85d9aa63fdae4b967800088cf7462017d05a6": "f90211a011a8d54820f471b7af2a8fc2431cd10b8e47ebb50006e995f5d273034179db42a01d59dff245f612088a66f9dbe74d0f1e63dfbcf0b78dbb1b55976a857bd01c34a0b2b21983dfe447c7f53d1235abc73c1f51c42cd70f0b59ac225252ea94201e02a06672e5cc9c527fc4fe2bdc4944321105a413bae8992ec1610c16ba37c0523c76a01d7c6ccbf22b6e84ba70a15e7922bdc881c4f4b54f940478dbca3f8238bde5ffa002d9a94db206b92c01503a33f3bc83ddae6f30a515c27e571d15a7fea16424e1a0a716f3de6ee62ff1a6d9802c055d7b12161f85b91327f3a96296d3b160f6b5b1a057633015ed3e748c28b6d35a36a2f0ce526b34279127635929a8e6b7879838e6a0a43e0f5c229b7aa35ac43a0566704af9650d4bcba0cf11047a1184a31e5f5023a0b716e117a0879422ca0f7cd497d6486447cbf52e6c3bbbb907cf394cd6ffa052a04cb9927966f3e71b4941507d3a1376c7a2177dabfbe3d68c71602f43e2836229a09bf9bcc7aed4e7c2ac98ad840f8a230be6efafa117b115983b8703fc036ee079a0cf5341308f7dc7d0acf9362da5f40847b49b79ca10ff58433dcee9f71570ce24a0189978207b09d7dd0e9692e40169e488cbeed3e109f4211e6b25c11f2cb8f483a0d102b90e2d2abab5f934a04a068e3578d7b94359c9679992116a61a4d324b3aba0ea27b858729203a5c0cf04221c084418433da81dd37edf90ec76fdb694f18eec80", + "abd9d3ec44bc5d2068826517627794d98005456ad6c30e22eb9550c6e1a2ddcb": "f90211a056fadd9664a64a3fb3ead6219153c84135b2215f3fdf684ea995a1c972e7c3b5a0dbcfbb5d3a36c5e0e1a28dad29de7671dff3fcfaf290705c9dc02e524f2dd062a0ff9c1514ed9036da67d464bde223a03687e5cb2226dadb636d6c16ce3cc8ceb2a01f34d0b7c1c7fed6d19b82c7f008370002f1272108569f3a8a3e177dd65a0ea2a01ea1be3a80091c7126e1913feec45ae1d13e01826d0bf9a6629851caa6783675a00de1402495cd4cf792b93dd477739c355f386edd5b456392ac4666b927ab6204a0ad4da8805249735301c7b4eb24561997f0b5c11c3c79435090abbb9b2b77336aa001f4b87112d6da757d12df2465872f651e04ac747381983013ab279ff942f0c7a0f4c5b0c9415ade3383cf2616de50fe30c4a955df18127b9ff4dff4d53622f17ca028506b3a07e0304195422bb3f668f9b74882e8b61c3968186acf184e3368d6b0a04d4a497b73f396f2b00b9c600251a6469ddeb11e0056593a451bda13b94a4ecea0f2f5ed051f21664a2c24fc480c1240c56a3df2a3cadfd6f9c7ac98671dff93a1a0a430c636b733540b42f46bc5c8dbeb4f968bbd1af48bea94b0fd3fb08baebd6ba04cd75689491bbe990c23afd36c12a805ed0f08233e38885dcc24b147b8577b67a063972c80531389f3a19f6a9f9bdb33110d9fd7ef5d061ebf12a404d840e7c169a09695c4a3d32e5c1faefec9da83a053161b79c67d44c23e77c42f618fe8d600d280", + "ac3fa07afad499090ee0504149efd5ffbb692227f13ce4e711c25afbc42e6808": "f90211a0e0a0ad7cc2b1ac161f955dce45b76317570076357e47fb808c2403be8fecbe5ea0e1f98c7c00ffec5ed047edb33fb3c6c6f09342f8d0eccf8855626cdb9c0e8212a03b2b1304aed49717ab2801c9f549f75a8fa2ff2836bdc155bdc14b917b6d5658a0aad0b2d535b4f676d5f2874126abb31626f3ec351125ec3195acd7d95f5907faa0f2cd55fede94befb7123a1627697080340171ed746283f9e602471a189d0b7eda03f2ac9752cc668e5494b2d8f7cc0c77a2ef07f74349fef1308f432d97d29ecc5a0588d8d1270409561d2664cddffc7a40882736a8f04186773e882d83b0435e8eba0a78f6630fba285c7652147f8aa53090f11e13868f7da19dfbc9ecc3d6886cb89a02c8eb136b6ccaa84f14d60fc4f875ac861c295feb70f23dee63dcccaae793ed1a00b811e5197aa52071eb2d8e179eb1877b27b0f4d1fa02b05a705b78ca87239f9a0497c5287edaa225b14f901c1c2cd8f996affa13ccc4ba07e9a70c01c2845ed72a06b5cf720889edde5182558c32142e258b09776ba35fe2a6382b3ff8505ed18d5a0a631b8ba6c18f5ca5f6faf8eec96bed653c2c42263137ac833a93b3c02a6c31ba0ae5270af6324fd521c7be33c0419f9d529d4fa86b555e7e17d92854a9e3bea69a0c0cf2eb86d07fa5a5eb15e0b1417995ee53be7ccb5dce2e82fcef7cfeb6d85b0a00d65773f47bc8d6d9e38fea3c666e4d3392906e9f44ed5be6b618965b08a90f080", + "ac465f2063b68d167cba3e4ee5c9bf7989675f46db8103a38e4e5157fd3bc21d": "f90211a0f2bc25e6f615eaf171f964d9d77aea88d28e7c2daf87b0f23480692801a35b26a0b0729d86aca05af309571f89b408ef6b1ddf574a94608de103ecf57c259c7cc3a074532e5129f6d7a14bc5aa655e6f91810b4d9dea69e26df0b2ecb6be63a1e25fa0ddcafde5dc36cbdc383ea9d5fe65152a5749d3cb25681e87995870a35c5fc509a04d617c974054b1feaf8fe32b2c987f53b506925139b5d5867e57b0eae8b851d3a0e3463905e69f2035c0c59cad24524eb638b4b547a91cff6bead97f3653dbaf44a00774e8f7cf423b7ca7b0fc834ffceb4122752f19b1a0ee01613a078d03ac19d5a04c9b2d1f4327da5ec86d6c4bcf12afb6e1b132cab456d493ba9aae1c299a72eaa0cb678235d1cf7c037e991d646cce70d3fc7372aa029533f3ccd8686500f40168a0bdd6f49ed2416c54ab96d41dc62aa5ec49992af3b08f4daf83bbe4ef5e506b6aa094627767aeb7209fde351b766ef94db10c8c22acaf24013b046b2fc09f6efeb6a0560b4b810d30c59f0c0f76fff4d920b3b86f158a7d6e158051724c80482b4afaa0c4df07da964c84e14849ae7c96c1ce0d816cbd8a25331dbd224d4af7d6a41256a07f5d6256f99958039ff0f7ee12613e7d33fb823feabe225f19aa2b4600e463daa0df21f07a87990c1cf36ffc9af55e8c53be75357dab79e2b305a8ffb369c3523ea03c928e9ad2c1be43388773b4665e0594f694f626575bf0cca09b36b15a1d2dac80", + "ac87e70fc7ef7fe6389288cebc1e790e25491bfea114e9db2312ee688debcca3": "f90211a0364d76b7e3b2592165f3f230f886386a3109deea68cb89f02aa0889b35631081a09722d35a4b103a745c4457f703b4e1e75d87e687881ad5ec5bc8c4e914bb7abba0532e4f5b444817ab51c02c4a85a4c41a0105a6cfd6122617ca208c1fa5ffe9c3a0cc7b4c69c7e6c4242f46bf988afdbe9a55e5d272e44c5b4a8cc2c00e259f0f17a01bdf82c46f6eea6f0fcb36d462b6b95ba984a5b9592b75c9e5de903001faf77da072ec03de45e93b8522add47779accabcbb4fd37531102d78a83411e02cb199b3a00c0cf42208dce89d20f558d13d476a0f4974b986e9d8cb1eaecab6dc6ab4162da043e7c78ba174dd20a60619da5e1d34625ec653c153c339fda9fbed93e1c9dd1aa0faa624afab2347435e173c5ecd3cdc07d5b7125d249be305ee9b9bc910290bfaa066ebee64061ffe17e42308c65a7bcd5bca3a4e5a6c9e06c84a5075b386ba2219a0f623db5e1dba9bbd1c8d0c1a259bd73d08d22a6ce925992eeae96e7516fd655ea0f243c5ebc362e52cfdafca58dff732e9fb096a132b859e205326c6bc0463835ea064c2cf9a8e50f393525b72c2c70780dabdf34043cdbc027f1d34459caf72832fa07424ca8fae70596d056f493bdc6131be524e03d076c9052c70fc3f80e203438ca0520f4410b04f734218b8a5026f6c727bf94dba55e96fc950df287effb0b7fcdea07b9864f4d865fad4c3c4e247fb0b8d8abb6164c25d12d7e64ce47f6cb5c0127f80", + "accb7aa10bf06a11781d12757829736dd24a29ef152ed3dfda429a7911e6543e": "f9019180a0c031ced7b0362485d07d925c38d8999143e47eed221554eede6344bbebece10180a0d971489d3c532e28f8fa13a4190203823ee662109245f91a2a9f556bf6b7912ca0f1dd6739dae64f573d13765ced3793114d5d612a4db4cee07e0d6c90f44c2bd0a0ba3b50611b8d08e112f786721ab14be73cce9c08d56415cd99f462d9f7d0655680a05a91b9febc9310fa629cff24d501522817bd73784b3fb32b0a1cef0e3ca34feea0dbf9d303b1334114a61176fea25539864b5976fedd566a715651c10ad295036da049c44b47530735680f1bcbfa87cd32026655333e67249c9513cfbac298e6e02a80a02dac67af3b0bae52c153cf4292653e89797676ee05cf3f69ee0a29d3102d1e3aa01efab90c36ac52c32a48f0926b0986b02a4f417a17492ea078d17006d58c465da043d6f31c6976b88ade960ef3a47d63637f44a3179b41b7d220cab1e514559d4fa0976e1db067552c0e2d2aaddf847e5deab2857e26d1a365450f683e23066d5bdaa03c580ffd92e72346d3be71cf8abd53f2a419943a269a0425439f3f265a680bd080", + "acd4dd99d96729011fecbd6161851ae15b8e2ff619449ceb7ccac82bb6fbd0a2": "f90211a099144c1bd273efca614a1f278d62cc4a33d5d2d8d95ce7ce97dac1b7760f9258a0e1eae345d43077524d2630793ab52d9d6e69f54ef88852cf59f024ec96269c40a01a59d53bd34f51741b4b3021bbf76a0b5b27f93b8444004074ffd93590abe4fea0bf6e3560323a881341dfad581565bd18cfb4708b88b687284c7df98fba587d1ba07f8e5ec72b94204e19224851309d26c7c2e294dfed88570889d51df068fa9010a0e4eafc5915fd9f5b9a8ce6c3203f1371db5cfb93f0dc5547e7952006e7bc5da1a02f4419aef30e06b2282a49724f44b97b59202c56294ed4027402a1ff329c677fa0abd81c7bcd5cbbba8a9fca75784738679a5a10f02536e9f75b6f522b7319707aa08524023b495a8a1c50f1425e674b31223ee5887091c1466f30d80a6b8e685f44a0b35005de179668b12f7828bb1afd51cc709f6d05a3acd3573144097d442a16f1a0238bc07742627216becbdba13c4dc28de34d1a204c4f5c02d733ed9ccdb3aad8a040ff2f046c5203f41a784d99bdb3e6aff7f1f72e115d9980f042630e5f415f7da0b918228faa2bb810c79acb2959546ddd5ee7838f5d80fc0771e9fcfb8efe6cbea0a1522c638612665b436e99f6b8893f30e6b1b38330a950bdbdebbd3810af281ea02ae93a3b977584bcce03d5a1a9b17a173e5539f3b329bb5e4c4a7a23b368a8afa04ce53a372ed0fbc774237b45d8c20565d540a51ef37ee898be0d0feb654f104c80", + "ace05f43632b41dad7e1dffe274088fd9f245b1bd4964ccb1773e7f5c601aa2c": "f90111a0e21c522e7e62c0d75b3013a76af63f7638d16916855dc60234ff558e274892d080808080a05f36258fdb0565afdbbb1278286c64a542b52d766fb987fef07830f6a81c3d0fa00976838ecb5884eee898f1449ef015447145455023b7ea37d8813f97e9f70147a0e88b62a9be2a2ea43fbcee4ceba83c728ad564d6128eda8e197115365f80485a8080a0ae4e60dcf92c6ac7cdc2acccc3e622e2d062ac24cdcd5ad7c995940729abd115a0fc939cb8d8dc1e0bd0c07addf90b80ae3e2e1bb6ff3f024ed3e33637ee82f801a06df5ce8eaf3f8ed4fc76cfb3a945dd222a0ff67c83686a691860619b1a56cfe980a08de880fbc0a635b2db327141cfb6d65cded691a8c5dccd1ba92d6c8c80e2c22a8080", + "ad605d41243e74e8e4cadd453b01bf90276de82bd5abaf71a994aa398efffaa1": "f90211a0fa74736a21e33d7556204f836390493ccba824e919cff1765c5916f3f26d772da0a873b44ecad60d9a862775ceed81818554be4b3e076747e98f9a9db2fcc61c25a0c43bad2c9d0a321d8f72ae79a1d8e395f7dd4d8ef2f5dd7998e35624362bec81a002788dddd0412b9776b73bb77e9ee771f7458bd7499b4b1f0af897f885c7c6a3a0101a547f0a43bfac519164eae7049d8e71f5aff9210bf48643e8f0824070735fa045d27d8675f4ad682b40f1a0e3d7344da4a94cd01f5705aa22e896f8dd9a9a39a01843315596127eab409e9c4c2bee83fb16b07c6db948c40cf1d8581a8457eca7a09e5f037834026e9f3b4ef5c1a7e78044aa46d70c27f41564f3b18699629b75d4a0cda827398e41edeaf92e4548905559c5dc76088cb582aa79ac5b87eb26c24784a0ebffe75588dcda804ea8d403bb65d2c9cbd41d95b82036d44c1b6e0f54e017e1a0220bde82110485cfdfd1c00918cf206bc6d18efece97eab95f8f11904d65bb79a0e65cab575db2cc72ad50159495969ea543ce5bd22489af8b39fe9baa211e0f3fa018538ec0191b4f2074996f398146c701b83d31ff21bdc325a166867dea39c321a049f50fbb24a316cfcea301e6535096cc7ddc49620e0276fbc6dc73250b1ca165a04f22d78a5c1876a27f8b91ea09f447477301ee5794bd07d336fc3c05f9ee5e68a0863193da4ff2a963e9719842e27613c1275aa94affed33a0c30e133341c6db4780", + "aed97da908f5f5b6c0f1285f9d7a1ed8771e6fc3fc4b9c14b9c8e9f3e39dbe7b": "f90211a0ba85c26ba3fcbf51d1229ab39670bd30c83f6fee3ae8033309f7d1968a992833a0d2f870be900a8ca24c8b4570a8a4201d05aaad53e8c7b2f49d9ca66677a17abda0352f091cf3b2040a345f06c96e7951e62ff6080f90fe9dc01082c892e492c191a0414ef6a2c71a93ef5ba86b6973511d305b4f05b072b5f4d77f6e156547a026eea00d18db612e27e814d4ba207d1a911bbd6cd85e09eb86b1630cc552a3d95fe840a0fdf5917239b15a5fc0c011b0d14ffc734407553192e781fa0213f4330daeb60fa04cfe2f6080ab876518c32d879faf763d0b54aa131483c98f5315d75fced3e826a03c374e3588196c688a8c179245932a9c1e9849a89754bf1513fcc882cba0df3aa0f41809bfa7a366d287eb28bed71fcf3bb39da1f9061b42ae9f5dd89cffd66e07a0d6e2226f1e8062f80d891ceeb0ac2e71c9c47858c98796427fd4688d95be19ada038fbd60ee2e800e2a8cbfc378299255ebbdd427e1917c6f7401e8f201311d48fa0ff471d5ff539fdad83b45864bc3cadd728c6e69ea4af8561b02bb4d52871bf18a0111ef78c006c10f54a6402a31d3984c90a0e199c6b468693af13cc088aec970ea0904a6664852dcdc7c3a19261ef970b1c60c40e7a12635c5c25f3207a928e17b5a06364e98d6366f7d3282dd1c8242d2dda97ec1008d772a905213bac43b7fd7da0a0b17ffb03a31f33e6a0ca87745bccaed29d9c9208929e8bc8f804a74fd0e295fc80", + "af7a421a3f3f128d09d801350510cfcdd9d576c2018e6b8843bb113fd8743d8d": "f90211a088c2387501bf41d7a39980d66312be457dd9b5ef855ddc09a6e625ce1d81ae42a0ff2cbf9575f2f410a1012fc4756f000754a5840886d0ebbfb820e9bfb80a1e78a02aa04c103c11b0b6438f43d1f1f8018f9b8ddd5321d283bc796a00cf871bbab5a06bfced91f24b6d3ef1b3ca9b22e9426714374bebae18f2803c4a008c009ff1bea0e72a2fdc4c2de98ec2575b1854baefdb8c83803b99fbccd262aa211c689904d2a033b3e1c3e2d3e98ea8a6ba57071faf66808168f60bfbf1136ee8012468af4377a09b0a34781ef05d87d8be1c11f516b92943f4b9002cbf2ff4b7c7da0af2d8c71ba062214c7663622dc5ace96fc040c82da833499a692730eed3b12cb8b92c065c05a0e51eb8a91a53d9b9723020c10b9c90c9a5357683b2294c08400b3e18cfacbc31a00ddd16129b717c4bacb2f89ec055fa1ba20a1ac97a77719c14f950247fb9eed7a084276c2d0dfba711259ddbd787539fb4e8b6f821322a178451951756bf9d9624a0cee7a74be5c63b83ddffb8dfa21e1c0b888a7a5daacdc057446f1b040f9628a6a001ea2dc751637c0b1a65a56c6102d9d51153b7b95f674ad0b5a7c99c83c236dda03b22cd5215424a72f16a168694b974d6c4cb2d84575e24f32c5d4fcab90d06d5a07d7de541af4169b2b0ecb94f161619e1e6782297c719b5879df4102f3b4e616da03d211c339a3e6b614464eab38278a37d2ecd0d687971e10a5ca621f660d6f50880", + "afb26de13662effbe2f8dd309a5580206bfffa3b79654a3926552ea880538364": "f90151a0292bc7cd7ea2d4501db110abb54709436979e740fc0f01497cd18acc184bc3c780a024007160aa7bf816f352c94a8ff18e0044aaf6f81626cf5917d22229737498cc80a053c344eb44ea227fc8fb8bc94401370ea6fbc39211cd97b59dc88a2969b8699680a0665afd6a7bba8bbdb7b67b0ffdea7e0bcfbd72c73221771ac5f0b10ef70d063780a03ac01a5453ff71366038daba0073228d0063e5fc84a4963a330122ff58c8719ea00ce92d05bc4fec04a835d497cab351af480a35b914f0460234afd62f8a7538bfa0217ab6a2d535929451d74785a9562eaf02a04bdce0fe20112c35cd7f314f968280a00e4fd4bebd34b098509b5060b0750605842b1df66324da0a0043cbfbbd9815d680a0c67861c6d9481c1a7a2179d0c4dfc77de6402eb05525f7cb43355da4c8fb0f32a03166579bc3591547f89db41d2113ccd0ceb03a18b344ba5156acefe4ca891e5380", + "afc7ad54a29e704f07a6dd160d6a2a4a68c1948b61f3dfdafebbc15b4bb556db": "f90211a02278657b3a6925f6ef6a926ca1e59a4175e43f7bae07557e70d59096caf0ce51a01c0b40975b27828bc224f65076ebc6fcbc8a9af6f84224877a40c8770cb708e9a027e40f9a2705ed6b0c3c358ab6f4904557d36ca36824a31e64418fc6b04bf183a0085567c6f37decccb503d26ac30decdc924d4233e4a0ba3b6cb16718872ad448a0e53bdccae7bde822f4a4caa9c068d0a2d3f923e6cc534d76c54d55be09467950a041c0ef1e578498da13048ebe1eca4729fb6208d241358236021e085b247761cfa080109d39ba89edf3544f14ffdec453a72a9613db87ad18fa061d1b9959f6b873a05d6d005b3c90919a286b145f65ba6bad78a5c3ae54c6c8de3ac447937688863ca021320ff5b6664481e6ce309d539ea2883141c54c18b75aa7408347c9fb58cd3aa00a944c155427fb757a5071616199deae8b7271b8a36883a71920b90aa4dd4037a06e6760efc69005f443dd0252e12b4f20ce69fa53cba1f58cbd503a4f5c378b33a00bdeee122274cdd8ccee1baa43c12564a027ba6ee101231c5633aa3240fb703ca0f8b141298a73945d7dbaedd8a8a0ef422443d08d958409627b54161b1b277907a0356641ddd86e14768b0354aefb425b3e85489318c3ddb51510f4823a431e6748a06eaebdfd878f7795180b0a6f675af0ba7d2a34056da0a188503fcd92c8f908d8a0a08a8c91366534090fc85203646b89142972e1c04151c4991f8a45a72ad9735d80", + "b051372af79654a3bd581fa3522b556992f9974b39b981133afb20b1e03132a9": "f90111a0a2cf131990d149475965f8a6cd06f23283bc6c41dc10769a4d338a7135c495088080a009dcf998e05359a060336b7fb50688c6e46babd0c1a6422cd9a638f114ff3b2780a019e01f46e9141e04ef8c2289c3bac4b75e02b377ce27f910a9d0aa6709a9afa6808080a09e13769faf2ba1a5a8aa823925ed273803d71a2cd9997010866072d07e0c247280a045d4afce4a70a3c189e15e4f70737ad624c2b9f65d75c8d0e354183491f6a103a0abe1374debba3718094c814e798c37c1eb6221e9a965865981d8d496d560cd4580a06f9459742cc06142bad454f64e29ec1da59d1e1cecabc4bac4794c6bd530ea60a0237d99f73d46cfccaf3f6196fa479f966c4fdf27d203b8a09b307531c4d58b7080", + "b055d890fcdd49d7189beddcd567f7f8cab5856323958217ee72a99376cb38f0": "f8b18080a0fea658cfbc794ff7c2559da7a54c4c498df46f27749727c9e3a2fb125f01a2a1a01ae94c8661ce1bf5ca026d8b62303c9db4f4b0897c177b5089962a8d4448690a8080a0ddfd2ecd9506bde97fff232632c07636e3b4e01caca50963b6cf664ccc07f43c8080a04533e1eb133b2573c0684e09e8ad69b2f15ced7b249cc07f3f34fb03e2d588dda0fa7771f08b391fd03e69645940973cffd4f0f6a84fba13af48b4296098e9f088808080808080", + "b0846221076674fcddb287f65c4a85a2638f1b1537d58360daee74785b76b096": "f90211a007dae85f75251812faea6d70b7a61053cff818277ecb8cbda23621d8e7f2d602a0c8b7ae5f86497bd8c9256197368d2b4502775374d2adc9ded95e31632b508affa074093df1ff178ea4f4c246b4504da7c5886f108737c2d372d01aec673efeacbca0c06fca1a6ae3c25fa337beba64f24e1e333a74bb83ac52dc81ab4bce4064804da027af6270c47c1d26229e73c272398c5034e0328f88410e6522b209ac2f9aff3da0c8f22c90937671622603855f1f3a2017797904c757955946d795d0d506d18c24a0946beb7acbb7b128af3f6d8fcd1b2bc57c28730d15ca9459505418f3f5798b1da0fcfe32b73244dc9a08439634d846a39f767552ae05778cd8e52708bea25cd805a09c0018ee90f45bcfed5e76221bf3fea9557d2aadd72dc68e3c8773b9a9437d16a07c524c75dc1226f5e328345fd24648e24061fa06c122cbf6ce09386066064510a051cc0d0f4a2c99a1115419570446aaacace212bff84ec72e824bf602696cd001a065b78367b410b827fa6a340719a8dc9131a011330d3efc4c46aed330e97504a2a027d01748601b67f84204741ab93ff1927c513f58bff22bc4e1e1d22700bce5aba0c0b9ca8876e6c2f3b7d276556cbf29ef5a83c72a959b3736e795354dbc30bbaaa023d7c6aba3b6aa9be07b0159c2312d89169d99bac145d508792ae7ada145fa93a0c5ebaca42b422e4582cb723dacbd51f7552fb405befe519a6a8708c2751ca98f80", + "b0d3dfffceb8aaa35130a73b0b7152744056c0bcf01089d04f933e87db10f884": "f90211a06fa9b71376a00284b607267985d40172740743158eac1aa2eb41b5e753d9ba1fa0ad5c62cea8f5ad1c76b13b879eb096fff286f804820ff9cbe2541022d0879670a00eff46381bf4df64aa616a390dead848d2f91be172b53e371123a8ec0fae7f2ca0974927483baa2e35dab3f947f9e2fe14613b56839631d36cc3736f77a4166e30a0eef76edbb6232031dfa63fec2117ae16d9f496547b114b6fb45c7e7fe02a959fa01abf94952f2ed8edb3b172e53afb23aa1adc3ae35c253922a1a3ae396cfd4a31a02ea8f2898220d76cc68b3378120c7bd1a8081fe6dcc4258a63c2fcc053814539a097ff1299415634827d91f5adb81035bbbd6bb3418ca15005f707135e519569a1a0e70b15a8f674dde82269d6e4ac7f920c037dd18ba37d67bf14551b09e46cf7b8a03f6bae9e508061350d0b8f662d4600a378f72eb0f9afb1546e405a69c8c62e1ca095fe111109ef3b829b0b96ba779cc36d4996bb85ce18a3205b3b73ccdd7500c8a0162896179095ecec32261afd082d8dc5e3b5b1bcbe2092a1003245a84877c50da092c53aa36e8aa879e4d1faca25cf8947af394bd723437dc1e0fb68678d0fcd82a04afcab30962262eca9543282dc00e63dd315f2412e3300d63c0adf4f2803f72ba07afb23848648035eddec36ef0470f27c56f70c079e207bf8230467bd4ae8063da0f43a576071970fd464524e6b740523c17e6fef10bafc0a06abf6565b5180806880", + "b45e67d0c01bafbc49da1624308d8c120f3a730bc159177d58416f09bc1a775a": "f8718080a0091b9ae20dacc0f3735c79e897e9b8c5bccf7e95f09fcc43151a67bfd0335fe980a0c1dfdb5cbbec198a6cc3326fd825c3384cd1a0bd88c5d269049fad7a6bb8f061808080808080808080a093f1c55d62e67da9e3a442c2a2b666c1e9511673200e922e3adbaa7e12aa67638080", + "b47716d1d566bb445b41cf129322cefbde28de6a7d98101c83cf481e868c28f2": "f90131a084f3073662ca1adb60fd7e796634cff628a93ed439b8f5070c030fac1d25150680a02626fbb62c0888b06854160f1f0e5cfe2dc8e527b2d79ec75ba8264b3fd4cfb8808080a081165c7f77f5dac72e244064ee63ba03cff111332bcc83f384a33b18d29ef766808080a020aa6cd3c81a93c2d1e31bf018ecc3aade4c83bb3fd733599599f6e08bcdd712a0b43cb3319da6455328c8392f6905054f78ad688545307db68c478b9917c2a7c0a040d81393cf65ed148e01f9840794c9a71513b26dd53a9cb997a44b39abbfcb8ba09aeec713f6502b641c10d7e153ec1418b342ce5e93f3cdbfdd2128cff5e70248a0ce5142ced367c47b3c0c368e910c842d998f62fba7f613556db3ed8786ecfe47a0d69a0eb64a234c08863f798781116d82998edcefc846e21957d491f8c5e3805f80", + "b5becb50edbd55ed62f7b8440a4a590fb3954f73a76c4991f7622e0e412fa236": "f90211a08bb5313f5257a2a983ac2c853c2b792e9f59f60da3e6f3945317beae3362f882a069e1bf6b8e7da0eac1536685903de4dd6c29499a99038d3a2c69a5017bac5732a012a1318053742c441486616c1133a8cbb6c976bf91422edf64a392d16c9c02d5a01019b7a92ebdaaedf7f48e5323bc60d423be1cdde002b2f26ca67f613cbb3af2a0bff2a99536785013a8b896830dc244f17befa3ed8d0cb1b784ad081ed261fd98a02c79b0cc68ba1d4536e8c4fa310c46047334d2a47bdb3e922d63c71dbf2f6b3ba067759dabaf844e3b0df1d3d6bf5b938b975881f74035551b4f7c0c1112024dcaa0f7aa7b49feffe534a75a0b572f2dc8d5b8ce222c49db3b68939da756db2cbecba0848230fbbc03d04c007b4613e83de1d9fd189056a4a7d18be1087882ad04dca8a096bfb9703af2fe3eed16073bd69347d157bcaacf88866690e6afb3b321134527a00d15b219c7b86ae67fb35818bb6e5fdf57b61b1271533acec4ec23945ed1130ea0ae3916571ab0efc40b70373ae78f1e85e05211aad9c0d0abe473eca41dc948dea0dca1f67dd17df0f302567cbd480c9ed9de5ce1284a0bd156861be4b293f6a15ba0c92d65f3a31b77c7780cb35f8f0a63a51545c98099d2a9ce925aada272490863a00c423590db1d70ea8c104b1489b0e513288930e1246b200f50daa09aea79a466a092cd14b516c3c1ba0f8f356a69b496caae22b5e78434d91df7abbbb6d410069280", + "b6b809a7bda41fbe525c9f19a6184e565a7e7bff7520f4f8ded00cdea697f833": "f90211a0523fb9cbda8598a39df5140e7d61f5a8e51f2abb5752e57a993d18424e0b7c07a01d4d8c1c48f0836867b381f666a00f514f01e43d3182a6dda2680ca722302de4a04cbc377795a99dedc57288023f3ce5e6cef68b26a77987cb561bba4d5d829995a0f7916f5e4aee97c7eee03840857dda5a28b31a370e9140a28fe8c70cd5913eaba0fa5c7688de29efccae765b840ea9a2b155ea8619fc4e5c78ef980ad416052c96a0d4eb3296e008229bfff3e413ae9a96ff4dbcd56137ac27f66d6411d503c1d462a00f608c600456f9e47857e55f57934c463bb4d51fec3bf65c81731055b4fe3ff8a0648f00ee1a86d3d63acfdefd3bd3b6dc75f0b1ca2378f0504781a15574b0b326a0a9a47f489043c8cac87b33c8b27172b737bf2363dfdd8632f6017c359aacad7ea071ece5fbcd63b6397b0a70709d16393ea3441bd247020eedb7962c7095336699a0ed3a4c9f33819015507654ced48e2fa7dc3060d051482796732f93466246c6aba0595daf1a3c969d51952728631d7683ce44385e638908cc67830ab29f2b40dc17a08191e83562a1980d567974c1f393e7175fab24811900850794e9a68a6eb05a7fa053df309bbb50e1e754e4beb296fb35e1547a0cd094b49981d8ee303a680f24daa03f04454f868623d9dea6b79286d5d1c8232df4bee7a7c079d5eb91ef76d402b8a0cee318f4bfa0b6dbfa4b062a151940709f603c63c712bb5b8991247ead64898980", + "b79811242d6b5b05530f5ab13df4ba3288c729127a334da034bd9f8e21b7f4f3": "f8d1808080a08f729a3d50416c97f7020248757ec99fb461dedaddd50f2559ab4e94ad60cf1b80a04bc6228cbb9b536ae4d2eafa74d5d6af87712afcb41dfb4226b95c88246f1450a0259c2569faf29b24372fe6e2155333f224f75c8f13b12c08e22f8d5cacb85484808080808080a06c9c90611f68ea5c86248cf7d8f9b2d7c48db61249065257c9c6bf4239690413a040e6efd8aa0bc63817019e3353df6a5cb09e4b814570d10603f594eab130125ea075717a05796436383ff43ab3ffa3702e91734d82a948594b7307eb52c6915bd380", + "b96946d1298b0e049fdf340edf7dbe4a7748c76b5b186f84ae3c207f4d0a4a8b": "f90211a0d7934fe1aa24a28e88514b6fff7db6aa76e4260e4fa0484d10251dbff4972ef8a051f52fb837d9201143c5ed1421f05ea139a66c4f061cdaee1a431bbbd2fea523a05e66eabac805d9377d861b2f1a0a060cb8f7638ef0a2b5783ffa6df6858056dda0ebfff3286207536c9ddaf49e8aaa3f1c1be7a540dceb4806c90cd6b63b578970a05b90eb36cf49176b8f1fb328b733a42f86ee5505e35aa3477f7af245df6c5ce2a016a9579e9282345386fbf886c39f0f7646de4ba6e617e91d1f4ad8c8b68a3ea3a0a4ab073e33b49cce7cdca3a419e064d827ae81a59be903281da0ed6c39527faca0b3682926ce764ded1f16fa4d22af79cc31a83a9b3f0e930c89ecbb686324fc46a0563dcd54281ce0aa478866055f775ba2ccbc820ccaff99425a0dcd3eaca7e655a0ce2904fc08d8886b48e5960b53872109fc3db6decd0e1a88fe09cf1f418468dba00ac2a8d68e7e6467015b8e19a7f0bd48475282b0c162f41dbca2587be21660f3a0f83de6d3c2f4511d57e2b4ba91d5682b39d710475437a5ead7596820c51a0ad6a014d8b7ab51f306be060a43b7b774ede60bb19313ef0c5aa1948e0045282ce9efa06a5443c4d1b8337f515d4fdf9ab14366ab382cb1df6c15183a128e3de47083eda0ce4bba51db114f626cc5a04de2259c4c7b003ea9f099cac46e47bc2630019b8fa09f2d25813c8729df578affa442dc8e30e658b6a2e86a5bfa5771880d0200b98a80", + "b9b52c2b23480fd435b810ec53e780b07f89e1cb228d849c30c6aad542e725da": "f90131a04280c433a3a2c6a0262a5ed249a97476307e2b66fb7679de1ab10feb6f47c0c08080a07faeb39cbe70d29f79e5fe3724946322cc25ff77e04b1cf50a9573462e038c2080a02b83ee5101f0d41664c7d3248fb974bfa68b3c42917d197611501b8a12fa22d6a0ac6a74dd6c3d15c8cb54750344ad5c08a57c0c4872192022742b754e857f3ca8a0c2fbad218cb725764d78d35b2896a8b1b4a7370e15815a87a1169e5d901f3a42a07345922d5b77934f54986728a7d9f45a8eaa08ac4a8d3748e4ef036cd5d29ad280a0320b1dbafb3ee67d114fe2b0b0a971a88223bbcb7e5312a96bebf965b832e3b380a06a73cb4633bdb5b1c2e993248d2eb653642f82e9416e292ce40b8b1cc3931d78a07e3a7665e43b2a2b15590bc0e8a18ca9eada41c470db3af762ad9aa25c821c50808080", + "ba32d656c4618673b416a6f3cbe398bad96c0d77a76b7a78a10566de2f641f10": "f8d1808080a03f75da57ee6d61ee468fd53eacd5ad47c9561a1443a013df6edb5604c783ea32a0dcfeaf2911f85e5a765353ac661db8675da222ea94853ef22c1546200bdb88ed808080a089083ea92b753f1598bc604f43e987c58aaa9cf2127a06ed1a2a5c5c628cab64a0598040c2450482a597e8cdfd4e8ce460849396046a689e490a6fbccc9690760c8080a01f6785a712844e0633848b831860e08ecb84386ed311c6b2894d602c9020910280a0b45c096b751361fd8b50191c766bd4d402cad25192b3ac58c4791d7963c12ac08080", + "bb26f3635184edcabdd44fd72442ec6e617cfed8144f11a3c756031c7068d649": "f90211a043a20bc79230694968fe06c05d10ebaba63dbe0e893e7a768e42258feb00fbf6a0fd387652179b98d146b3be7a58519afacb005086b2557e9ff085797e18c30b87a0ef7862e67d698683544b265a5fe194b1a37d98010898eb67f3492bba615674e2a09e62ace1fee5f4bf681d3359232714788891388aedd50a843913650c4f08273ea0be693451e05c8f824919a9532e93e8fbdbf7b854f650434458c04051c7c02effa0f103936186fa39d7e7662df83e82bb5fe50ddebc77a61c84a13466e968875e4ca068b16ad43c0b257c9089c061d8747b3e767924b7ff2f0efaf975b688defb18f9a0a2fd1b515c6140cdd78d4bb26181fba32bf8214670de5029a333c531a153f9aaa03520da9937402d872983a4aa6b6b1643dd53ca03f77d60348230968ac300038da04652ec9c84074e28e4c970452601a9310460d303b581f89a5dacd8d09e41e819a0b3bbeb748e3ba6ad8a3e5cf1ce7fd4657b031e2e5ae5bb1565af30a610e4c8b4a0ff2d2bf9dba85c3974cec548ce36c76e451812635773b06e23da432ded98d697a031d0608e281578dce52a9906e478dad539f68c31772fe1b2634270ea8081761ea0548dfbdfc77d30b3e1a1d8ae9c4b99c27783512cb3a706179c5ff3bbb0de272ba023b6234fdd4f159710626b185b9ac47fb3b32e9b2f53625c2e3309f04cbade2da0e8e35471fb9353e0393c3378045ef523a7511722bcd612f3f0577d2ef706000980", + "bb454dfad395dfcdbaa03c923b84f83c347fa2e617d763c3613f2097c176f44d": "f8f180a0b83bd82c32dfb12efdc118893dadf5f927881a0fb0b595ec0e4418ee6a36bf23a08ad64ffbbc93b751637076cf89f37bc61ada8959a11d7908d640abe49a8e8159a062aa8ad371914643d0310452b6447a557e0c47bcc41b466cee267d9e651652a780a02afac32c48947de387fabcd2216bee9c1c88019f077504b39d979307d02f82bd80a06c082683d4a5cd200a4ddb54d868a86103aa8463496f4ecaee8094be0b7cb4498080a013279fd1390fe4f74df7542723a7ac489bf3492ba04b7fdc1e2dca9c270f0f26a054e838f0e72244a0b4622e60cbd500579a13a6615657f5d7045adaa6a7073f788080808080", + "bc656172578a3665590f3d2ed177a1d082d9c8ce8a2e614907fb16429d9f20b4": "f8b1808080a079e98be1d443145b240c379dde9af7d3f031f8a1226a0dec02f0eca3d5e35b50a0dfd3abd115196a11ae88e00daf66508f5ee4f7e5d2544daca6a9ce603101b466808080a02a35ecb3ad7819818c66bee5c71f4246e78d17f1d360bff09d1f636e917667d7a0bd9c1b7833a6571df7d62313b3c4a3a4c16a8a3b6a996668c857993c596d7eaf80808080a00510ef4c33b4342a49325a765b5c8dfcac3f565484f9e372563ca0bebc083c398080", + "bd3702c0dfc79748400d72dfb91231502e0ecbfff94c3f315cf5911c6102cdbf": "f90211a02edb707eae21a27312b6ca3f456312b08090deb1a5c34c45944741e2fe93b001a010ed615cf10952de153465bde446d994f64c1fdbfb86c7f45f94d38b60247581a02e108a5623a5d625d9c1b7269f832a0b3e1c198365a05d84f756fa282bafa306a0bc7fd6405cee95cd67118fc5c7a32f5647f02bda2f8ae4f477b48886542516f9a03855b68d0e1ab4f8f6788cf2d45d7aed1323e008ee645bd4483658f3f92ad7a9a067e0596690f75d01a92768c8e431ee93a9239ca690dfbac89ec0bd13ea971348a09108ac6e1eff8c46e705d890921f59cb06cc94f9738227afaa4e0152951887c6a0d8dc441dd4cc3bd1b4454a019efb75879eaa4151b9812b0e17337d8eb64cb489a0cb9d1844dd16bc57551c443c4eb5302d6a7bd8b11df406f6dce00b562c1a0784a0bc5868404093d29c7e6991ebcf54d575f2238c235323506807d82430a9e24a37a0565ab415f5bc4c4f54711176d8453d85e6344c7cb9d1c3c2397060d8feff6750a0ec58c2a42c437f554f70a50e1c136b7bf3d1b4759c4936f8e43b895d7a1b65c9a0be2b6f65bd279e2649f61b3da1398874aef3c341b0ec8af1010aed1ef54e60c7a08bc6cad8d92f984afb9257c2bc0b4fa31c59a8b55b1daa0ac7142ccf9d40906aa01c9a9f46c4d688a8e102e19b57cd78910cd6fcbe7a7e9e5d310abe9bc3a7ffd2a0938810a41b1a79a4677af1895c93f6c1975b6e38fd3b5348f8f406a6338fdd5880", + "bdd6f49ed2416c54ab96d41dc62aa5ec49992af3b08f4daf83bbe4ef5e506b6a": "f90211a042b86145ceb022c727612213dbb8482a7ab8c4ac835fd0fb7d779e3e6c518139a05935f2b4ab061693175619955af7ef8b5410b905d8c9617c9f14d08c87d4114ba05b46693931c3ce409ae98fbe2b3bef1481830e7d9e9d578518096ed4ffd4b2b4a096b2bd01d5cd92012ace8066460137c2e12cf2302b45c63f3478151cb143e54ea0601b16f4bd1025a16a390d80adb37d039131ef2a0f4ff437d5f8747f5220457ea092c3b71e20fcb176526a884e0c7e55f5c0a2009039e3dbe9a5c3be233f98c033a0622e78cb0e14bfa3738cecb90dcda4e6204d1ada60bb18df5e83c4928adfbfa6a04144cc9e8c620416badba803c7641f1be0dff605c7207676f109432aca2bd2d2a0584ed6005432d5f7f600dfe29597012c1b15fff259dfafd408cca2fe2825de71a08f957451fde81789d980d3ac25180100e0a9ba0ebca3bd3db5368e650464882aa097adb6ae8e3cf813fe97c55bfbf93689419b7d955d8ed193ac6e1099565535e4a025b26e4d2dad037fbe78c9e6facf94e137b6baa3b0b08b91a118be9928225a7ea087396eab37047a851faba0dde6a48b5da4c79652663b19b7772b2dbf73e2ddb3a0ddfea4b170fecd313faffb4d421fce9de71f979139a9146d336325a300616f9ea08024f062f46026fd19d43be16c4084fe489cb791bf0e3bc7fd686bba2cf19300a05b7332a568c2c2ddcb1b1bed3beac3267c24e9feeac7950954d5a9dab6a0f8dc80", + "be7fbe2def8f872d272685d83bfe1946c45c607c804555952ba75bc921e9fc47": "f8419e30b2faf697fc5dba87c94d054114918a23aecfc65f0d81e90e31e3915259a1a0dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00d", + "c04700525cd0a1d86454ed97c41757b61dabdd9e2638600a256304164928ce05": "f90211a0c5ff471b2dbc9c62fd3177e68ff08f98f71a420bd84712877e997e10a19bad5da0352e07ff9483f3bd8f47825b23278b4d8868ca1a3f54bc4167ddc59b58c742f0a0e673dcdf8a9efe89cd446d939a02e9fce19994ba22aba83474cdecac686d5bd5a0a71fad1a858d09e900e5c7b562f3b7dc668b3cf4009fb85095a480308c00c77fa0aac65e703e8afd480a4ad7e22c4182eac9057772aef2126716c6e476e850d8ada0f8dac91ae2c8699002e9c36c963fcbe6d9e69f96b6bb1051c061ba01ae9fc896a00df072c2899efc8de1ed0d84eb8c75bde585e97bfd12b0a18f0a69e9cc8de387a0297f9daec11fe042328c78b0ccadd4c596c67d0d98563249773b74ec3448db51a0f6f25c5dcc0e1c819fdffe26576c6b7c3a80706d83b764abcacefc6d8edc8520a0ec9a595555800aaca69aae7fe55e88efb4ed202f45fc793bd22530e16c8ac7b1a0802baa295b526fd3f3afd315fd4028648a9f12f4cff95babf24a70438089bb97a033f41e319868b59872a25a3c59ae0a39120080cca49c1fa6269e8e2299c008baa013e86626b39c39ef67661eff84a49262593bf84f1039e11290534426a65b39c9a06d5dd47f8d72fa8d568f84562699bae08b0158ba2c03b79aba9267e890d7bf34a05cade5982e50026e9801b072d9b326d0057033f89148a790ce9e42c7337b0a54a081a10ff12430c04a175ad7ec506bf4e83ea2ddb7c76a92a15dbaa6e77fc6d3f780", + "c0906a846ae684eec3864a80092f59acaf47e9e080d0fa37b2b0600422a51bd4": "f90211a02b7b50779219bf40ed7384a469f8488ff661a78e6a138a6173873472dd220b9da0998cf93a0d8b93d35959b33ebd41e500252fc58e0df9188a4e1f1c53d4771929a07cb69b6a8383d8995ec6980b2bc70d81c3df0392a01cbff4d63734ecad5535e5a01f20b9f30078dd0ac3c67b8269a6870a8db581d361125d86e3799ea7324dbac8a0613b06377afbd6ae089bbf8b0fec2bf73790cc88166ee2cb5639cb1db3caf0dfa033f550f474262165b1d9df8ec692c87d6633cffe2daf24d6517bdb216b299b2da05821e56a89db565b1dceaaed00311621bb5be1f8b5d9dde5e486a741fe90cbc6a016542f514f2786aadf924c99e251da98e1195b6122774562a273318518a1ae1ea0dea914b89ff259902acca17c90d27a9cb980e5cff9b516db8d77aecafee64438a0f61eee8f71a287c8561ebb99d2327ea955b2f081dc62a4be33c8675c8d5c3727a0b95457b59983c5137b728d62bc05234ed6cb1a55f84b3b6b52a0aa49cd21a87fa0fa52e76ff1c450eb4b2582e35f0681fa1bb48502fd48d39208160e651e1fba19a0181c8834f606ccb63fdd3cb357997f5a0676646de24bc54202e554995c2f1cd8a0217ea47fd3f307ffb3a071bb720fe6aeca55c2ccae75876c165febc1a607f2eaa00819a182c07122df1df57599dc3d6227a01a2a55e6311575b0081a8f6f14c936a0984ef1bf1ff7bc25240a2925f752d2bd59ead2700bc25a7d6328ac3f976dab6980", + "c19d91c2a81180de78273b7461427b337647ff9b42e79a388433396f4fa150e1": "f90211a0443d76b89b14e2cc3bffa0d99af8695d5f69eed92a9d8ce275d540c164e7cdd1a0e20c35fa257c6357276e1a4c507e18154a61c04d0b96e3f147b8fbc9caf70e74a031a034d33813e4dfd48996739f26bfd0d1429cbffaa37c4e91c47a56d2496348a0671f1c8da030114b2d3df5a65d7be92556329ff0740513870b144166a05accb3a08f2e7dd44ce5c000a99c508e396a04a4cb8751bbe8575ea846b5fd5fe371c194a0fffd20b681d8d4d98ee5cdbd4922f4c3a0464134c4d04b927ef305922f564e7ba0e02d7981b7af38417865bbe8f8e8e0dcd6b2aecfe2f5a31aa008f22153480613a074c1aefb3b0dc4105cbc831b2380889af471739d63190e9f5d0303f87fe12e4fa0a9b2a10a3e46d898d51b5491ea07f5c9050ebb4cfe360347475d327467aca9c5a0fcafa6876857c4ed8995794d898efe1fe20d93c7e5b43fe98c283123924cc74ca0f2d006207e994befc37f78d3fdea029f37f32f9ed1544fba9d13fca775ebb719a055acf37597b7a2793b31bc8edd8a2f9686a880d3cb24ed92c925614f3ecc86aea0e7530501db2687c73e1cc9b8204cb7c29f244d20ce156b0af2fe830ec537b4cfa0386d3a8ec59db64fe270a58693099dff1f54448652b91ffda974aec2eec5536da0d55c102d2903c7657c8d729cdad9b8e19ae21180c069c9f882cfda734c819407a032816c6866cc82aeb8d5d140b409d3f0443fef72c52b93f7f8b3f2d63f614eea80", + "c464b2d744334c4094d2eae0ff9d3ee93fdf1959f6fb5ea762e5a6a17bbd6ce3": "f8f1a0724f8269597045e61528ea8aa1034eeab3e6de84a94e864904d87d45954158e6a0974c1944919f27fd85b89d488137de9a45438a71f89d6456bebc6d678e602bc380a0352bf037a7dbcac4d2517191bc3225c4b42489f15b48464bc1fabc80f4f460ae80a0759dd5e040d8ec1858591947520723eb61aeaf28cf09a403cd18b874db7d8cc1a0162fae7190ce60a18051e7f2853be0032597da1903096783ac10ec3f0240b282a0b809abcc89f9c523df3a7a37609fc593cbe61d042fdbcab5b67b00c7f1c292f280808080808080a0ddcc9f00f9be819be93e9ae1f0fecad98affe60d69c69150c99e0027bcd4be8480", + "c46ba0d152f58f060f5979ec848e23a5cb7a3a2b50072bc304e35073d80e22d4": "f90211a05ae182ffc5ad4546bd9c5cfbf53beed68774017fdd24ec3ed57fc8bee0449827a0da7a1db7389d48f3b459d9c377b6d67c564cc0189bc5b5756bbfff7fa08302a4a0bc74a7b84a775c6b71160f53062e1d3f025b30d974d839a31112159a3a62234ca0cff8bbf1cdb97dee31b6fe7fdab24e108c23647c2ae690cefdc1a53ec996d2d7a0df962edabd7b686a5097bb71db979cd93532a9e12e44a2d032ca88eb5461b618a005633f7fc790acfc41debea193d7e03bf355cb193d321c77400e01d100b12a35a03ce62750b4c32fe5b09ab958c7f6c4eb9d34924607d246e63e809eafb6b8ebe2a03d4cc00a827886e5df28555ede0e8ba93b39cd8725904c0f0fd8f0de2fcd37cea0aa81ae2e454c470362f8414848fc09607e7c43597e83bb86fdd148aa86a40c3fa0187e9557c004906a7c06b0602ae8340d3ad98047e9a7c975d3bc84e420de9772a04974257b5e51dcca4914c23091f63a0588b1d55a0e69ed6d76dd2df7edccfd6fa0cc7eeed289cc4be7813d04f499b6ec24a137da5656f2158f39349126aca0ca3da0d578575697af3ae855b5867f31557b97ad880f3cdc6c8264c15e89c389f2b67ea071962197159cc8099d6c0ad4b3b9f81f5826d0a6713d259dae503ddbb12d136fa0178cf70af82bcb0fbb8c1be4b56e89b3743896c045fa40fc555471992cdb2a38a0682b6ce8179b01b7f72d0c3692c3e33b06ab083c8bd741b9ba35cb61a1df49c980", + "c6165d79a4fe9e02acdcba2b528e2a3ed721ab17df6c0c8d24e4ee29f43da711": "f90211a09b6b7574cdc0bd6c20123b9004e271de5a764b836d26e956734e191611b2d8f6a0b84a9b8ff3eae8d41e65a9f8cebc23fb3c1f9e1d2a1d979ba2331d4bb7608ae8a0cb1336f8c9a59337ed1f0e506ea6b38d1025dd9fa8c4da0b329e3ddff6c5790da078029e322a1f4933f7f8d98fc501a684522ad5666ccb57098c5cf14c689ba309a0e9100dc84a099da7c6f7f863b9ddc3d9fd74eaf8b7f52a889252f62af65a59f4a0029c7f6e59984e1b993b72259f94c3810847d0935a47c96f9eab57eb528b3a7fa03323c8261afeccce5f88b510470b107b942864b5920726def8c9562dd05412d6a0afee9f0e625a297964894883974b3b0dfe7e69319e18802fd81b068474a966a2a00c4ddb1cd88318e80ae6668155a8794d16e0f29f5d6a28fc83fd20bdcdc17cfca05fc390a2df6fb311b2882fba4d1697c2eab5e7ad61d83f2c06e2f733bece5f78a0e209370cf77ca609d5cb9fbeabd2fd7ff0838d87de467dd834b00bdea1006ee2a092bed4e95dfd56e3c4f44a86da7c0652c5dac656b5ae5b6ebba194f7a7a33c7ba014cf330036384e5eb6de41d607533fdf51c0fc3cf373af8cf31418f291271929a0e93c48b9f894696bac2e791e43b5a4ab0040818e47b4ce029ac25a2dedfc6d01a0de34629ccbef99a22437e7c747b98bf697d7140fdaa4038379e5c8a1e4c1f27aa029c1e1fce77b4d2834ec68c2d89bd4eccbcbe09e09f56af9164526735a35371b80", + "c663bd9b0f912a5fee29c8b34f7d0eef062fd440522cdf1ab7fd3ef8cdd630a4": "f8419e3f0873f04d1e703ff874c2d0e1b0d2001312384808710248f321513b50e9a1a0cafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeaf", + "c76f34549cc95765b2f011b05e0978155d2d6d84d88a2c4006ed713521627084": "f90211a0df5b7cefad2c04bfaadf438fcb24554d7240cbb886ae121691f5ecbce2ebbddba04fca7600b4a71c4c75a0ab5131df404c0664262ea92a91f6c9f6d7b2533995ada0412ae1b5e0a127daacb414f62765ad9a682d403edf75bd1331b65953b2aa58f7a0f12dec8e72bb2cd1d32b65ac93c8f061e28c3dda4f53eb5b75ab2a6a630b9821a0f4af19a0bf2124c8acd7173ce0929336dfe3c7ac73e37c25138aafd3b9cde0d3a0db40142f7f55626d06564bd928cc85d01877a7b8b4ecced441dcb92f38673735a064c235bb18013bb68af4d0ee3c9aeebbe15d287a435c10948c70c21efc31c6d1a05b98d87e4a088e3b97bb5c92d0148e0e7c2d34f6e3b180e5dce3c830d0077f8ba0a66550bf64dbd68d8776bad8d6928a0fff6f168615703bb589a153c9207b56bea01d6ae070e7ff94fd948b839a3fd67da45f162cb8208828a5d2310cf3f422175ea051a315c5c48abff1d2cbfd41fe0d05357e4e19dd9343bdc17e3675afbf558ea8a0c533257a2d5366831d076e8b44a1e8f622b25b011125335a3074d6f223d263a9a062fb2cc7a32bfd7ba1eb47aef620f8340958d4b5af328acbec3fffdf7c6fcbd2a06c58bf2c14ae4648794451df32f677b82f3dc731bb16b5b702d84af81af63d10a00a724e73b5df0a0e020daa23805c89ccc78093a1d2796fa178a67134db1a602ca081bf4488734fa9c8ecfe00c950aa0557e712899b7455c2befac5662cba074d3880", + "c84486afd8131bf039615d8600ded2334c94a632308de277fba548e917ccee99": "f8419e3645c69bf3cc8373b32fdcaf820a41aded22ee3022772ba7ee9aa5b8c973a1a0defec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de", + "c89e8a859b2ff542dda37467103651268be0bc72415d5b861fb8abdebb750bdf": "f90211a0dad1795e6476ce6fbb390776192abdc9601a6a977d4b5ed20024e6e2c2f8d86da0c904b305b6deefbf798cd7d51ab48e107d66cdd3768c21860c1b25747e21f0f8a052c07bb450c3a41d71074880ac2d698230b543876764f73dddbb03cd91a06a7da0f8fe55e3eca6a19272750b1a220946901e74b3d426d02517cd00c9c24083e381a075e6c85c20c2e309954c34f8fe44a617a40499879df70e2bc8ee662da9ceda36a06c51c211b9e0994dfaee26c43fb264ecbed4a8fff9557ebc5374b31f46efa888a0160198d99c0c6c367d5d068af3cdf15d70ca7234336aa1c741ac438523dd4194a00ed87f39b0e95961e32a441dde2ded948f6cb8fb6c20563a3e4bb4fd16af8b2ca02ddb13d2b76f4b5dd4ffa33e100919a50c901f56bcd8ed7cf8b8a3a4feee604aa096d0952f5fe395cacf9fea9385b0159937ddb840894766a0cc5fe830b43e3d7ea0c95cd1443392791becce6a76d5c890f96a7b4e025ad288e9554a0a51ea4eb1fba093acede0ffcec7a37b2a14fecd61cf9c963b41ba3cab2678ac1d74d0851a34bfa0c94223dc99b6c7d4f64b7f0bd4b00e3db2d66c234f9116f0f461401f683b62e6a0aa89e2d76747298c8584cb2e39107fa067d3252be2999bb413d7f750f6a9bbf5a0c043fd7308e7e86c264e3e6c9844390d7d86c9e81812ed5459bc85f38625f8caa09474f7adbac6b0abbc3786aa56059216afab9c2510274c58311fbf02e5ddd9ba80", + "c8b402c941194a37a413bfc512b4e003f79a9fadeb5b02f049fec0edb1c1705b": "f8419e377bd1cde15b166faecc7174b064d5c9aaa8d7ca865fa8807616f550bd49a1a0cafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeaf", + "c9ef4bef7715b41226d59feb20be7b511c33dc60a9ff64ffdf93f0858edddfb1": "f90211a040ae4d08698d20dd478b7a5313f033a5a9976fdda23a6b106ccc6c941caff1a1a0836cf1ed650739b81d5564d385235b51a352759462e5c853621b17743a27988fa077ff881a5e0d268c3e20fd2f735c6cdb75cadc483c90d809d823869e56dbe60ca0b49e1cc08170ce0122c56dd914068350eeb592f5d7dc5fe3b9701154b5dd2e05a0dea4848b9b977b858e8c56b38d49f4fc9621c3c2179de490d235f1a665d87ab6a0171b835c26be4e1a371684b7544212b65766c4897e704a1bbed060738fb957aba04f3d8bdea7661673c9848b8f3905fe504bca92f50308138295306bdeb6989c28a01dc5adb8c3afd19c5c0491b441f538739af9e9a0bdf1c050109de3cfc70353f1a0788431d02e7da5d3471a412a4772a44e561e2ed990510d9a021ad715978245eea035e2aa19a97f67ab742e104e1d8eaacbe1d584a6d645b2611eb587d5a31920dca09fd46207bfdbe98539457b5e9805d2bb8ca7bd3734a3ffc0bc3be10f27639489a01da84049aa01531cb34e6752ea2793ac51824aec9831b0005a7f3f84796ba06fa08945ccf44f9c4870af9c5c3d7eb559531e13700ea0912692a8a348c7d671f2a2a04857e1aea69407ee8146c93f29d7eced300e431e510d49c8a2f7e1d4a087380ea0076b6ebacb85528374d7c7cef072bc40dae020e6e42d6ec3da575fd9ee16dee9a053f49ebf16a030e2c6dc380b940b1c25cf418f9db175e0defed3f36447f2bfe280", + "ca9d7066a008f45873bb651610e549e5c3467014acfa5988afe95a9d51bee7f2": "f90211a09c34c8495fa68721b025a54a216088ede9f67d843fd7f2bb7f21a5f28da3d873a0b656ade7a30005341461a471bc829265b72b29d556bbab2d0b5ce8b92f9b82bda08b9ec008099edd404dd4dfb573f86fcef1c20c376fb92d78339ef9b3104a1bd7a0d4308701a6684eec65208e8732c9baeb7e602440ef9218dfc82990cbe8450fd5a01ff7faa5e0142c1ded0452d0965e2514e8b1d56627e3246d5ff31b6a72e6afb4a0dcdb5ba60059f1cb4190d9e5b28c51ecee4a37965dae4ebc039569d7de2e88c9a029da18b0cdc430f1ecdbe50ae98fe480d341b1f65e12c1bcb6b9f345ccbc3073a0f10ef13814196b7c42116845ddecb8fa2fee1528fa20c0bc93a353f5b3912967a07e8ef1f0bb37dad4c38a7f196c537424e42300e269f29b648969f4f6ebae392da0ed6fb76a871eac0f74717bde24db977ecb9150488f062e446a7f8cacf99ce07ea004142e4ec5315786c30e95b795d51e1df47c96eda66234732c240bc26b65579da09330d83e6ad19ccc13028c673c0f8d6fdd80a2f23e0943b143159a687cff5760a00929abc43af2390ee1594c69f8e5ebb65f1ab518c8d54d3ea740bf9943e95e04a06a842dc47ada4741343f4610ac6adb1a12e3baf5e89967f0cc9fdc9523622744a07ac4b52e2dece3b5729b48f1102022baff4f960b88bdc8a04d82af85f980a56da0f454cf1bad8bdb835ea83109dc55359d7c2ac319032c7dcb17c180ea142704d380", + "caa482827e86d181120c76dc3a387ed2ef4a060512ef069761e46dd0ae36f247": "f8d1a0dfbe9d9836a5b8e6649e36684016eeed93b3cf45c56bb716f69ed0bd124f7521a05d47be7c00f91532a144f3f15022c2a83788eb395b34bb55e0cc825584cf11e78080a0bfdf1cded03e3799041897cb33196e3c82297d2b5c4921c341a77069c1cbc4e58080808080a073688f1853da9869f39e9ac69079ae097aed51539b44c9698f2e79fd9c9092af808080a0d6a702d7fddf7d35f8e01b6ba4a45195bbe4b2ba6740b04ad7ba6ae16ce98223a04239f418b12a70b84deca6063d8394f5ae256103ab0b97c0555a48660e059f5080", + "cb3dc35fd95666fb836fd4f275fe2f8e0de6b0f4cfe5cd2140ffa7105ed1071c": "f90211a017fa439ac15220608b688e79f68de39a945d5a9fb26af3e1b264ee9b6f6aa24fa00176fe99351635424e4ad0844393a2524796cefa288625ad4e46296d9c176beea0e13343cefa47942a4da58d906ec5a39410f2b39fceeb88bc8749aa84e23e6c61a09bf60f012dafe6939f0b69fe8906209263805ba173aa315f4fb8622b091671d7a02cbd55420b6cfe39c8aa5fb977a454352cf26b90990e8f9801a6e9a23e29979ea0afc7ad54a29e704f07a6dd160d6a2a4a68c1948b61f3dfdafebbc15b4bb556dba013c75348040b32d663e809f41df7e898e327651b091cd3ded62585fa33fa55f0a0e5e38139e194a500cd74e7949887a959fa66f4414df027e165c936e0a392adf9a0a7bcfc5207ee91326041756fc184072d5a1087901c04e894eab6e6a3e4502594a081c858bb661f50f44b234b377c20c6d0eceaeb79be6ea805214465df6c41dd6ea08868c048759ceaca68e38fae64f97d6615558ada99aa86ca3de514d97cd6efc1a0032c8350b4423cf2008715f73f2fe2fcce726cd4ab2d439653338a48264f73aea0ce4e7933dc95f69a35d99f3fda2226abe040e86ed96d8d43318180224ea613cba0a6146ecfeab5d208120ed087a57f1d991188d30c154b7c284599dfe9a24559f1a0c82b43d01f58d7186725a02051ae9e90470e1d9fac1cd3ba196f8ce1b379b6d8a090dcd0ee8be9b531bfaeb0276004b5cd8a3af27f4d2420008dcaf850e05493b080", + "cb56df6e9eff972cb1cdb773142bec1687b001422db0def8f17643596b685890": "f8d18080a07924de4f0bea629d7ab12b9be8483bdb8d65c6bbb569477f8b6a216981628ee6808080a05c25f508343f930146d60a2dfa4a72ba2e034b7db247b865e48011325460f412a01d436061d2b0e261bfc6fd3cb0e209f3772c18df33b6c7b3ff82377f0ad5f0748080a021dd6e65c61b64bc87b9ac1d9704c54750552203a9498d468a170db38efb1853a012fbfe9d7cc6da5add7032a0d3e5a4083dbbe34db2acf0dec68bfe4e27c666a48080a07d0653202074bbdfc3d8cca74f3a1765e11d38b4a50b0f12d988845f6b3b2e018080", + "cc1a4df8439f81f3fabb8d66ae387cca8edf9c555e29bfc36dddaf0545acca63": "f8419e3060b17828abb7c64976fb8175954d0f3f730d7528f9b07d85b0327c0588a1a0baadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabe", + "cc5dc99deacf55ac3d75a56942c61df8fab14a7d58ac5ed051c0b180edbaf1c2": "f90171a0c5d6f66d4fadabd6f2af74d77c616efe267db6c8aee7bf0ef0808b5baa36c580a0a687caa187b67b8976372fc80192056c4780cce8eaee6732c788626f80e00281a0a42d3ee1b6067b0e76db3675ed55c727eff3f1d66dad331d811b565f3fe564118080a0b6b68059b71f51d0dac5b11954595c26d57ca9655c25c5299565235006d033d780a0be7fbe2def8f872d272685d83bfe1946c45c607c804555952ba75bc921e9fc47a0a17c81b542375bbfc12d281e05d4dadb00aeb147ac561dfcff9db4d593507818a0617947495a6319c2da8a82df0a46cccf8073326facf3b026a2182f2e0735d41da0a842b92006b8cb505d1e97a89506e92e6327b71fdadd97e815af79f55d7a590780a01ffa59eb13506aedff66f1dae6dbdecdd57979a19e65b00a7efe33a9cbb3140aa0b603361c695ebb9200d426f6ab5b3cd9c971bec1d6c033121dec3cc6bb9325a8a01da28fb42ca827d1e5e91a622e5c30086ab92fadf0b5ef455d8792965378e0c58080", + "cc7b4c69c7e6c4242f46bf988afdbe9a55e5d272e44c5b4a8cc2c00e259f0f17": "f90211a0710c16b4f2745ad4f8cc07c027f3204da3b17f2adc8f7283b17a1a19ee0fe94ba025bca3597b92ba3ed9de75b1a08afd2bb77b59487a8ef57899769e168ec0ae1ca03021e5bf2bcd69568a01f982177368000204d9c5665aa02c8574a91dec884eb9a0fe46f5d6dddb35717669faf8218ec033270ad0f78d87f056b6e315f7b5903543a0e1352c22df35dadbce9a46fc50bc7a886db546ef1062413f2d1b46495cac034ea098eadcb283ced6e945ac7e1384f796a911781adf30380e10ab5c99d0af6c4176a018fa0adac23bd42ba9abcb41bf8a43c0e0ab590328633dba88f1bfcf736a407da098a93a924334f634a84946803e5d84a7eea32f601f84735bb71a176e3ed74440a01d6da91a2b52c2961b5315bb5ce06466a002feac1b6859873fb35705f00b4f3ea017f05a52b56e5ad6407f2738f7ecff706abc00910aa6af8a0fcc88c1296844eda03b05028bac2c598e2f83a01d9061ab31bb531f0fd3baffe846cb4a6ce40915e4a08177929ac44f592c90b5bb2e7239c5a0c25c898193752c60d739ff8efaa4428ba0adc8696b377199082f4b25b841af2fc112d0037201a481195785b365665e6d57a0f5c7799531b0b748cf254cc70b1cd2c02fdbeecbc30d67864b79e0470b91cfa8a0522e231db5dfacd4e1eedcf574dc0ee9f4dbb7be17e62f1d426e67015bfa615aa05729fb884439b5e2231d2bcc5d2e0bd64090e862ff4a9bfb0b721d0ce0740cf680", + "cdc75fa9865fc40ebc29e2fe74c83f117b82b0d101934766dc142f17bbc6eb04": "f891a01e4322d8d7226263d0f8b5a7a7a7668d3f9961b9a46a8cdf6b9dba5f713f342b808080a00cbf62aa5ca7798838a04e5cf937439cc7ea06cbd74e53264f7d41b88b2ad045a095c213cbcc2dc4c26ec3f11bfbce2ad2c4bbdbe65c66259624147dba99d763338080808080a0bac246cec07bbd7342067ada0a8b3ecfa02205a431a414c08c541201d9074c8b8080808080", + "ce611908391933502f922626b01678aab1ffc5422e6ad39a4e475c64b97a259c": "f90211a03def2c24d71ce8700049d1207bce5e9f71f78b6b7c07a8c321b53adcb4d8e2cea07b5fd328fb05c1667e628dc286a9808f7c42b769005622990ba652c4f1cf159aa013f9ebf361ba60ef63f40ecce52075f06c04cffd1a0a022773c645fc788c45d7a08880cda86f85f5fb55a16cca794eba5044eee1e62ce3162bda0d5b1dc82411c0a0243735d7ad5e4857ca2efc5051b16f5a5382b7eea801ea5f0204be32762be4aea086d6e35bd591d67b348101bc3b87d40f8f81c78c60bfedc53e87b7ba4c1c432fa0de700941e15c534ffc059d9cfcdbf3d014227fd9685961736fc73850423481d5a0653eaaca48818e85e4f0e7ce841a498c4afa42287887cad28e9cb8c29103b030a00b36697f2dd15cbb2066b8c3889fed1d8a38a3afc7f5e474df1e0a82ade115a7a0903d2cd1bc51bdc720aaa7fdea70e149b319a5d8c9cfac7134f61f750dbf5beea0abed5e9dd6a9087fec7587c9b47a07522c8f29d07abba2c877bbd5602ef91e58a0e5d957849a4e5c1b7283b418216d6fff7019a610bfa13a1742becdf9eb1dceb6a09981f5b5fc8ae7cdb398a43458207fe94eaf427e9e7ac44404ae691306c1f507a0e74873c41dc9888e004df11f6c9d66d1967fc3acef24df8d03d316a51100be6ba00631a75cc4fc195c7f6f7af1962d0765947e8c1cc9865cfecfd5a096054a1d51a0621cc2f89a42fae73099559c31a2bc76bb9e39325b0845b18653bb1e051a894b80", + "cf2e13be7626659cd54237c1b756e762ead0c9feb45035f080185f3fdf502d32": "f90211a099a736af04807b1d12e0393ea474191d5d83040205d8a7cb9fcefbc76cd5c42ca02bb5287ee0f84946753841b82da3d9b1bf8b40fd0223ada77a9e68cb39316d07a058d949f334c223b860b0a0bbb5b944e4cfb89c9cd2a9ead77d5d8c5e4520312fa018d4980a6c23d5f09f39b03ddc08b03f0681ad7796815d745e288494465a74f6a06f1aaf3eeabfeae1128df69b2fcc583eb53f06ba115187e5a44f6ca449df59a4a0197d12884cfadca25e1213cdda0c9fbf18fa338c7d76da539efa8569e999ae19a03f081c4149cf2364c99a1799524172704631e39a7629078133f35c093f8f5255a0a1fdc22107c07d33e25f3a7c391888186d7d39e98daef63cff80d05265c2eefda08e8df6c58d7f8634417c65435cfeae34d9092594491c9d6c9a62d57b79caf849a015a88a51531f904cfdd61e0736d6b5ca41ef18bc5f22139f038dc532382b4387a074b4b86d2a3ebe724718084ef41e4b2366a921b901468ef42ee208312042980ea0854283a98374ed1b3e43a12d0602201f87b5108b1817e2fb9b806c903a91a970a03380e13372a399107f9cca8e45f921474f4a48f7b8ee8d8cb72e32d2e1262aaba03dcef64f8805a7feafd428126bb9f1b83b14854b5c16a367f01e505b52fd26e9a0a95cc8a58a5468c6f2a6cf77b2e6214b751bc7361022a5cb7b296de4b3ac3e9da01beb70958b13e6c1442870467a83ed172eced6533d01f38434e28f3591a39a7080", + "cf5341308f7dc7d0acf9362da5f40847b49b79ca10ff58433dcee9f71570ce24": "f90211a0adf51059066fdb3990e97b21b667b45a4fcb5ad15f148b7dc22625fd9c683b22a0ffaa0b85e04f3563f545dce886b0c135b3d882c696078ad05d343a9223e5fc62a06377107755fb77957b4df80d13ede1757a771008431072eeaf2a9db982139c61a0f54fa3f1a828906a90ac19c713d11cf3615a277e3b7195894f61b8591b8ff190a02e58ad7b17da481fd23b0787b5601e9869e3d3e0760afc096c41f91377fd7de7a099d81c345efe786eca22f8be5046b71b12b1a64c9d443359e6b10145c8475604a0846746a2a384bfccd9ed07ac984b2a4590a058f2d612c10da1060577d8887763a08b2b35fa4fe0d65e3afb4e976c63d696fd6ab3f09a6a42563ee6ed69aded4698a0e5dad2b02534a7a9676d894a2dc37f6a77b57aa17e80c9c7af88bc5e3d643575a0da0a788b4324f45f99889dc6f802e062a08cb637c99af2e79c70cc25837e5b27a02a07930c350dc4bf770642fb381412037df8a779c53d236b7ffb32967c6e12f7a00cf7dc4a683262770ea0958dd0c378be1d0f86a771cf2745be1b7b493c86c329a0bf5ab2f5073e9d276b48d75d070493e0a25fda8c7589cf6bf39cb276adb0e086a0edda5a318592c48a7ae079dedd5162a45eb5d936a8d7fd4016e9026cb0b51f24a09ec1d56b4d8e6911b31c9f4777112910b32d01088696b4c84cc7ecba36604d3ca0736cca1ee36169cead591cfb85bf3193cf3eaf0618a8e2fcf0a30bec5eed727e80", + "d1044c5c73457b4ca87ded35848516d95f8e1c3bb6afff915b2c2a03606c27be": "f9011180a0cbac136a35d1e8ce5a3f557097607d5dff6d9561234bd727b5ad8f2e91f515e08080a0833410eeed81d4f7ea100865d146e77fac969d55e9f67d857fe449e5d7084dbd8080a05dfe3df391d2aec0a7d5378f300afe20b929a4e4050941c9552f306d40294747a04102f08e6f76907c2e116475c37c66e87c4422c5223519d2ef74b3af60d5878aa041a4448ec90e2ec296f5c77838a0e3d13b6ff76b0881059f0d07ca5f9e80fed5a098334b5923617c1fcb5b5f7ce79d36a41faa59fb9ec5d486f3258f25405690e280a03b4f0fb6fdaf2960de68ac16e541328b49d12a2401305c36dc8474966b3db08f80a0526b421099cd67655e774ed5624e02333ceb573bc4c07c765bc48a42438c18b88080", + "d194f061c614e187e926b10b7401c82aabae045cb0d57ddc4c0a3ee912277229": "f90211a06ddca46c37913e5d7b1e1f2de5f352ba4e7f21bbaed9ef7b0971b099d139544ea05d28fdfdcf1f717f9306d8b47c1f1783fb1145865430f1c81c9564886ea09f62a049f369aeb42adff7636ec861e38811421989b7aea6a4c22f47bdf4b133c3a777a055c0eabc7436428504261fbc68ec93ddd9fcb85fff468b9158d24d237c5bf266a05afe7de99acf628cfa38364b4b27e9f197f2ecee4fc9c48244a8afba7f042235a0692e3ee71dc51965057d8f048aaede52463c978e0a93d1d2520037d7472730e2a05b446b0945c1cf7dd05bb76115be0dcb5503a07aa15a3171f0b50f2f75a96e75a041491c1d3fb9d46c92e9706a94fd34398690cbe61940cac9e58a1c31a0119949a06dfe58c7ff911f5abf1f570ffec92a946b912d4735414e99b94e69f5ae66ab18a0205aa4dbdb30ad03999f3c02dbf6c9ce678b8820a74703f93263d27facab4622a014a6b83ee9a4d2ba49eb6cd1632234da6927e2181d8adada9cfbbd9c318b6cd0a016a2cc1fd5312e776e7059010c7eff90b3841753baed288e38a06c177514136ba0da8c16dbedcfaedb2ea9591b8039fc84a85c9d3d68837336eab72ec0eebf997ea0d244e68354344346a4dbc9ceb4e588f401ca795d9fae2b716401e19cdfa429d3a050c5e64f457840ad57899056fe9b70b5a9809ea4c15a001c736de5679af3e66fa092768c5bfce61008d24c49e6dbf36d1b3bc6df5cc27a6daff60f8fcb1729d55c80", + "d1cd727ba27d0d1560347abb129c8103578ece7124dafb685b2b79353a9fae29": "f8f1808080a06f093c903d86eab04d1bdd9b628c59d8f0972405d25fb600992d91eb634d2347a05ec85860ec1e203c795ef0a201671b0565b89c56356675c6d2a77fb9275b3137a046aab247f16fb2913231ad0c54409643046a2db691b56aebca8979ee675cb898808080a0669961cf98917aa88b47a9e9d5c48c54b5ab16a06cb95c01c131577b4b18972ea09510ef192b49c21aaeeb892f7a5e95c49343d27ca44af0f9e390bba250aeb92fa0c88a3a42102f742399d3520b9cb8104e55f2722b370d6c0a2d2399eefb84e86b8080a0d986be733e5d42f0dc9ad48d286ebd31f1910c12b31e36a978b09b40882608d28080", + "d26b2a8ba4dada6f8977eaf6bd17d0bcfbab102b5202682c110aabe62ce2e6e5": "f90211a03372584598ea6dac89b00afac5e9ef15ad41d23a36111d908c7754659c2fc08ea02fedbc53b3d00e200e76d46ed1e33bf15b88f3b65c9beb01dffd47dc78675bd6a09326457b0be5d597199f4b5a52109e54928a58e9d4c335399adf0afcfe905dc6a066b2ebe2f04253e7a40162028fa9b7ce357a33f8f7130f4ea15eeb5eb5470beda02cd84a56ae1ceb56879a9f05498143f0df6d4f1f4bd9e0c7463cac5dbbca2124a00251fcaa592c765d789bc53aaad5d510ba354ad489e52177493047966edf450fa09924a2e8b2fd8ac5d4111bdee59089466b619d5a78a1eb0313757c328529fec9a0e888fa4f607ca747e6bb04be8c788045e2c9af49dd42aa2c452be8aa65e08b64a0426f1d656eca70b6f5403b4637f9cfcc319e73ef2c4b5e627dc4613e3b3376b3a0cb039be3a7e42e1dc3ea2584112b5f764f6b0f2f681e3dfecb0d8d3b69247477a0933c837627092e513aacac50e9556482519bd2d6bc0a9c2d00df52fee45e4626a07d00b8c5a57b7fa10c082b329c9ec5d1966186f8320d694590c632432fa3d30aa08af4ff2496d2208a46354ce83892c17b90267d19a8080291ff05cdec499e55bba075806ad1a51d0a097e944bf3d6806d88293024a800ac684a02bc0acacb31979da0a2ae25e98d131c84ec54851412e1fa4d5a8c9ee2f2efd3a8165b89c2034e23e9a0883275f0eeabda0b50367e55fcfbb103d72144e2dc02031eaef504cdcac4e0f880", + "d28c18e13afe286fe2b20c319c6baeffff9d6c267f19a3a654ba82313ee368c3": "f90131a021a807ad429b02021cb9d52626ad565af02e5cc8824e3c147750d14d8f39884d80a0b05c208a1e5a8635b65313f16e2848a6adf71d9fdbee7db581db130ef696dae180a021ff7eafda4ff664074d2806cd708fa44b6972f28fd3be42d85b38725be0d57c80a0c8a8ea5d15057ef476e126570c40d56ac3c1f1921d9dffa44669dfc9728eef9b80a0817a92cb17b7801878cef5f8f6831445a75d441a2fa8d67fb2a4d410f0378623a06c8ab3a486f09d3dc0e1f4ac9c4254b55e349d7323ba23b2fe819c88930f011080a0ffcee0c127e349bc57e90caa422dba1ea6bef18d6a0bd4b845ea80a0f028ea0380a0bff2685f2d70d70f688b155445eddc6e64f99ff7de0c2c8a67fe75d14c1e27dda0cac1b96fde52d9c7e16c922a334f9060b2b9078290ee7edc87094ef6e85619d08080", + "d2e47c44778cf1775cb363da3c200e595a3871633b4aff0d448a7de3e03fdbc7": "f90211a059cb827c864a9686c7594fd4f5582c25e0cbf33455898ae0fe1800145e1139e4a0b75cc101c1cafcb7ec520a6b495b9cada2527f431013ef78d70a464f6cc9d34ba0bb454dfad395dfcdbaa03c923b84f83c347fa2e617d763c3613f2097c176f44da00ae6517c9585825e9f3ea60629fae12818242ce5d53e4b196e6f7810d625ab6ea09a5552ff7d440a3bde9a310e900480ddb076efbaf360cf67deff5ccd98af8b6ea0576b4a52368bc71419107e2ec68997fb059c935ca3692ce241f369f38e53f754a0c5db4f3a0cd6faaa2f41dfdecfb64a00da58767c01af45f3c3c13ff5e0db00dda0450e20fe7821b955c3f424318f362977fdcd2c9033f7e4a3b3a7163912603b7fa08f0291ce7bda50f6c818af1648ac1932e0dfbf50d4d3d919acdc34ab68a93725a0a56378af292120fecd2e1e75cb3781193a0fe26fc39927936d669f522c6d4257a00b1750fadd538a2554264ae03b7545ea4b372a7b2cde6814676a854ac5fdd416a089f39938dd49c6892078230da99ab9afbfd8f0d36d48f1df2f318ffa4333b47da05061667b1133c828c45fde9059aef4cd698b003eb3ee0dc82f5ab48432d58831a0289e90be0cad23d33d842dbd4559ad92694fcecdff8dde6f2fe0e610b8854353a06fa043e8d7d61acb70085fd22c9c7f38f9357821f737888b9693004c7f1dab90a072a14fbcb89ba7d655f8afc5614e8c02d3c8b3942f61cc0c6697a1472e56337d80", + "d5626cb68f579840457a7bc4607260af2798fe34a02f1b80871b7e240eb3eea7": "f90211a073fe9bf668ea45af449da19c9ffe0a66eb8eb0630ea568e159231e80252d4f29a0233185270482e01a772775a1fd226e373cf20bd95b317d89d043829a5a011aa7a0b946a1019ee2194a5c711107623e3b67664c0c046d7625b89219dfcd0dbeb401a0cc235ac169185880a2055a37b40951992043c6d413cdad4d2aa7d7acdaa75449a0587fd1509148435cec5a2972f56c2457d173ab06c891718de31efe6407089ec3a0a8cc5087ba676f875f43028220f8a1ddc45dd8a0724a6a8c21eaafb32d3dec50a074ebb741679a5d8dff6aacd9ba632055e0060261c821fec6b1c37c19a651f756a0549556d571c086a4280ea0c8582591eca3c1d00edad3120174fc311e4338a099a0bf76f304425a0aae5c23ed7941787bb93db035f23b71efca7cf5cb3789e13d1aa0a0ad88bf39f6a00d6b5a9da2c2e3a8eeb9c20a94d3f1bb540b3783ec085c6618a0535bf09781099597eace7460b8021b09c6bc4f89151b6ff68bb7814aeac5866aa0bbe27a49309b650d65f06d045390d849355c17b08247df099f4b66b9bfc490f1a092686381fdfce4583a9638a71cd077589f8f3e1a7bbeb3ff770e73b7a25a8e7fa07ad75d94848616268aa277bad1582dac2f26f94d028321e58f532dc66369f602a0bf8ff48a6a3a35cf62f6a4ce8beee37d29c9ac2ff92f14d4ef6e1ef97bff22fca03d68775f5dee10b31d68d71e3faa7413cd5605e6d6bfa8f16e2b08c481e359f980", + "d706322a3d0cc1d9ed30c519aca353ee54e97744c2d8b19df188cc9efd89efa0": "f901318080a0b2e8b6bdd25e5c8df7f677044cd3d8da72b83e94339b575a0fbfe4ec77faded8a02f076749258f1190b54bdbf383d447c0161c1f5c859d10973e204fdf7827fd488080a03067aca1ae2e729acb8d8a9fef8a001ce63e763e8f8fd842611bc0e3fd8a0094a0589ff81e82aebaae236b21e67e88c51ce7014c2a4c831e1c7a731583618fb524a0e930015791ddfb40f0560a83903656ff8c9ec5b9e0c413879f076e74360d85a5a0398eabd316d22a87dc673801f47398c71e878f433ca65117ceac88e90100e9a680a02b095d8002754058c971bcd51f10a3ef2975970d54716ea2ee666bd55ba77b0a80a091ac33f28914ec4ee463d7b9d366a0f48a93771496ec24a6b4b7acad3e60045fa0b173412e7de1ed60ebd548833e3ea5695e25a1119e514c13d3f414c81484f5cf8080", + "d783c0f3ab85e061d97cfc724a4a5e3e9e3c0675be5ce0230d8f00d303ad9c52": "f8f180a052e18db3b80a82a7eb706b8cf4166e88518bf8d25ec6ff8e59893a4af5f33fa880a0b54d6be5a9c3afda7b304db7362b9c55df5d3f413dc3818c817609431f2d42638080a041c0a7e78598fa275a45becdfe4a3efeba7cb2b54313ad11fb812278507eb71580a0d0d1b093bbc2542625dbd5a6abc4bbfd5a0aedeb8930be0f8a7a34758cf87acca09de933dbc4bafc922a28011176ba6de6a015fadcc4fdb8a17011d52817365c9a808080a04327a611b120f0884937c2a3b86a13b71f91f3412a4d8eb3f4a82a7649a03acea0668d6b3c16c0109b54df732f0051ff33de2385b2ecb5da2c79185dc60d81138f8080", + "d81e37dd3361efdd6e6dd2b4ff16d1ae55dae3ab63545e0e839e0bfaa43dbd5d": "f90211a088c7f305f91b22654fa8d2896d75ebd92788ae53d9d45cc7599e07abe08003cea0e142d649dd96fe8380e9df94ebc362ece3335c2cd158fb3e76095ecc0d3c3e4ca0cfa209d9c9feb4b46705d8f18843ead9aab90a030942903722981a4ec040e9c1a0e1314642ca9441879353418f522053bc897c0c9117592197fe7ad9a354924cdaa0c4e7e688b90bb8582d05698430d25367505647c03bcd4be0e2a087ecd3da52e6a005066e16b0003f57913816272fa6064f5c023bd92115d40dc4b507c7b9e4ed4fa0679881e250d50de7896e20719f546c1cff5d86e1abfc4cfe79283f7364ee43a5a0e8c2e9a6690dc5c3c0edec95eb458a5f1a0bed0ce7b0b095e92350f39b80084ba0bbb91224d5f11a981f8678fe65983e60830c2fc357e3a130d2d2be2a39c939e9a05506931eb4bc56a30e39a91dbce7ceaaea9c0bc31b1014e7be84b55c294f67cca010c8144dadd55adf9b30c7122d31f0c1acb8c3f4616db3b56e511ef3ecef367ea075404c250c61cf1176ebb0b3de6eeaca54f5c36dbc212492cb870b5287465fa8a0e9477bf211f4e6033c441b71308bb962d5fa06a5d727718e56571a8443914aa6a0492b199495eb22ece7e18ee6e5a1866702beafac027dac8837e5da92e5175f40a08f3f257a70fc9d6eeee0cbb8afb8e98b75da41474a8af1dec842bbff00f6b659a01f6aac7544034dde4fc668c92321742f71fd0349165be787ae9ca19b30b0c86e80", + "d8fea56522f7a124e42e78352e9ed400bea9de3d74996288f22e66b38da15074": "f90211a059df98cd6a960fd3a170be2bc4f3a2e34a0d82da96ed885bd1c7041a9852edfba01678c376ba0565e0d38c6c17753bb0f23a19a1330f6b0878780227ce7190484ba0c236c084e8892b9f2b5e3e5b09c023285d7799e39748d33daa99b8309ecb2a75a0acba9ed77b13eb8893fd1b9b0d3ba9625417215f1076b93b9f1780cccc59c6e6a0d9670d6be535d78dfad81d23796f7b6629d13ae87f5a9911b1936cc022ba4512a084fc516c24e2952a638b255c762eb4f28ea5f969fdfb345678c704cbe84bb54aa0012b030778f32e6f836016a17333abd245152638b94e1c6fd8fc7d912d75e8a3a0c27b186e0d782d73c62a65cb179940580a6109c1ac766cac0369ccbf487c30c3a01aeaeca4d71bbc26c66a7ec4be8fcf808c9e5fda90b0fa0a5df0901aacae274ea053af391cf3919dc180db4bdc64623a5dfa6cf18c9ecacf02dff7506c0bc51c36a06d27a9966e94f1ea21971dfd9b2e7bb7cd8206c57fcb062cb305dd35ac432ee5a046fc22d6d07ba6dd611c5bffdbc2293c4c31cb228ab8a972066f30c8c64a83b8a03310cdc264b67e560164012a360da3e29c789f47865070b7ea38827c1685e40aa0c7febf529f53bf9ad26baf54048e668dcb42711e0d4adf58d7da1e48f6e23974a026d0451f40ac9abc98a2be0103f5e1a9410d67d49869a62058b1537b969f6aada00c15214956bb0f5a88e8e028c997833c6dac59818e7ca282be8192608e18234f80", + "d9670d6be535d78dfad81d23796f7b6629d13ae87f5a9911b1936cc022ba4512": "f8d1808080a04da03a5fd236544236b53971747e8fb47d6084cee6ee0b7ad9236cf6103c5d19a0cf54e1231aeb4cd9a537cdf77774c21ea2b97d147318c05cc0e604ca5d0b5707a0a4291d6922924b9ba1b8e1964c917a202ac5ba54090907d8a4736544d117ce40a0a759da580499f5a51f4dd6ac1d6b8cd32be79cf41108dc70f5afacf74cf8ae0b80a0210bb28b98bb79b93232d637920d7af4e1c7fd735aeacdc51e7459c5d50ceb8880808080a059e637746eb3b0983b8b300d2df6fce1f729227554608c0677f4db52abf9fbf6808080", + "d971489d3c532e28f8fa13a4190203823ee662109245f91a2a9f556bf6b7912c": "f8518080a0f719ffd7f9562924bcfe03021fafd2a89b8625b914d435e60c9b6e2702333c03808080808080808080a0a81fd467c66204a7aec13a098c068df51c944c8da012fc621ddca6265fd0769080808080", + "da2d58f4b9eb7a2555c49d3829ef09e7089a13286faa94d42c241107ed198600": "f8b180a0d51757dc1f2a252923992e02b6eb9c250af98d51a7076e087e29ff134cb478aaa0d466e86322b8ff25541f187186643cfc9359b49518ad206e93aa650081a83739808080a076d23daa0a31a7fd12f4305b01f68208c47c867a47e371e52101ebd0c84f06ac8080808080a0234b49e2fd87964dc7849cd79c50af5d0778db0b4349ec54f97f4ca60956cdcfa0eac1687218941e0bfe7e1fbcfbcedf244ad25f617bfd897856c38b36223a5f4c808080", + "da68687a9b35ed6f2a70b85ad12b3a045deab691b94abcd4da36555f39cb5d44": "f8f18080a0a7fc3b20ae00ae0dc2c660fa4fb2866cbec4d19d47ceabdd03c16ad63366fd5ca0597d1527517611d1724220ebfca41c9e4c3640ffac4ccbc96e86a20a01020af080a0ffc0533be8f83d4a258ad5cdc10143016f25160c0af31170257e539891461797808080a05bf04fdb6d835662530c0b455691c0733936852e57dfab7f1652f5e4fd0076fb808080a0c751fea88573c1120d7ac4d2202d31917dad4a89cf2bae4c8544b4233f7a2382a06ede77dadb3f9f98e9b30d2a33f0245ac3760a321565fd5df681e5f6e7ad599fa0a1c2fc5b45ffbea953bbf6baedb72cb9e708c46568d92844403c914c55e5d8f880", + "dc67281822dbad3723d1eb3351868a8217f0d2a6b921e2a1f116abe441bb250d": "f90211a0bd3702c0dfc79748400d72dfb91231502e0ecbfff94c3f315cf5911c6102cdbfa0461cba92d2108ffacc398c2ea26f1a463ccc83b1ce57e0dfca0d4c9838c2d3f7a0b16bc4b448c09e34236f840731f13874f7bfc73142dfc1534c41347f1d154213a058b639d7ec70a1d1eb2238aba343c4863aa84d1df2e49af8d2f396943364aba8a0955af49b8b5bcd8e3d050f1630fd90517aa20b9d3f810621348f3f653b2b4466a04ebac6c98999985c1c9a1b766bdbf0ac0885cc78246e3b893cfc139ba00673d3a0e91e5a6560d6cab596f011eca7b95b98d666de5dc3a4c5ac274e80045c9fec92a0bffb80a1d1e6487d63ceec17ec296bf7bd361c895f1f6657ac4d14da9659f422a0fb49e0c1a443c2e0260c4c14458e375b6ed07880a32e671199fbc973f91cc120a0da3a1f5319ae2faa21938b452a5d4052ff1246a5c97554afafba8eca21d823eba0932608ce5333a7f3720c20b2ec43c434f8bab97bf0427962166bfca3c690596ba0075d41a53b84ac008697ea307563199a612c2ea02c0926c168d5725724d95227a0988f5d5712ec04a260abfdc7f86ee66b8c61261c4bb296abf36df5d345fc01a0a0b82a1b38bc1ab3a803f5d43710e0139b54555a5712c1b1c6513859ed2e96124ca029b750dd7f6033d5f8a766fc04f013e2af6e31202a10452095cb395012764c36a010656c50044c8c60886d09baad3dfd7b37de5a281b82c04c4626e844971e718580", + "dcdb5ba60059f1cb4190d9e5b28c51ecee4a37965dae4ebc039569d7de2e88c9": "f90211a032ef1ac9353a5970916abaf4b8d9a986fb369309252ec8fdb7d71e79d5d40ee9a0a7e482f75f359d439d27ff5fb5ed2b6796a05ee9f5bc66c00f1d53a9cbc6336ea0facebb03314f4f39daad4aaf485b63c6f7a7947afd96b9631e82d2d9cfbb3501a0208544cc467a0bffdbdfe633973919618dccd501c8514cc5dd62e2d42c0ba215a0e3c8d618dadc597cc25f79513b63080f2d61ea4d83c59c8808a3d2ae435d882ca0286a21ce3d4bac7a178b48992c17051e9044a882b195b205e0152310c74f8d7aa05abae31e52072a09e79dca70824ead4b5aecea57ad17896d117846512323f179a02f5321575aeeb91f8da931b9b252ae053fc510fb0e18a28292d0c8562cad64aca0f40baf7a21a37608930275b07ec48828000b1f2dd09700e5c46d20bfbba7bb50a0e95409e90d6712fd2f39fb156cd39fb7378d1fe154d8dd138f119f30076a69c0a035314eb4d2410929462907f8f295e5ac58b4049f2a46f1ba8605ae69e29ccdfda039f624a3e26dfe1a041160483e9185618b209ba6fdb03efee945af328a5b112ba0f8c9d6cd875ed955580f97e52e21b32da3cc69f802e14d4b3698371890573fc4a089e89b8a6bc10bb7de5b33bd337492f110f3166b6c88e6b9c9d720453668cceba0a64015ba69129ac2f6a649348fbdcaa1139749bd8553667742c256b42a0986c5a002594b5f39c9d150eeebcafd4c2b69b76fd1a90a9e293e369613c43538f4e52280", + "de6a446b251c0750543bc9290d7d0fda03fa7b85bb543e68e9a3775250e04ee9": "f90211a0ec18088432e18321b93a3af7641423179e3ab5f2a0f5ac8054adb96e46cf26b8a01466d30e7649263168d6a913e44fd73987717f396633c8e7b69a8b526cfd3d5fa03731487bf62974358fd9927c498ba731251878e5f8767f290d4535c960061093a0c50b1d6bf8bd6e9c267ff1e7f66eaddd08736dac4f0f0aed6fc252877b0782f5a086a4d3f4b1d28a0bb5a899ac16258f5072fc2d4b3726218db944e927544db595a0f2a098252ea13413d31f84f41b9eabed0148be4100cae35328c35e483426045da034d8ad9629c4fa6d0f4a751fe12560ebe85d433c2a55d6959d18b8ff74966e00a0c3c0fc57bf1ac51187db16f054a1551ca63d8c7df070835e61ba8989335a47dfa0f33f50dc23dc9e85e47be56fd20a2e3b5bd8d1261e6d1a239fed59cbe1552d25a02a0eb724ec3ebea9af2c8b5c3216533f992cd1f1a836fd224cff79c36516afa4a015627c03bf53f559c4d3b916e0f10edd1424800bf6ccfeed2e8228b3e8d81a46a0c61f03f12fb9e3b706d389f66083262a2526d6db408afbacb11ff263912e8be6a0adf2cf3d5347de8f86c1c28b1d3934bcd120f1c283b7433c56c1a6e78392cc60a0123241cd2d7beef1be4348da5aa50a45b481d715e5fe5052d67dd86bc35424a9a08407b329c05a34d31380dd657a601d64a4bdf31a69b9828462d407b33d90d4e5a07557c94d2d3164e3e9ff6dbcf53392292a8ad291737332cfcfbfd9732375b7f580", + "dea4848b9b977b858e8c56b38d49f4fc9621c3c2179de490d235f1a665d87ab6": "f90211a0b854407bcb77713db5346d22eb60827ee771c543caa79f2f673f21c82203cd91a07707f55438e215cf961e838fed2641db7c9536843c5ea910c248c2d8163c813ea09f0d4a0696cc088e7d82960a93a8a73cc6d149b98cb3581298c3ef4fe49a4e30a0c01484df1ca6eae107468c11437bfea188562d2ba802a1573d143f331bc1200ba062e82f6ae361c1b2da99cde1f5de3834293dcd938f473b003dee56e2849ec40ea06bb2eb0a64730d3e652c228bae4b3679e828b15c27d9071fe8d4ad6082b41619a07031338ed253dd4adab3f5d5c7d5952d63d45357ecf8e7c36407820dea3fcba4a04dbb8db8c7e8920a00ec19056ffa0b1b078ca28fb237911be784092aaea19b23a081a2b3d6fee7f774fc83d723c8762211f23e3830186a3b7da624de53f82a1799a0d91136d1e0564e615d60c8a7d355af2e8238df43735a9e1ec42c88726f152f09a030c7076402f79631f52338c0bea72bb695647baa2b72c22e3b0ea7202eed9ca1a0d2390736185bcdd32d9c5a0976ec9275ebe316e1d65d546e4166dddd3157193ea0571adfadbe1e5832602cac8376e01895d4e2b5b87a102ca1bade792d427df296a03086be308c165a4fafdb4d1b03dbd90a217d07a2971f9937ca598f47d4051d08a0d2e47c44778cf1775cb363da3c200e595a3871633b4aff0d448a7de3e03fdbc7a05b384328eb29259ac93833822a5447319dd6d781fd7ccb794aa247eaed2cc2ba80", + "dea914b89ff259902acca17c90d27a9cb980e5cff9b516db8d77aecafee64438": "f90211a016ac58c68185172e8d34a0b64d94595995bcc40aed433da6b23467c743a72986a098c2bc7ab7400049ddc76177c707ff5e5192270e76e750bff3d516a778a2f67fa06e43ddfaf79c86a57f7e2f900184576994fc507f66cc80c300361ee2c921972ea0160b0be7a23770cfbd6affd3035853dd1817ee0f6cff9da9d3f143ac18c1a53ea043f4550adb8ff5d2584d2cd33a9d99e46e3a7f42c0e2b12778619ef45cfca68ca05ccfa0b18c13b56e579987c56a16b545b359d35b0dd0efff6dcd5af7bc9b9f2ea0b4fbbd80244d53ef326076cb060f2f4bbe3f5e72ac044b644cf7a5119c61ffbaa0a7f2ade61b93ee1069dd096a4febce59715104cc861ce233a3a32446584a5a92a0d2623f120154b315718b3f586872e3fb742265bcc185fa0dc1ceb2cf645e98caa0f143ceb1d07423c80ba25b514ada48f1387ef69201b9669f4c6c6e1ff3bf4227a0a8132c80dd561ab864312d697e51839f7138bae5cdc80c123d3d2a18ea125e40a0e9b38c273f0db1cd9bf262c72c774ee468b437302b2efa5b1a890c677cf9f9e1a0ad605d41243e74e8e4cadd453b01bf90276de82bd5abaf71a994aa398efffaa1a0355fed079e23106851fff677a922345ae7cfb1f25aa6d2a4ea24ceae6d509d1fa051f92f6cad19b7da764f32fbc8a00db408794dc6f1c2f1de3fed14c148614b22a0e1ae05942f0d900242a9377dda61a5ba3c4d118c3fb4310ad59032d83e0dcf0280", + "e455c9e9c13f83104d5b848239206ea5cacb2cfd5e04cdb6eec0d869c36fe076": "f90211a05b306254b380316c6d4b7188eae217793724b18bd10010f2ce575852d0fba16aa0ad1e00700c40c3d2ddb49a1c80d0ebab537bddb862224bbdc58b930736e591c1a0a24feae5d4de51cee413ab56b0a5aef3a1fed50bdf7160ba110420c7924879f2a0fa36c7abe9728e9218ede73f530f847cb9ec9e113dd5ee0c3d136425a31e294ba081cd6e1a1cadce744e53cb15636b5dd702241f1a6c9e382b31ba24dbe667ecd1a06a6217dc0e085444f4831d2ed334d065d06769d30d33af9f9d7eaf03606edd62a01494d50d60afa32c2e9e51c86e0e24c2a0dd115117bb5891e24d5a74a99a787ca0319a9dcc15e8a4e0a2a166c2a81f37693b6dade76926211e2c3f96967ac44a52a06f3546e8ad1ea7d2793341c76574e9946aab41d57d53d8299bb11080ad7e959fa09339e754a575bd75b132a118aff3161ed10b576c768a4224afda6237b66ab751a07596531c88c2844c5846ccd19f0e8344c0296e3191daf5bc15fb720d393f5145a03b69756a1be7b5d986556a802f9a9bdbd922b307d751df0687065e7093888e98a01b84dab9c1810385983d1338c4fcd83874b92d5ac5841c867db2c7e3a423e478a0c9019476527507dc7263f2cb8a2f8b5ce1d617d100794252dc3bba2d9844f9a5a06409979b958673bb9e7f1fef28d48593b58ba3eeae9b50f5122cbf2aff76ba87a07bb1727d38b0bc01c2f0b256768d7c3d081763c383649d184dbde2060f2fc16180", + "e51eb8a91a53d9b9723020c10b9c90c9a5357683b2294c08400b3e18cfacbc31": "f90211a0282b7f30d99f1f21396157977e3f545da8dddaf6a9c5c8508d4f08bcd57f733ba0c2160db198b88cf14c25e8a2bb26d66c728f9d071da682df65d65a6e715b427fa03bbf6c6535a3025f1241b51863b866240ed9931e748f1151290b4d6a653668bba01285ff0827d8f0a569292bedc7bd012ceca688c006a96d0a53dbd93b540393cfa050fa9e3075490c1ee61c904338ef0c7470a313718f6255fc3a1df0867256054fa0c3c0530d0767f43d1a9f6e43411b5e82bd30cf56cdc1225d639fc792f3120465a023d205e1165e1fc2b9cef28dd8e8ab473ca63f8b5593e2d6dd6b94417a29ec14a0ac5d893432c436047730146474a153749b626d59940ce3f358ae11d5c451583ba0e9cc306e37b166d2b8ccac44ba5866a379186c434eb10794bbfd7add2ca7f6c0a00f4aced82cea6c09bbce6cdf63dd51eb3850a251484110fd2fdddb4360e757eda031484d644416c072848bdd99c2fd292fc54b8a299901ad55b2789ae15acb055aa04258f4246c113eca21c12a271d8194ca8822f337bc370963335999ca9daff765a09b1b3410b0a2911a19beccc6efaba714f0b6d34b07df836df902c5f5a14fbcc0a063ef8dd057e1e3866d153192b61492e25959824e75d599efd2bc966e0da2513fa033de704a296b573493802fccbcd059f0fb5390303c102ca976c0f4d62a613d3ea0523e9e54a7d970a187f210a9f3b067c75cf6a44fc18e05135d52b67ffad75c7b80", + "e5374bde4be096c791d5d4d42b2e419221b1b639065ee1434f99b2ee41baead7": "f90211a06327be637fe26eadd02d937d2d69b70af3a522cfc67f0a7a954f2aafb710e74fa034143e5bc9356f9b1b7587fa417ff9f4eb4ff86a0d76478147914c7c8ee575f9a07238ef1ddf393ef8079c9a1930fd78608d2cca424142d1bf7b9cf6e89801ecf1a05ee6eefab3e33378422a1e52f21529af6d65ac2f2e51871b118676bf8d5c9519a0b79e2d89606d9506a83ed828013793622bc6920b62d7f76a6f7993e2851d038aa08541a6df2e2bff17fcfcc385fb7ea1aa78c3884f0435d8f3720f1f5749aacbe2a03a97fd82f74b8ea4861ced600d7592fea158810dfc1acf7439b8cf31ce62b7c8a08813da7d3cc7dcb5dd7b7f040ebd8ea7d7fd0424e72246697c3f3e0f511bf4cba002a4e1a0c0e8d62053ccbb0a07e3162eade8acb31f8bc6504283c6856848d7b8a036cb92ba36742f66d8b57e39e8e27fe2f97fe2d99c91d2fe3ad312cfb5d09851a0629367fa72300d95e7bb617903fc2026e63e47ad27689bcaf68340a90504452ca0d64f5dfe05b5ca777f76b0e11c41421f9f60fa2d9a43c52b5f0791c7b8d6bf21a0b984127bcf377fbd1313949923a389499750bcc3c2a3de9a084602148d60e897a0f59c5c69539506bb7180bdcdfcef631b2aa2244bbe9e1eaef282e004a773d3e7a017efd0d9bd4d115ce158015c1f2c1f4c25fbf2c5e9455587e33dabe768e30162a031e406ee7ba66980b7490592426810e1f388ba8001e8556411bc5864ea5df43880", + "e5cdac661e8411ef431da9abf0ecbe19fef7b490fd3f3adcc846e40fa9aba5e6": "f90211a0dce91de7f9c2709410aa02c055b8e964ad492e14eeb672af667826257436836da086642664b1c879170ae16882a47e61a3eab7f08e7bfb9bf18ac43e3c9aaeb4c0a08ae73395f7587731e391c800f18eb9b91b38e4ff40ac8032403334ae35423618a084097ea11e5053c8095a34f7cda7d1633ce43b0db74b20dc19db3b338ab67384a079316b96cfa23edcfe77407e4a7b9c60af0ac4b6f04896bed3ca69b72942cbb2a09115f7f69d189d3e5639eb62b484f18ee541a491d84a83a29a8694d9b9240a3ea08eedf9ae1f5f5f469179ea2c1dbb12c86b4be87828b93670b535b53cbf45125ea06db0f1c21d61beb7d027e18b51952c94f257f811273c7e3d999915e014eb6d9ea01c6e77f3f3ccdf5855aa998a44262258122dd8756ff936a7371a79fd7351dc62a0d7add808b1222d3e166620152d4d8694f0368b97225b06ed06dacfa76cc0f9bda0d419583c2711b8a4592ce7f071cd1c69b734502a4bf8f0f2c62b0874159620a8a0056d8c961e5ee897ce79ed1585ebb1281c28b85f7f3b8a1bbcefa809789975a1a02daa55e490f824ee5886f79258752d52bb432dca91757dea7d919bd8a359709ea0fb7dae6a7b88aa0a8a302ecd178b433da26fdbd02c8ddfd1dc643de305fc6017a0d6335c2f160e36a210667de4246822cf84f5fa636ac42b1120c7791fb49b88fba0df3e5541b3eef4f86dd2453f3996095df7325c3f62ca2c54d08b09a59602035280", + "e6517b1c04ff2f297604b90dcdf2d26eefb5b6c183e23e47a0bd1a98f15bd462": "f901318080a0769ff65ded9601d7d5c49c83f7270e434c427726f4e58cac6f55ce05e70066a08080a0f4794aeea59b611cd1019b6809571058d13ac3cd573721b8241dbac08caa2f3680a000a7df79be1db7e933de735cae2a7f090c2a7a9aa53d0f5f644bd09a07d1313480a04f97435e588970030f1654169f8d2041c4e19eebf0b9fe13c473f6b8727c8b2da04227b49b486ddf93361b799c84e3d4092f49a2bbd3bb6bfd985c39bf4fb601bca02a7064120dc887fd6ba3f37aad2c50c05620ab59195e5a0e2c1cfc176babdb12a0579c49b829565d9f9464b27184e8b9d30f6e20be49450ceff157df180bb4542ca0acda7636c53efb7d3ba2cc30b17c27df660ca4db889d3d0d24fb09458072d89aa0defdb1e0a06912fa405b9c8e06d53b593f0e8d64cbde17dabea5c1bd2321c8ad8080", + "e6864b9874664405d167ef15c4a0d3ca2214446ce2e51ec7d3fc07ee4f7d3be0": "f8b1a077b8e3c2d5f118c1b1b7ff361e24d5bc356827fcfd3e1b0306cd30cad93b4cc580a0c3fcfa17534945bef368ccb85d47ccf60cce90baac9e0c69345abb0e5fab36e18080808080808080a008aa78cb008c378f7f99cfd03cc1c8b3e7580759e119672fef134fabb1ae0c1ca0e334e34c8161394717a4d3e9c17bf59384d2a88bf2ca76a191df31ea464acf0680a065f6b287af5bbd4ee1dbfc8466b7af22bd865ad929ff22321131a396a71bc5228080", + "e70ca022df7793435bf43c3f3b669ebe9974f74199793b417e824c025579916a": "f90211a0ed0c18f88ef9de1d08d05681860d6a19105eaacb7d65329d568e12f047b645e3a0b4470b33249d68e221f7274ccbc7abd029f63d1326d2a6e894449a66039500e5a04ed87eae28641241a86bc76a216bd1ed5bfffdbaaa4e8473a34b22729912c07ca057c08248e120c8ff1f8a53effd76c1267ac2c0f85f64793f6bc000ec41b24f02a0ca1eb8d42a08ed15842c7c30af5d512cd3df6c6f0834026c1bf90e0b7c742abfa043e42cf5ccc16e043575bbade8e8507ad4a82b4df37f839b922c49fcef63a7e2a0e793d0940a6bd34c05928b9e519e996de7e645e20c03fd97d3a1a37cae7ffe10a0512e57096893b2de2a261c9bd048a6aa4be1c2d32cd03f227efdcbe003b53c8ba0973ddfd52865ca29561ac351d06d66c8914af8fa9e2dd7faa7786bc8a1433bf7a055a72f3779d0fcf2cbb630fb4a72ed0591f8aca661c94df186575f24a865242da03ef7419dc1347ad7ed16ee3598f97b0ac73899a1466d31a8faa6b8f3c4b092cba07e95a1fd272c8fc7f1d6bc79e4d97064806f2280fb15ced5857ebc3ae03227b3a059b409411397399a56a1c155056d7075d2b96b39678afe9374244ed012be9786a086bda51bf458420d3f537f5cdda5a2e703ea2e2266a7618c3c2fe2b08e866b8ca02e5c45014b9d39d9e7976d4006ad6476db46636360506f6331f8fd587b603b71a01d9a6ad9cc2907b5082fb787742a00a1ecb8d92ceae038fe7902668b76bdd13880", + "e84481c24cd5b58b3251009d714726852a4c0800637f09cdd7a8c62988cae67e": "f90211a0d3c8f58f2d6340f1cbbb0b8997a7b9a571c45c149208bd01c7f8dffaa55f1840a060ab34ace436e4d5edfe062f24782e24b1520ac524c73452ad164b8643478f25a03047f6408e5055f987993312a846bbd736edb6df01e841a8779977e29aa6eb5ea0d8e3fa957e6efe54a7c9d6458e37810611b136a34444fbdaec8845bd43f02260a0a177e9c2b657f026c3d7d10e437e738d9f1b25440c1d76cb73ccbb94afc80872a04c5aba4c67893b26b8d347ad29d4b2aacf7aa7d3dadcd54c0b2dcb0e8f9c0278a0439e20c8de404b259a387781ce7d662b2c94d05973ce8810684bfaf122d69860a08310dd15252489643c3f1f7043af3eaac520b68eccab92410f7f078a58c2f947a0776c94ea47a2c5573d2a1c806d5361223b28fe7f44e3bca7d652cb629178d91fa0db20529583c9b85818154f38cea096e86c43ed0d81d7f468682e730274ab558ea0a19f56424a412164ca1d7e6ed792079a5e876dbb0f01e1191f41323bfc10e3eda07cb0aea9fb7394a1131d181413d9081268d7739271e7b354d5305936cf32bd6fa06e0655c0e0a7599405856a37e6addb71a6076a58032ee0a1f514b143ebacca2ca0c0d3a75cc108beafe43a4912af3440b7eeb0bf847cffacdd3ecb9d5d2cf323dba0dd8aea9014d9309ec23b170c2eb18a9b0944b94fdccc47350fd10a63ee7c40afa0928cf1ddc71f0a79bf43c187692695814089f33b589cebb2d6d3b912bb26838080", + "e904e8981e2f78221111e7907f72c7377bbaa0b594c06494f5a272f5ab6d44df": "f8b1808080a047a9f4a8ea5162f5c0383f289d1a87c44bb0e0bb815986cc65f23de96bc7c7d9a0622c8fda554fdd583bb09bce7cd36543433d3e38be667cdd590a5351bd2283ba808080a0ca4fbf8d57c8ae4852e67ce374c82c67615981e21106ddcdb78ac5b79e95b2b18080a0aa45ebb0e3e55a1d9bcf06f2f13948b244f8192e251377a68ac0d65fe246d25b808080a0e8f8f31dcf9d04221d1907cf674fcbd2cb5a6980c73755f81e10b1a62848817480", + "e9100dc84a099da7c6f7f863b9ddc3d9fd74eaf8b7f52a889252f62af65a59f4": "f90211a0df9d2858284b58f7cc3ae837ef039b36b9723662e989425a26fad73327929ed8a03cd382be091224d7bc4a112b4cfa8aa25ee81e0f8aa6eb19f4f416b1791056d7a0a8294992db59c3687b4769b504fab98ee5889c4ed0a868e9b54d9382bae192e4a05d9d09bd83097c9313aba1d3c9169aff306d8ae1ccdee3546123402d1d49b66da0cbaa5a650c21af62bdd008fd353cf1503016bfe28b2f7c30ec343cb7b3af42a0a07d87dfe8ab06e003ac727878ccd987ead1e52a2488403ef22ae7d48213c9ca98a0e322f1749ae7cf1028ed8a3b9142db29b60ebc0f87997932e4be0770a47891a6a0752b4142aaf7f1e457737c404c8d1e5edd3dd4da21c6e9392f1bd97270512957a0987ad829cec3ff571720db51fa58319abba8589be6e8c64f817dc64655299747a089ff6575a993a95f7366d4939e121f0c7ffa5f19686495b56bdb2ed4d80e3fe0a0e5cc14b50095ece15d555ace24a72f695fe558d0872ab486655c7247ef2dbd24a03db691c2cf45267da809af1f8030a3931d99f2bc704bd097def6af781d0d17dda0b055d890fcdd49d7189beddcd567f7f8cab5856323958217ee72a99376cb38f0a081917dca950ff6d291b600265bedea6c1e4c2ce559818c42059cf70666fc0c8aa02856fadf2b840869503f463de5029804fa0ff5d74ee0fb8bae9ced357e9e3831a02f8ff6df7a041d5f8a279c1562aaa4e37e388d44649939dfdc2f14de2a5336bf80", + "ea20d5a286aaa075afe2aaac98f53de26fa250a220d0f36ab4bafcca40628e74": "f90211a07f9297e3685d80c07a9fe8ab05e49be27448a92e3862be5d7b5328d96d2ec6aba0b0d3dfffceb8aaa35130a73b0b7152744056c0bcf01089d04f933e87db10f884a066142bdf1766b8c40c8acfd1ddd50f80cd667c78d7bc9088ae7e2d2043d49511a0ad926d84f98a507288e100110956bdc4b7adbd2c117f53851502c27abaec0752a02f2763f23a11a3d316ae06226082389dc3654eb187f7d21baf9872f1f6fde290a029fe9dc212d629d113cc0c0c67303ecc02e5e28fc875e3791bb9cb8a2ab4615ba02b510d637ae30f2dd05cc376e0ce64ec7e447a9da6a876e0006c7143d6db0186a05a4100b75834827fc8a55e32abb5fd6f5aedf74d5b1055c12743700fc7a18206a0edf7fce5fc0c03ad0b8a892d973f842c2028c5e02142bd3b1cd366a4ffd12e31a04e129ff5bd6744600a1cf2001e1072867c3ac1cf5be28c8e9cd19ca356162592a034eb9bbaec30efb16ce8a26376b121120bacc721442f0ec55c5833f3b91d066da0340b2c9363b4bdb81fc896b50e874ac4daddeeda6a78800de3bb4dd97eeea526a05fcaf602bbcae650b814e7d89837b6e9036f0b6fc7f1d92b46716cdcd7ba59c0a0362e5f90c723b6f8d6a8a4c7ee1b1a5e72e39bb180942316444ac762e4b0c82ea01231fd0eec20d3eb156294e34a18d31682a79f4f4eb63eb354c55594f6cc833ca06ce9a9eb714a21f2431ebfe4edece03d5e916ef89771c8fa269b51305f815d1b80", + "ea2e3258ef3435ea0834fcfdca5b64806b062643d36ce6721d17256cb7aa7b9c": "f8419e37df00937b24ec62aeebbbbc4064f6ffea3b0561e398ecb981b827da4b04a1a0feedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabe", + "eadc924c27252102387ff446a4b4502e375438ae22b14be8c7f86006d958ddf5": "e39e36c251e6d3e3fb3224dc4d782c5c2ff76262edd8af06e63c294971f017bb83820801", + "eb5519d63a3c198af4978ef69319fe72e73c747d74dbdf1e4210070e5cbf300d": "f9015180a0b82a4c013a1f09833e61042e19acc9eeb08428b6612b852078acd8e7fadc4f08a0431e4287c47f0ae413168ec07d800ac25e754e9bec6ff0596982e543dc1432128080a0c31eb112fe4313daad570c2115931cecd628bf495bb9643b86ba6e4e3bc67bf0a077c0a5a0003dde23d568e72e1c681bee08af7cd4b1c49ccc61e206ac98120540a047b5a3011cc1c0e341309330b5370634958038c56a4980a159d93d00df7318d98080a04f4efcf750344137ab7926584483376bf4859e8329b8e6f63f4fb4140b8fc1c7a0168f8013cb82abc89c4290a5854613dfa69fe7dce4b88a9614a3a1debe3b84e4a0c4589c710643d5f836a0335046cf5eee4534c383d93e70ff0fddc285bfbbabc9a087a6aeba48866c036928d461c24e934c6739507e264cc0de663a06c79f2f80e880a0a5085dd481a307374d5f1e4b01794ca01f6ce834f208cafae8ed2383082a4e1880", + "ebd5332ca24e5ca847eb2cd1cc0d661668632aa02bf11fc096b1debe0c727236": "f90211a05a8808f5656f3ff357fa2ec77b055dcd4b3eb3f2d151e44b1156b4b57f942c3da07230ad6e84db8fef1870586de47c908ca519c9c9bf589e0ab7cc60395571249ea0ba15a1ef1ba30b1253de0c0a905c8b7aed87f0033474defbf36f4507a8ba1e02a03e2f05bf2d7cfb75012baf648b043582adcbe55addb92bfb24f36a32d5a4698da0a04d852a1016f7f2bb52521d45b0b8f07a5d5340ffcae61ae26c1219828b1e1ba05c60434e02ee8e4b0bdcc535bb0a7be1a890f8796a72a0c462090cb56e6d019fa099793283c952f0699d67041a524c6237d6ec6e2d03190b2a35355563ff756544a0b6996b3827e5337245f1ee2a8b58a14b27b9d455d3b2e381d96bc29e257b5b92a07281a3fd3fc55357b62af11a8faa1d2bbf94f855f48c9848ce61ccae45d433c5a085dc29768e3e27cd2290af8f5afc4201f3e6cc00087a00157130784212e94ed4a04226e9d66fe40d64319c12eabf51706c44015ab97c6e485ff8de18b426809ae5a035bb36b6d70d56d7ed13520c538f28c5ee9437eb7fc1d478730ba3da3dff4bc8a0b88f44dd5432ea5b3226dfcc2af8791321d1923abd7381f50672d214b81b3835a0fe9137081219e4c5f91eb9f6e5c5063ef1015a7355faeb32a4dc14fecc8f7d0ea00e4b5f0422ee8a35f19fd893a21e106ff514c907fe223e224e9e2650cfbf2affa0e12a8cc579df4f065795b86c1244692b0a6bbe5620dbf4397d811120af069d8880", + "ebfff3286207536c9ddaf49e8aaa3f1c1be7a540dceb4806c90cd6b63b578970": "f9013180a08c1d971be23db6faf04e673945fab56c7cbc72f69359b1df07a764c5cf5f3a90a05f0aca551491b22041f63c6351f960b3111d50ffad4bddac08d194ff01d2dc8580a03f1223675a324f8cf7906f690ff9c8e06327aea55a117d3442609a0ecc5c9cd980a06dcc36dd70bd6ae51dc2eff21067ad37cf9b2a89e81dfddae2037b228413ab6f8080a07fc3a34ead195b4ba3319e8ef047764e640871674d4f58871720750ded3a3359a09117a258cdfb0c0fd537c33d4b15deade7505dad5e2f794e6606d1c163868afa80a0c2576efb68cc861fcaa3fe1dcc931291e55845ca0e9f2bed6faaa3b9a2c708c180a0a8a3185d8ccce3c2390f2f93b4a8245e3d39cfd0ffae9a1336219251be9bf1baa0acb1713b120c498d5bf2b1071c7f95d19d1edad2eb0f83d0cb62f561c067e0bc80", + "ec8972f15beec00c03f1a83ba36f03c33e6b8952aaff8a81cbd08112c5f5ab92": "f90211a0ac6d5407d0f41a83aa13e1efa838eccbea8331fdb4b1e22a0243f38d4ab136cba0fe60a4bce77d097c8936a4456ba3c83144092df6c49d8f17e2e270f836eaa7eba0608e077ac7cba5bbfa0cbe8f6a3f2509a4bce7f5496d58970ad06fde63a5bd22a0e75cf0b4b4fdccecd48531097fdf468e626a32cdb22b9d60ff53730db37ce585a0788807bbb02f189198b820f71d1aaf5b4ae3e9430155a8c4cffe1d0ce2d3b2d4a016cacf9b8d699132e14c7993faca8c4e1c2222437c80cc1e64dfd6b759b849d9a0b3b62fefbf100b8144183b404c069dfce3ed10a40decda737433cc39fb94d504a03e87e0be1080a3fa22c6f60959b7c46baf16383be61d1f793776eadc738851d0a0233fe93857b5766ac96a0c2319ababcf3d3b52e9d7c12f20dda2d6d720d64b03a0cfbb2eee735a50638c4ccd016658951bd89ebced77352f1c85082e68fbaff7a6a068398141d5083756202e9d95b30a1ce3bbfc988f56a99d66942e512235aa223da019127cfb2e00353ea06e9a588a4209a3ca900560f14cddbdc3c05b90930563dba0a7e57c092f19c1ab9fd7a64e4ed69a3ba73f110f1bba341134196b77fe0ac028a03aaf2957e0101577ed193f7ee1a2ad98a14f2f1928fdf306e2f0913eb03f2efea0fade037931798fa5dabfb04c41c717dfe3231af4baa19957c97bdd9a70d5036da04507aa51988f3d73ec1c8aa12917fc4ecca368117fa5842f7d6f2549c18baa8380", + "ed0c18f88ef9de1d08d05681860d6a19105eaacb7d65329d568e12f047b645e3": "f8b180a04457c0f4fa1f50449c072f141d55640e91374c6509e2615e0efed1f08d5280f58080a0b89548612b8f18d53bd59d8e737fffbb995236457153674e5dd97f6abed46c7d808080a025b074e894f6d84b3583922721a62070ee8c1da62f92223e558bfd58a0f60bc7808080a0e2c7d190f9ddf08d3113b9394b2369ba868b8b4aabb13f37b9559a088a450db480a014f100a607ad8df72154f0e971223ac8344e8877269e05e53ac0c0989345e8448080", + "edfbbf076d9dc0e497939f5726e88eb23d95e05788c5de0bca82ec28f2cde03f": "f8419e3ef71bbd83b9277ec15f5b27ef7822c33b2e55644e95b9f1430665202976a1a0baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ff", + "ef5a162b77400a3a2513a451dd761ab2ba5c94ac8286248db5855c2e2fa788c0": "f9011180a0cc1a4df8439f81f3fabb8d66ae387cca8edf9c555e29bfc36dddaf0545acca638080a0b66ed527206bb85211b7aae938396ffaf45b1bae22d4b69fba6323d070b7de3ba03249547b7bf3ea063e2db4ca25c575ac5387d2825ec6cbac09ec9e209c0626a9a04d34d40be2f0af53b73f46bb34926b2b731460d905b1ddc530d09a12ca62ad4ea059029277c6d13eb307ddcb309ac1ef70fdb9b8b393d7b3061303028e3ae8a02e80a0af625d82d34de8b53b3f40719933cc8f32096add3a5f8c13245fdf8712de84c28080a037d7849c8f470d218a904665a7a394ab6610e27a3413e9bf8ef685823da746e58080a06009ccc99d187ee35a1436069fc6b17ea0c7590cbd83e9c4578600a601ed5b0a80", + "ef7862e67d698683544b265a5fe194b1a37d98010898eb67f3492bba615674e2": "f90211a0abd50f8bdd2de9f18072d2f0a0bd0447301841be5a36c11f1bba1041a1bf0a1fa0e5267dc3d82fdd1b5f07c6d6d302aa30ba29810c797a8058dcfbebe76fdda4eda00edc77bcfa154bb1dfbfdeb54886e5bca2500c6109cc1ab23b7f2a1d1ab395b4a03b6f32e2b9bc812d409043ba616842c6778e684fca5a61e1f0fbd13b7a4127d0a03ccda38501f18c0173ca6ff5b6993965857fa4e558decf9ec4eb029fedec35a9a0b4fcd9cab6ce1e4dd287e2ef45ff833c29f2d242071956735980382b8c5e4896a0990ea3ce3565e48bd298b94fa31a0ee138cf2a78eec2cb230e195a312b38615ca038b85a6dab7f3864ab27808bcea7afba47067f331df883f555c3b8a63f7f2708a00b4010de07890a392becd7b0a65ba025b68881338d90a8564948578ed3d603d1a0a3bd8522009985aefbda0c042cbd491ab95c64d06eec64c4f14b279d794c491ca02256aa32ff963eda317097c66085b4bbc7cbdb1b5bb3c20ffb315f8841e191f7a0defff5b730f636ddc7416f6be9eaf6093baafaf7e15ee3e1d8f286e18e813b44a0e6fcfc136e142784c9bd999f9a6bc7fb101fdb15570ab9efd843a718fcc14907a0b828dd6f14dd2342c36b9aceb643450772bea5ac0e287ace969d4825dddfa257a0b45e67d0c01bafbc49da1624308d8c120f3a730bc159177d58416f09bc1a775aa05f22ed8a7dea5bb08d7f1b21a1c4fa1877e49199bbf894dcdd78b5046699967b80", + "f0570d0215c72c80f88b99fbf3066173f08d70b1a38710d2c8f7da1b338c63af": "f8419e34c935999ef35f90638635ee1e8f18794e44ae035f5f8929d81a34d1fc30a1a0baadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabe", + "f10ef13814196b7c42116845ddecb8fa2fee1528fa20c0bc93a353f5b3912967": "f90211a0fa04d29b78fef22d5fd53c5a9c4ca3e650c6a756362dd18b48dd288193187706a0a02b5ca4d83881b35e7933ffad5a9159595399f2cc9c9da50448d603e5ee000da08fb9bf73dd8e084efc22c0b01e0587116ec5fc3b540ca48fc450b80513ca3e03a0c7d3b66013691d87e7d4130c16ccaa8857e69b8c80a0533857bfd674c44fa0aaa03fd2f67eaa309e041fd088d564283e22408a7842134597eb0da388920785ac86a0d991027b1baaff33ac1c6174871865672000765e4c62d445fa69f257ac79ea05a01a5d146c7b5b780d20e46bc5cf61a754abe46125550c5b01316e333cd84476bca06b2ec63e9156dc8fac4bf8d1ee6b7f7441c1b429ecda35655485c23f56cda40da06c6b0227675886c924ba75b8a5aea620e111a1c6524206f1356b8c96f3b9943ba0520035d0272b23419fb41de0f9be77f62f8a44483d192582b7b22ea6ec16ee2fa0a1000f88b4a667a6f276ca8a4b626b587d0506a424fb5378f7b45edd8769e907a03d76e2140cf49dfa89f0c2bf4628e7c8c5616891e2cbe915ed6e524ddae93213a052983f5967e6da52896ee86775986421891e78ab81ba803239291f64808b1cc9a06f2ae2b0b26237bc2482e73ed4beb2250e3d00d2685bbbc6795d333b2af3e93ba0825c1fd6628db8572adac976d5a460a42fa3d07cdfd2814e7a1ee1a99eb7aeaaa0185de8abf2d57dccc3663d088f441bdd1ac700b53a9c553401fe03e717a455d180", + "f118c6405ee680ac2c222ff2368b66c87460ddcc033897df266f95cad77b7997": "f90211a0998fd32083139f044c61aaf158be958d7cfd8493ecde344e30118ffe38862f55a0504651b3830cd8a8d0b94c022bbde54b5678e6e3313efc829690301481bcd35fa04474c2d3d86c2edbda92aae58878125686755a38e30361896a6b3dffcf54b7f8a0ce1a2bf6e4500c8b0829ade1f7e99fb8b6ad48c96a305f28a7ce570f88658a74a03b9bb5068e155d43d61f49cf73d0f2c3a48d96715eac3995566972741543fe7da0c46b51231790db88503a6fefe26ac33e62c6f117d942fb90600605fae4dbe098a02d07d0e31a9f3d48f7b04787294f906591c32bf4439a042d4d0fd40c4da87992a054df0667f08bacce450b0b53b8bee9636505023cb9a1714234f28efaa86dde23a060a9dfb7064ea5340ed5cc15b3e3f40a900c8353a49a2b6fd16e437d05e273e8a045c5650310b6a4e722f7e1c0175e73dbbb6128110cd04534f5a06fb9a62433e5a0ac0a6b5f0e9e90ea9366b40c99eafd71a896314e5844286866bbef9154a4f361a01fbd65b40e309118ba0598ef1fadded3fbd562a9cfb40f2894948b1e5a0a04a3a0dadf477d00c22884861a1e1194463efad63e08bab0eedc06f7e604bf2c8f6738a0b03ea0d36d753770f17a242f58dcdde49130dbfe3d5b40efaba819612a3ecedba05c3c5a620c939b9a7955a8108feb237ba7e753cf612b30b0c9c2924edcc3a43ba03482eb74340cca20d04109fe6344b6b9a7a3da5dfbf3b83cae305ee15947544880", + "f20203db7c0c28908c05792752426f72e219b8cda3ea5d63fe446f658cc9391b": "f90171a0ebaad4c587d32cd03a059a35124226c47d06ae27088fac68ca141cc6efeb4af7808080a0fb138f1a8912283842111e46828c9793eb75c4e8f69744cdece865269dc7350680a0f4538394fe09b83ef09caf47026f2cb9d68de78810e9c1fc7fa0bd14c91a828fa016a4e4db9c92746cd28aaa52ff26f0fb38bc1b6ea0f22c1239488442057d190ca0ed870120ddf293d88596d19d301217c67fb7d775b16fccd6dabf577c2865189aa05874746e23077144dce870d38383048c15defe6e2ef2b3378dec5d93b0b4dfe4a094b624f3f17bd055fd92c64df4c1a67e8c33e542e7a787cc47fedf685eb1c969a0058844e5d937fa570351a107484a39007b23c716d3d899f636dbf8d68613edc5a0af2420743f85122260f22dd2e188c218e32844176cc7c7934866a26b7b3ca04a80a063bd2f98ea7ea685ef473861d6bd51d615d103351845c7281a19ba36951aa38da0c8b402c941194a37a413bfc512b4e003f79a9fadeb5b02f049fec0edb1c1705b80", + "f294569b57edd4aa3d83bcc69bdd79db5706b11aebcfbeafb1e3df66bf46dcf4": "f90211a0d3ff089b0e10f7a78235f8282aa74396628f87db569a2701067c80cbbc530509a05b15be26263c6dd237e1e08366bd1b7e96f4922328ccee3c8977fe46b1b5a4e8a0fa38192b6f096428cb5d1a4932367cb57fd7149facafbaa8836ef369e8156177a0885c7d9922a823451bd00743e52fa04967ca16c49b7c15ba0a8e3067e22aca60a0aeb507d8d44ccaea6cd0a0257c7f0e99386032f4dfedde030c19b0cdc5bf2f4aa0d0de371dd1b1e6e3998fe0e10d70663a29a7476e14552b57fb86adc8abc35bf3a094e083746721816f5b28e80eb5f6d0038edd4e5d9e8af2a3e300299504d37e3da04471e04bb79b679ffbdea26deabbc3b0e3cd964b81c5d31173749d3f43f92f49a014878f3c01eafa72bc76aee1e56add1ab303877177a571f210c50c4e07445b80a0136cc810274b8260b29334bfa35dd204a920ef8c24414a6d4c31331c29997fa0a08f1dd67ac42b6dec334634bacabc4f402e24d03ddd5ce029b8654c7dc7f84651a07c3f9b17695cb1a630027e27d594d6def289ad7f61bb39e399d95fb1256f0bf6a0d194f061c614e187e926b10b7401c82aabae045cb0d57ddc4c0a3ee912277229a0848835fc3186c0281e6900f94ff3cc6532b85cc766acc3a45dd773dce044b4baa04e753d51a138e539d7273b5941437c65f400a37b70e6a6a53201655a54449860a0c28328d4e5a3ac84b724ff3698a137d146ed95a3d15c87839369ede67aca606780", + "f2cd55fede94befb7123a1627697080340171ed746283f9e602471a189d0b7ed": "f90211a032fcbf6c4e1b17354600caf62f9e7d1e231a55c8e1d8e4cfc298b17f07633a24a036a3492ec67091deac6aa78f8f333a980cd3fe47f991ad832d05c9a021db14efa0227651d627582de1e41356ec3f3b4916ea96b64a33648c51192b490dc7930d89a07b082c99648a62c23887956000339c5a443be80e0a6158b45c5d9b5de6e9feeaa0c70201eeeea190578fae4f7d9e6b224e654101ebb20cf21867564492129deb80a0d3ce8fe84d31470e358444d58f508b3c53c0e57782810fdaa72522222ec5dae5a00557d7c39a0b2c68233e5c3f1187016c3248aca4390daba9bbaea682ea8f0637a078e93e4015a4355e09ce4d0496a36d0656e5cc20390dc1170b7b35c1594bf5e2a08f7f62ee95216530263364614b74c2a1ffba4430aa4ce64ea1eebf2df64d1a8fa00df14e4825b9f64f7696cad46d8cb7fd066ac7e6aa2f6ba7407bfdb989f4eaf0a0ff393693b68318b23ed9e4aa4a7368596b58ba887f54a09813714db196a391dba0b825982b96bc6dac8667cbb618b67c44cffda19b07e6fe27e800f2f6e535499fa01543f6dc5d9c50a8a5ccf8f762ed9aff3ad112e60b785a1885a2026010a9fc06a03ddec9d9301bd6ab1ffadba5aba1148a52faef015faf91d90872ae403e5a65dea0483fdf8de0c666838b1342bbe5d2c3c2907255fdeedb15b94a092403d319af70a05540515cb4d16d57e64b7e1635c0e2711367c3599451da03e9951315b2855bbe80", + "f33530d450f5de1250ee98690733c01f23c79d693aa38cea35804252d754fe20": "f90111a037bdf170e872fcc8021680f15ba29821196827b4dc5399cacf38be7304e120d18080a0f7b57796c13867ff38665e7d4b287ec71c8289cd648ee0ad15f9bef7d015edb98080a09fabfc8fa48ff521e60d3b5c03f25bfe7a1ca2b89a62bd267cef8a9641e6d3b4a046d1322a23ed5109e92053273ca656d9eab1f5d8f6e1bc87eb1f421dba3f6bcda012878272e2d741d7266d3c226914d7fab192887288df93435d9b41015723a72c80a09e1f8a5c0fe7bc750327b4f12cd0134d149e8b8d7ba61e396b293e8f4490e180a0c4f3fdd4cfbec2cdcb14c71e608530d92e86fc6bf5fb4b3f1abcba76d59754fd8080a01445568a19b8311cd0cf054db908c97f9e36890ba4f36ba031e99872f8144b6f8080", + "f3b1230c6b239ae5fedfbf2e5cf3308ca97a9e7c59a952e091622f4c9f5ae62b": "f8b18080808080a06f1b2cf14b5c8f558225c7d73e4e4ee259f794199aeece1c022b5702333a667f80a05e56e3cb53a08466cf8ce98cbc9dba50b236732cf88e06dd71137536a9bb7a6480a0991797dda597c5d08cbd9e4931c42e090666410c3e0d1d10416efcbee682c682a0ef46e45ef8c5620f4351c3032d5cb7898778bb91b9e43cf065085e1ef5a51d2e8080a0c8f1f9ad4268a84ec0c5ab6f7fa6a06d1e6aad7f30866474a104c571a0ce5f5c808080", + "f424524e15bf7904d5b0ab04ece08073bbebb2fed66b58d6003d69b688ea9057": "f90211a0c63855522af2631c29ecf6153401a8b0bfc39bb6a86711c246999a06de7573b6a05f5dce43724a8db8c64c92acc9577c913a2a22a43a3b25f55f9d50a5d63b86c8a0b344eda5864a2627f92986b7d93c1b77830bc8fc7d1e6d560555645effc1f858a046c2d54a8d8a3da2146056b7d34ea3faa0e411d09ee4b3b78dbf6d8a23dc50a6a08a9b92991790073a3eca700a882e8cc47c38e9bb3efabfa4d110e33dc9dd5d47a0688f7331a005dfd72f6f1962eebd02167d1206550afddaf601c45fe993d19ed4a0567d2383b9bf835a9b36e001fde04ab59564f01e7a8b39b432dffc1abee1d834a06ee14cacf37f9397c5b4c2c4ee686cdc8cd4ac2ec65bd6cd62af787fea948c13a01fe2a8aa80ea9fb0e0b2e40463c791ec373417d9b64b83c9b7480911effa9f80a0a65a985812cee63114fd5972d56745a5fd10baffeed5b82198ff4d4823e7b801a0e20830069a41f91857663958a1302323ba5c07f817a1713229473d51095d22fea08d3c72f5b927eecafae2f50e516f8917a3ee3fb7f20ac6ae8e7b4cb68aca784ba06269ad1df6a564d20359a4c448c67745b2069148cd1fd685bf48df0f810fe1cca087df66c67ab026b2caa64b4caf44d2815673f0bcd1c7dcae0791b346af21fda7a07267889955578fdbf032b4d58c0b3153797181df9605d27d09cec4d678c2722da05d85246fdc22a0f50c39616de9aea6c57d509d497d7ba04cc7c53dcd246fbe6d80", + "f4dc42e7ded8ede43acd6e6be2bc324619b9cf93fc4432607ac2bd1855e70e75": "f8b180a04244dd9f96367c3df36102cadce07bf565fa939742928d8549ae16433551272e808080808080a02e7d7ba09b0af25e33416a4c36a16f228d24c78906574fdaa037c73baf77e7c08080a0f6da563ed87a91024274d8f8c189ba4621aaf696a3d1391886e65a1e074dfc8c80a032a23e6afb2aaa64e45a30a977ff90c744dbbf794012ad3a74b7812f72c3fc5c80a099617a8b124fb4b9f1ad1d9a476f4a1f5a7e8d4ff8fafbc9eb033ded4f35c5e780", + "f4ec1e678469e4424d59a5acd602d45f638d52aaffd744f011000105d4ac8762": "f90211a01ae78f9e84d417ff04024093cf2eaf68e7d29b6220fadb2e07962b92d30f5043a0f83e9f60ae1571b966ec9896d168af6db5e50e5de32e17976dcd49d3ef4ddc58a025431ec6e5fa481862368b3acb61d843040a06d36f1f214d07b1db11412d7adda0c9ae2745a2c72a7e0628f1a84605e24023f964bc354f36432344d2d6243c4fd8a0c54de6ec04a1fd400268eda0b8e99b9ed342802e70a4c316ec6183ab6472e8d8a03d69b5c506034c07d79a910dff5574d882ec9f5fce414521f4f0fe0d2b9fd6cfa0820c16b83efbd040b9209d695bfce7fba64f27da2830702d4dc480b2d0cb057ca0979b5fee50b78980f150ddaaeda2c6c7aab3f9ee95ec134cc911dd9273cf467ca04c16dbbe6e120ca71832b98b9c232858da8c5f25e4b5196c7f48db0ac9936b1aa0e294dd724b8d19156daccedc59bc39e0c8d854c41c315c59123a27eda709124ca00b030cfa5691ba68bee075634d5a8094c13a3b391a685ec432b2679cc01f2312a0d50053cc1e79218b7b3320ca13337067446d611c90f7ae5e2e5e328c0d9f0821a0ce073af42d991867e1130412d9d577dc30dc7337e0b1bbf8cdcf79ec34f2ebd9a0721fa772d1e234d9b750edd3bf2ce45dba762624169dc2db361e8952b9fecfc0a04d8ce7d5bf7ce9e8928016254ad4cba31aa26f5d5daa3661e13a661399caa421a08ce0975afd7f30541fdc25b20f09d00b902b316162d4457fae75a08733402edb80", + "f58dde8702ff92a6b5b794e7b21a801ccde3c6340ab800af6e649a989e1d8836": "f90211a09c877c8bd4e7d5d44a19b5b0deac6d7ec2d359c712121f911d6f87aff0c84981a06399e4cf5487b2c62460f3ab60081b9ad04fcd5bb00d18aaecb951041b7b7e4fa0ff1f178e228b642da8bf5cd10e0a088e4b988411830af742b8f5f677e0fc4a7fa083b1b61478e41c888ed108f1daeb9103303539e2d615d5de8521d0a16e85eb09a0023e05f135e193efdddbaee178977c260cefcfce0a49f16d669e09841e6abcafa0bf978483a13825b9c1aafd09adc8d59900a3f369884fad7e7add9cc9abc63f76a015c1b07ae34a89c7daf494bf971a2c1b703f7c0d917e7e06c7f8f560e85633e9a0ccdfa1a33242bba5e4667817745774f928aab98f5e81d01e81d2559f6c86d42ea0df897364c30a79cbc7cef281d6f162e8d82a15ca0e5722ac9c917cd8f44b6508a040eae84c36100956e12c7e7b3660c886d5fed95ffecce36abddc886f519d5ecda0a6b31a088fde8f24108538e982d30efcb835710a0c7927446fda0c73b3c356e0a0983ca8dec73bbd7abd714cc85dea36b027422cb079b0b7c17a451d292e437934a0a44f6df186a58727bb43c133a16f220190a79a777c6a3fdb1fb601b95318cb2ba021826ba88b2e7577ae2559f1279e90062eadef1028c43a87b68283ec72b6ab52a0255b3a2cb1bbc89af6fcd761340156e906c3b0d484a989942f2636e678856e51a0d3c046cfc9bf20a36d64ef0cc3328e53e1a235a491c5f1a8466ea6a7e557a2b780", + "f59c5c69539506bb7180bdcdfcef631b2aa2244bbe9e1eaef282e004a773d3e7": "f8d180808080808080a0d781015f668b0db517a83e15329aad2a658b0c9e7925afddba18aee8d854e29fa0e6895ed5b40be966c4eb2b44ad02d83e95daabe15049ecb4cd5ece3326e2e2a6a0ed9a49a723b2d3d8067a94aebb1ec876fbcccab0464b1c3e459677abae3763a4a0087bae9b406acdc96f279857b5c512933af2a0700bcfba754deaf4ead3ad99b780a0a91ff20634297f0bda786653895437785d7c75b5ee1a75c435d2d3cc1f0fa2268080a005e0e2a7988a763bd07f58a29bf59c85a98dd830d6dd2df444207612beb8d5d880", + "f61eee8f71a287c8561ebb99d2327ea955b2f081dc62a4be33c8675c8d5c3727": "f90211a005733e19ab2de0b62b29f29b79731374ee3dabbb17208d820261fcfadd79155da0f9844be68e0109514f428d1c8b85359a7c729f15991ea3696725412f053e2133a06857abf81c3994e4b85816c4c329b74089e9a11c24d92558bb7d42175ac3ed21a01f49db536be0f64a4cc7b25d838d64617d64b9be46ce036449fd03bf38f9d888a0051d755bb44c69e201b4e6e127a8334ac452b67e0b83cde54f96462a317c0af4a0524aeddae6fdb03d2de38466cd91ed60c9ca97d542e691309ec52a6ad807a2c5a08b0a4fb96bc270072147808b6a6176a6803742521936c21f25328c5075356a04a08cc6b4ae128971b7a6b4deacaa610397f97b40a82dcd94871374fb9b579c714ea0432d92d10e7ab1432414ed5592e91f4af06b5de7a5042ad269edfdaa1e910b70a081676d26ff6fb074ccc9ac6bc7a64d780d09837f9d812a766f58f4d3a6c4bf7fa021ed7d147a5ec4cf5a986a66f446b8593c924a3ba3715fe532f5b6c08950b86fa0e054b7c24244899d126ff967efe13d79557c919d3ddf184d4865ccae0879006ca0df097a159209efbed3344db003ec632b89b1209e46278b7993840e23106f2e31a0c76f34549cc95765b2f011b05e0978155d2d6d84d88a2c4006ed713521627084a00837352ca944c201c39059c79189623a7d3cae6534b648cd2e788c2cb117aa0ca0bee883c610a5aeee38e8fd2d65ed0077abc24c77d8b3cda49b1bc5455cc8fe8a80", + "f71305d6c27f3126aa03aed08cf4ad76173cd9339945642682df5944686b3f55": "f90211a0f0c14e20c39d0e5734cb5d3c0fe4a2ffaed086bbc3100bab3c938148b2adb9a4a0d514678a462daa77ed80bc698230b264215573fa7008a0e026f4c77083b846eba0cb6c43fde37b9930c17326fc6e86114f0053bce9291afe56ce105824745691afa0672b3941a701700f06def0d392eb7fedd49ed6a0839e57b0b1bfb510da8e500aa0453cca3ec06cde57ab5af155f45886f1c9b61fabbc16ef7b668420a2c154d39fa00b918189da8ca92002f01eb47f7037ae74dfa812b03953889d4637eca0fd118da0f6fd26adec32557a8d69eb520ab8791368cbf62e4d5ea92786805580508d3e76a086d533805a6dc4406140dfa8bc50638c4207242a6099559a1f11307ea69a767fa0f6ac8889af998ac16705b9b535e8baf3fde495faa92fbb7a8c0fb1b74cd8ece3a092f55bff6784abf10e45cf71fdc30edb1b6abada7cf9ecb0706ef8a1e97ea074a0e687e6e30b0384a60b6e08eb7afb4daab573ffb82a211de54182fe8a006e199aa0eaae4afc09649d5bcb815b81f8403b836c56e3e2f15823956d13ef5641ff97afa0547817b9b510d03ab3ea6b6d392235561844538983bc853a30d506e5d97ff431a0dd9e161b6ee5ac4a103baaf7fa62ba252138e7eb34ed793d0176bebddee5f54ba090e29537c6b72e979674411e8046de9de737344c5e1d37f82e591e119c8bfe55a044857555d501f4336ac4e46d4a79b14489e0f5d4db92c4028c56a5af6adb1b9680", + "f7196a25be0817a316b4df115f367a24903d0f137ac368486a68ee0517219724": "f90211a0cc2c5926940e1c259a24de6f96051971279ff7f6bfde76835e8b70371364c85ea0b1382de3c22addb8c29e4881ea51f0d0f55fab70182ca7278819333d3e14a54ba048ec4cb9918a99a0ab25134bf51481893c452fddfe3e9ac0a431d41eb2b114e9a03b9f979bce0c4e71b0ada08233305fb42b28cc6ea5b118a71dee59b7f4a41386a0eb2a5e36104b04868d1ad69971514966e032d55687b827af6808549cafc858aaa075e32706507a1e5fe0c69af0998a6c6af3651e519edd5887160734ade47750c4a052f67a05b24bf52d749d37e2ef41f32378f2dd4054d230064c58094a6c0a7026a0ba52d5a308ddc3f250196842a1ae830b652c09e49ba580f347f6cd24db548025a04d9ef8b5df6f04bc7c9c545a12fef81becd0ecc7ece0af3d799f5e7845cad573a078c13339cdd5d2ceaf8fdef1a6662df4e05a76341eb0274fbd7767f7b4d871baa0b687e7ae2ebae3d0f7e3aa31bf927f646a379b10a35edf6d58281d50ac6aa4fea034b24382ec00282a950dbdd248bc1dea9395eb3098f4816f36a8f649abf23a30a012a5e72350a9105737fc65a1da54c91583a1b71686fd0e24440e14c22b1d828ca0c1107cc3369108487e0295e22333807cf3a35dc596d46a4965711bfb5c564611a03536414ee0dfb7a9e5919812fe0c67b09a6531b9482252dd3f44e39c2630e792a01a9ad704f4ad0e9ae0a2020ae41a53bb6b88825c6bd7c79556f231642acb7b8680", + "f8b141298a73945d7dbaedd8a8a0ef422443d08d958409627b54161b1b277907": "f8b1a0a77545c50af6883966409114090fd0ea01da1a74baaecb60ee1ac64fec6633778080808080a0a83cb530413cecf306f0794d3536b8e61086a0f8842ea6a2e2371bdbc668030fa03c12e66ba2467e37a4348edd7e4f477993809310ec383e8194d628d733427868808080808080a081b636afc6614ba2dd78593ceb6704a03d945634a99f05c6606c7455fa3d4640a05d6e9d75e313723d9674b37a689434ebd2726ac32e78fe9a32ac7a32523f728f80", + "f9731da5be992bdce76170350f290d9d754195f3926fe8b4b65d2f9c051e9a1b": "f90111a01d714d0b1974ae27a2387f50aff075249fa9a018d33bfc5931ef246ee3734622a01947111c6e631eaa4d1776feae7e3fb964290f0b48bdf339f155a2530be2b27580a07a402c1a432509594c0175d298eab446247d4c3286d74efbe3fc64d1572d9abd8080a0b6b9907ef89dc9a7fbc10535fc1cccab7f1e8cacf8fa2f788e4ec101be3c3c26808080a073e83c417e6ee2ddcbbba356543f9dfe982fc2109a8c543ec0d91e31963a138da0e858e8dafa5aef306bd61569372950f71247d118146d3a9538830d5ea2cb3f2080a0d782ba1d8a122edfddcc7b410d72940921fc403e719db12cbaa2be1dc2a61c8280a080f5b6057bc43f0c174ea4f5fd0734a5355bbbbf1c283644a5a1be0d2a73089f80", + "fa7771f08b391fd03e69645940973cffd4f0f6a84fba13af48b4296098e9f088": "f8518080808080a0f628a54fdeab25a459830954436ac075408e63a934af90c267f5f116e669d22f808080a0595b243f37b06f53d918af6eb6972c289281603328389d06d7055a80668b756980808080808080", + "fb617882d02c69c87240a7bfc0b9edef6947702e866391241c057acc846ddf21": "f90211a033386b2b812bd72a1580bfbad0f8ea0bdac53f36bf3b8905765056b8bb314120a08d1f21f52e413ec55a5fa1bf90924b12f09399d418407006114ec6ad3efe707ca07b3c235af7ff9d547bf9faef9b64babe4faad497aca0c1236505b4c88d1a9553a070f1db9c1c22055a30198f7d0e66c7840bc3abf3a75f99c5d31d9ab80e3d11d3a0f51bffc369443b2bde8f04d220f5dea7b121ad0f6608cac2e0416c63973d7a3ca02323b5b2064814de80c3efcc3817c4f7f15a3271bfa55cafab3841fc6c556fe4a0688d5b11729a5ed1298d142b5423677a0da64515316135d155921f3de7054596a0d077465e74529e965f1823e487a96b0556001281b6c38e2dbd994d890433c156a038817e5e390810ae4a93f54a6271de2515f47b661a6ead91bd692d27021237c7a0be312c09ed679faf227eea833e1ba0f2e11278d00c9aa4b4fac99ef582f68d35a0cd0a4b9ebb8e68602212d720bcfca23278d2abc419290ccebd90273845de509ca009f99818622f2dc48357684066c75acfb77ca8b61bb91689f7cab49d0b7a7de0a076cf218022ad1af1ddeb84c2dfc6959e5edc5c32652f7baac09a3f6f6ecaef0fa0daaf9de60831301ca0f7ee9de594887ddafa1e7135a715ca26dff3748b05f5cba0c63dba659bb64880ab56b406aa8e9b063d7f9b72efd848760f19a5561815d1f7a039d1b3ab8272293b340d1bf11200610fca853b76504044e07dd2868557c4513580", + "fc6ac87d10550c904ab264584511899a12edd23e6801f80ff68b5ecd7f774de1": "f90211a0d83601909d5c211f5fc9f428b378a594e0454260ac516ac887c00a5584ebd189a01aaffc1fd7bea4e0d836cc790cb8cf32075cc55bba24eb48c33cf14e582a9c8ea08f4dd57cf3d66566e0f8db7f461da0339ba092934076bd444ea3c8d56848dc2ea058c7147ba81e83310642bf04961c3c86d78d8083b0b61b0de364ff7806bdbfe0a09bdee70790d798e6f07484bccdca7113635c1765665150271d97afb86b371f07a0fa5ace29d5ea4128f371a47ecfbcf7edcf51d442ffe35337213213e3076c3222a0fb0c42df3bca53295f6db02b7136ee4668e5385eda7bc2f74ad7f52c26009be2a011881dc233e9ab32122a8093ea06193bf95780fcb72d034db7da48d3d2a9753ca06d5b980de31253e4a2b75c241378a169a0558d9abfd4a86fcd78c7c9e3e47bd6a0b6fc66247f2e737a7b80c5ba7fe4d3b545fb9a941dc536f7a66d196f90ebdcb0a0398ff765b546f14291cdc97e6c62a12639b47588a37cdc024ffa5dfb80264014a0fa41513638ed92814369ace333d9726b6fb5504662dc800c1cd59f5b4146aa03a0b6fe1576c91375acefb6515583e60bbf5ddd29f8653c99cd62e00316ccfcfe7aa00423dfc1061903a7505e3c9bacc978d9632ec1b64fd353b28870a3056ec1c308a03b73260117e014baef0bfa9bcf0dd450817693091ed30650692fe90cd3a2c60fa0f025f2368de48972af7e44b8a96e6b27c489cceee09d0fa50899964c69d9f4ac80", + "fccac1597dbb9c323776eef714bdc7e013d0abe2d23de672ee20f1eda5846efb": "f90211a052abfaae552517380d3072cd87ae415f45305f4d42f8a4918aa91b76a496aca4a05121f84a798d2ed197bb05a3b8fb098d387126afdf85862c8f060a56543f4fa3a0a189485195cc3901705a5583bb81f10450872984bdedea50837fa4f1dc49fdf1a0488edbab0ff5603e9ced4e29282796a183d680ec678c54b96143aa0a1b368d91a07cd1dd2762f23aeff316dc47e1d92161e9f0950dda633fd4fc46740b8ea53f96a0f2b9f33e178be18097248ea1effa8b60cd79b7f7a38e1d50473b4ac955aa9638a06a57fdc70ade6076687d368526c2bebe6e574256bc2a0c3084e15de481d60076a0b8b1a4b3dacd20a77241dd79b619f63674d329587cfd7015dcf6a48ddb6e834ca07ac4c0580b08e57ecc42b204b170812e3a67a3849a4351b5a0abee34569deaf3a0240dec0ec07b508a6c800034535c21367268803d7e6951dfce14d070376d9927a03994dd7bd2ac403367c34366856f1a0aa6007ea0d031507bb4a025faa5c5bb46a00207127f88014b7dde80ed9035c4a68794e375c54871a6a4a0eaa6cca4add3dea02a462dcf2d0a1f7c76574d0a42186358f378e20d996d14ea8b0dbd73b6857260a0333b094107c4a07c7a35c4a5012359fb0546f02ab4d3d8966463165d01af560ba00c7617aa05ad6ea5dcbdbbd7d786e3b7a08d950a9dec9132849fe49c3d69226fa08510fff18d2037fee65aafcc130413d8df7b9bdbf75022645188bd2f78b079f380", + "fcef8054763af3dff0c963f8df3d06bdfe5730257341121ee24dbfe7b3f966b2": "f85180808080a080671aa571faf40034aabcb8f7f89a20f2ab48765a931493799d0dc91b1284c480808080808080808080a0c2e0b534b8a839c74108596405e4824f6038106b0d74046ea937baa0c69675ba80", + "fe46f5d6dddb35717669faf8218ec033270ad0f78d87f056b6e315f7b5903543": "f90211a0b95d3a56d750733889220e556adc1a3f3cf31fdda2c6c61af131d3b77cd6e79ea0b2a34def84a3b78192737ab9b728a0c810b510bbdc9177734b173c92393818b9a0194e3188ac44ad110de8ac12aee1d005147f4a84fdc76d48b1b094bd8e2e88a8a0384c297644b699393d3262a60809ee27bf887c1f3fa24c15d4354adb6501c203a0cd4456ac9ae6fd5582abea866ec1b5fcdaa1c1687c3f5477b70c5a71b887880da0c7224ae2a7c4cfe2562944fe6bdeedd6dd6464f2a4725b3fda4adcdbef9c962ba0665bb29b3f8f1fb9de073f632afd705b395471585ec1e305b472d1b48461a84fa0ef0984fc1c4fb87c7edf10ee5d6813fe62edd7d715fcd0133b38a55d9ec7dd76a0fef4c48c5f80bca8f752bee295f4b677579a040507a9b6e2d8174435fdb66903a088b89ad5006e9cc3e3053457b82dfff5354cc5d119159b6f1f51e02872182f6ba0a06b5a668a73a8c1f149d9200ad163e0c2d2ef7885f06798b69428c994b415baa0d4ca9b762c321ea63b26c7f3cdf9e7b3bba431fbfbb3b09f3ea3382b360277f0a08b043d2556a5d19965204fc16a02c48db58c44fce37ca29c5d941334a8db137fa06a871f79487d292c1ff7adc89716a9024fd96972f9a8e1d6e6a2b60eec3dcb92a0f8ff1b415a075489db1e6219d1c88b064b7540975e259c51c699134056844b1ca0ca5ef3c0b87e4a8d156692550fe42f9bd87882f48458ddcb72c759a14dd3bc4880", + "fe60a4bce77d097c8936a4456ba3c83144092df6c49d8f17e2e270f836eaa7eb": "f90211a09136a27f826707cd8a8217457db124c8a1c1c27a48bfec7aa936b170344288c8a06a79a9b529f01a0dea16a8c9837365b4bb69573e9c717ad9ca9a969cf0f46a2ea039c8109d4918c1a291042701adcfc5105a9d4534a93b3a168206403f4f515a50a0bf9a216203a885733eb20087abff828865b8dc65693178e84effa03a6019d572a0cd1caeca670db5c068a4b565d548e01663dff0af625ef8f8f1ad0362e4b7a89da017c5abeb1c81980f91df5518da56a24a3fef6004423123aaeb717449decfb4b2a08afc6793f1d7b4c5aabedead8546e16d29ba44ea8978e6669055c5a6d61bd2e3a098df008229cc8a9dbb13bae6f68c2227a0b163ebcf0adcf01b80c28c7ff3c430a004cb61cdf921438dd7d0a05dc2ab5279ec346963868d0d6dcc623789b291d0eaa029f7bedacef251443f02108e1bb1bb5667731b97ca78296e27cfd4ad7ab858b4a088e86d6f2d9667dfeff1673b8a3bcd86b5466ac8ccfdf49970f2d21b9e88f121a07a1868faef66b33b89ca753b4bd81588bc0f4b72106ae42b73db3283e49f4d59a07b0ee1d9b8e7bfaca8e8c799d8b6f2d7d188e6694031682970c50a08ce024d4fa079fab6b7e2ca671e8ec684a8f7dcb2a15673d9c924407f294798f2b103beb975a02a6ee492d26d305bf8dc73cb84243347351056f8c86125786fcf5c601310c15fa0c57b70e198a741b569ea565abe31feec70c5acbe5086c0b5660402f0f724bbdd80", + "ffdee49c5a0109eff7c53ce7c254ace02363105b9a17baaca3db3f8b0949f1e6": "f90211a0d2c711cedc21a246c5b122461ea78ac443e7cdc728549aaaab5c28f674218f49a0a6c4f8b091095fada898d490b719a884958842d32f60d44b34f1eabaa78cdb7ca0878a412e05c0df9d1af5170394a371d378f067cfe2b4cbf2c575da8364226408a05477345a83c623d093513140f14b3ad4363bbc40b96e354e275bc9b2bcc3e4f4a0b2233a87bbef49e1d2b54dad1d4d13f12e12f8660e84803431bf24c4cfea6ff1a01850573b263fc818381ac494fc820d74935350e54978f1db0d7fcdd335efa7f6a02d512c7518b2a42e45c998930db9e4ca1ad1ff4d054a056653caec7f589bec6ea0e9a39aa9e83ee614931590fea422de873517fb4e0a5bdf2dd744a371b79580b4a08673da46ecaa9f7aeb4b2bc140ef00bc8af5b26f5fd6681a1edc512972e85ea5a0c3a1b7540b82a4a3d7dc3b50f51d945906d64399647fad5b90f9e4a687069da3a0f3c8c89cb3ea01481f60b4e5c78e379d12f7f26edea3937d67fc6f5d1d13b117a0f79bc53c7e4e7cc4f1319f0b901d3bb87b3f5f8ba9fca4afef3d1c5371b8c2cca0839573792e04b48b69f00e79f5d563a09a1f60bfe42a256f2af9912b93ec0f01a0aed33cb7a585b9a671d894f575092c8ade7877678d4073b268f0a179ab7eb718a05c2d2aaf81986dcf7f7062c000e486ee9ef7732469755d71daea78901b489d76a062154a189e64b541c4349f49f8dbb243e052365cceec8126b23e03d7e87fb08380" + }, + "parentStateRoot": "0xcbccf9f17eecc98379ccf4a140a026a8c2585ca3b0901563e4f9a9f1b15907c7", + "transactionTraces": [ + { + "txn": "0xf904aa8248d080830ad21e946fda56c57b0acadb96ed5624ac500c0429d5942980b90444b374012b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de820fc6a05b6c9cef6e35d76a51713b0cc5180b19059c3a0182da05f7525eac10b327a572a044fd10b9a63cd495a798d2c3d4264ff49a8c7e954e3bca63b7a7b60fe91dd20a", + "delta": { + "0x0000000000000000000000000000000000000000": { + "address": "0x0000000000000000000000000000000000000000", + "balance": 1000000000000092200000000, + "read": true + }, + "0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429": { + "address": "0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429", + "balance": 0, + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000048d0", + "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bba39d": "0x0000000000000000000000000000000000000000000000000000000000000801", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1b": "0x000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1c": "0xbaaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ff", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1d": "0xcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabe", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1e": "0xdeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeed", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1f": "0xdecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabe", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e20": "0xfeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabe", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e21": "0xb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0ba", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e22": "0xb0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e23": "0xdead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00d", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e24": "0xdeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeed", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e25": "0xfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e26": "0x1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00d", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e27": "0xbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00d", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e28": "0xcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeef", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e29": "0xdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8ed", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2a": "0xd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2b": "0xf00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b5", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2c": "0x0b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabe", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2d": "0xc00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaad", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2e": "0xdeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10cc", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2f": "0xdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1dead", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e30": "0xfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00d", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e31": "0xabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafe", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e32": "0xcafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5e", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e33": "0xdabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddead", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e34": "0xdeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e35": "0xfacefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e36": "0x00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaad", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e37": "0xbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabe", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e38": "0xcafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeaf", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e39": "0xdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbad", + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e3a": "0xdefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de" + }, + "storage_read": { + "0x0000000000000000000000000000000000000000000000000000000000000002": {}, + "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bba39d": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1b": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1c": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1d": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1e": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e1f": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e20": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e21": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e22": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e23": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e24": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e25": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e26": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e27": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e28": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e29": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2a": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2b": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2c": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2d": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2e": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e2f": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e30": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e31": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e32": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e33": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e34": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e35": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e36": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e37": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e38": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e39": {}, + "0x4a27a46697da58dfe447cc2de67cbc23d5e879f136b82f2bd9034c3a30247e3a": {} + }, + "code_read": "YIBgQFI0gBVhABBXYACA/VtQYAQ2EGEEVFdgADVg4ByAY4CUf4ARYQJBV4Bjv1KcoRFhATtXgGPdm+9gEWEAw1eAY/J5yoERYQCHV4Bj8nnKgRRhEWFXgGP00fxhFGERkVeAY/WPw2oUYRHBV4Bj9rC79xRhEfFXgGP953IcFGESIVdhBFRWW4Bj3ZvvYBRhEHFXgGPel6NjFGEQoVeAY+n5s/IUYRDRV4Bj6lFB5hRhEQFXgGPt8APPFGERMVdhBFRWW4Bjzjz07xFhAQpXgGPOPPTvFGEPgVeAY9EXMgsUYQ+xV4Bj1R57WxRhD+FXgGPVP/P9FGEQEVeAY9k81VgUYRBBV2EEVFZbgGO/UpyhFGEOwVeAY8Ngq6YUYQ7xV4BjxCDrYRRhDyFXgGPEvWXVFGEPUVdhBFRWW4BjoYaDyxFhAclXgGOzdAErEWEBjVeAY7N0ASsUYQ3RV4Bjs9hH8hRhDgFXgGO3uGIHFGEOMVeAY7gcFIQUYQ5hV4Bjvch1/BRhDpFXYQRUVluAY6GGg8sUYQzzV4BjonG3IRRhDSNXgGOmChCHFGENQVeAY6ZFycIUYQ1xV4BjrK699hRhDaFXYQRUVluAY5YuTcIRYQIQV4Bjli5NwhRhDANXgGOYRW8+FGEMM1eAY5orfIEUYQxjV4BjnM58+RRhDJNXgGOgQK7GFGEMw1dhBFRWW4BjgJR/gBRhC0NXgGOIDv85FGELc1eAY5GKX80UYQujV4BjkeeydxRhC9NXYQRUVluAYzQw7AYRYQNSV4BjYOE83hFhAtpXgGNvCZyNEWECnleAY28JnI0UYQpTV4BjcdkdKBRhCoNXgGN7bgsOFGEKs1eAY3wZHSAUYQrjV4BjfejG+BRhCxNXYQRUVluAY2DhPN4UYQl1V4BjYT0KghRhCaVXgGNjE41PFGEJ1VeAY2Wbu08UYQoFV4Bjbn8f5xRhCiNXYQRUVluAY0D+JmIRYQMhV4BjQP4mYhRhCIVXgGNEzzvHFGEItVeAY0phrx8UYQjlV4BjTSx0sxRhCRVXgGNVkMLZFGEJRVdhBFRWW4BjNDDsBhRhB9dXgGM3EwPAFGEIB1eAYzpBHxIUYQglV4BjOkJd/BRhCFVXYQRUVluAYxgJO0YRYQPgV4BjIZzd6xFhA6RXgGMhnN3rFGEG51eAYyKU/H8UYQcXV4BjKHHvhRRhB0dXgGMrIe9EFGEHd1eAYy0055gUYQenV2EEVFZbgGMYCTtGFGEF91eAYxm2IdYUYQYnV4BjGroH6hRhBldXgGMd4vNDFGEGh1eAYyAHMy4UYQa3V2EEVFZbgGMLqKc7EWEEJ1eAYwuopzsUYQUZV4BjEoemjBRhBUlXgGMTXVL3FGEFZ1eAYxWBzxkUYQWXV4BjFlghUBRhBcdXYQRUVluAYwNK73EUYQRZV4BjBQCC+BRhBIlXgGMIe06EFGEEuVeAYws7mWoUYQTpV1tgAID9W2EEc2AEgDYDgQGQYQRukZBhJhFWW2ESUVZbYEBRYQSAkZBhJk1WW2BAUYCRA5DzW2EEo2AEgDYDgQGQYQSekZBhJhFWW2ESjFZbYEBRYQSwkZBhJk1WW2BAUYCRA5DzW2EE02AEgDYDgQGQYQTOkZBhJhFWW2ESx1ZbYEBRYQTgkZBhJk1WW2BAUYCRA5DzW2EFA2AEgDYDgQGQYQT+kZBhJ65WW2ETAVZbYEBRYQUQkZBhKHZWW2BAUYCRA5DzW2EFM2AEgDYDgQGQYQUukZBhJhFWW2ETKFZbYEBRYQVAkZBhJk1WW2BAUYCRA5DzW2EFUWETZFZbYEBRYQVekZBhJk1WW2BAUYCRA5DzW2EFgWAEgDYDgQGQYQV8kZBhJhFWW2ETbVZbYEBRYQWOkZBhJk1WW2BAUYCRA5DzW2EFsWAEgDYDgQGQYQWskZBhJhFWW2ETqVZbYEBRYQW+kZBhJk1WW2BAUYCRA5DzW2EF4WAEgDYDgQGQYQXckZBhJhFWW2ET5FZbYEBRYQXukZBhJk1WW2BAUYCRA5DzW2EGEWAEgDYDgQGQYQYMkZBhJhFWW2EUP1ZbYEBRYQYekZBhJk1WW2BAUYCRA5DzW2EGQWAEgDYDgQGQYQY8kZBhJhFWW2EUfVZbYEBRYQZOkZBhJk1WW2BAUYCRA5DzW2EGcWAEgDYDgQGQYQZskZBhJhFWW2EVDFZbYEBRYQZ+kZBhJk1WW2BAUYCRA5DzW2EGoWAEgDYDgQGQYQackZBhJhFWW2EVUlZbYEBRYQaukZBhJk1WW2BAUYCRA5DzW2EG0WAEgDYDgQGQYQbMkZBhJhFWW2EVkFZbYEBRYQbekZBhJk1WW2BAUYCRA5DzW2EHAWAEgDYDgQGQYQb8kZBhJhFWW2EVzFZbYEBRYQcOkZBhJk1WW2BAUYCRA5DzW2EHMWAEgDYDgQGQYQcskZBhJhFWW2EWB1ZbYEBRYQc+kZBhJk1WW2BAUYCRA5DzW2EHYWAEgDYDgQGQYQdckZBhJhFWW2EWRlZbYEBRYQdukZBhJk1WW2BAUYCRA5DzW2EHkWAEgDYDgQGQYQeMkZBhJhFWW2EWgVZbYEBRYQeekZBhJk1WW2BAUYCRA5DzW2EHwWAEgDYDgQGQYQe8kZBhJhFWW2EWvFZbYEBRYQfOkZBhJk1WW2BAUYCRA5DzW2EH8WAEgDYDgQGQYQfskZBhJhFWW2EW91ZbYEBRYQf+kZBhKHZWW2BAUYCRA5DzW2EID2EXo1ZbYEBRYQgckZBhJk1WW2BAUYCRA5DzW2EIP2AEgDYDgQGQYQg6kZBhJhFWW2EXwlZbYEBRYQhMkZBhJk1WW2BAUYCRA5DzW2EIb2AEgDYDgQGQYQhqkZBhJhFWW2EX/lZbYEBRYQh8kZBhJk1WW2BAUYCRA5DzW2EIn2AEgDYDgQGQYQiakZBhJhFWW2EYOlZbYEBRYQiskZBhJk1WW2BAUYCRA5DzW2EIz2AEgDYDgQGQYQjKkZBhJhFWW2EYeVZbYEBRYQjckZBhJk1WW2BAUYCRA5DzW2EI/2AEgDYDgQGQYQj6kZBhJhFWW2EYtFZbYEBRYQkMkZBhJk1WW2BAUYCRA5DzW2EJL2AEgDYDgQGQYQkqkZBhJhFWW2EY8lZbYEBRYQk8kZBhJk1WW2BAUYCRA5DzW2EJX2AEgDYDgQGQYQlakZBhJhFWW2EZLVZbYEBRYQlskZBhJk1WW2BAUYCRA5DzW2EJj2AEgDYDgQGQYQmKkZBhJhFWW2EZclZbYEBRYQmckZBhJk1WW2BAUYCRA5DzW2EJv2AEgDYDgQGQYQm6kZBhJ65WW2EZrlZbYEBRYQnMkZBhKHZWW2BAUYCRA5DzW2EJ72AEgDYDgQGQYQnqkZBhJ65WW2EZ4FZbYEBRYQn8kZBhKLFWW2BAUYCRA5DzW2EKDWEaDFZbYEBRYQoakZBhJk1WW2BAUYCRA5DzW2EKPWAEgDYDgQGQYQo4kZBhJhFWW2EaSFZbYEBRYQpKkZBhJk1WW2BAUYCRA5DzW2EKbWAEgDYDgQGQYQpokZBhJhFWW2EahlZbYEBRYQp6kZBhJk1WW2BAUYCRA5DzW2EKnWAEgDYDgQGQYQqYkZBhJhFWW2EawVZbYEBRYQqqkZBhJk1WW2BAUYCRA5DzW2EKzWAEgDYDgQGQYQrIkZBhJhFWW2Ea/1ZbYEBRYQrakZBhJk1WW2BAUYCRA5DzW2EK/WAEgDYDgQGQYQr4kZBhJhFWW2EbO1ZbYEBRYQsKkZBhJk1WW2BAUYCRA5DzW2ELLWAEgDYDgQGQYQsokZBhJhFWW2EbdlZbYEBRYQs6kZBhJk1WW2BAUYCRA5DzW2ELXWAEgDYDgQGQYQtYkZBhJhFWW2EbslZbYEBRYQtqkZBhJk1WW2BAUYCRA5DzW2ELjWAEgDYDgQGQYQuIkZBhJhFWW2EcD1ZbYEBRYQuakZBhJk1WW2BAUYCRA5DzW2ELvWAEgDYDgQGQYQu4kZBhJhFWW2EcTlZbYEBRYQvKkZBhJk1WW2BAUYCRA5DzW2EL7WAEgDYDgQGQYQvokZBhJhFWW2EciVZbYEBRYQv6kZBhJk1WW2BAUYCRA5DzW2EMHWAEgDYDgQGQYQwYkZBhJ65WW2Ec1VZbYEBRYQwqkZBhKHZWW2BAUYCRA5DzW2EMTWAEgDYDgQGQYQxIkZBhJhFWW2EdQ1ZbYEBRYQxakZBhJk1WW2BAUYCRA5DzW2EMfWAEgDYDgQGQYQx4kZBhJhFWW2Edg1ZbYEBRYQyKkZBhJk1WW2BAUYCRA5DzW2EMrWAEgDYDgQGQYQyokZBhJ65WW2EdvlZbYEBRYQy6kZBhKHZWW2BAUYCRA5DzW2EM3WAEgDYDgQGQYQzYkZBhJ65WW2Ed71ZbYEBRYQzqkZBhKHZWW2BAUYCRA5DzW2ENDWAEgDYDgQGQYQ0IkZBhJ65WW2EeFlZbYEBRYQ0akZBhKQ1WW2BAUYCRA5DzW2ENK2EemFZbYEBRYQ04kZBhJk1WW2BAUYCRA5DzW2ENW2AEgDYDgQGQYQ1WkZBhJhFWW2Ee41ZbYEBRYQ1okZBhJk1WW2BAUYCRA5DzW2ENi2AEgDYDgQGQYQ2GkZBhJhFWW2EfHlZbYEBRYQ2YkZBhJk1WW2BAUYCRA5DzW2ENu2AEgDYDgQGQYQ22kZBhJhFWW2EfWlZbYEBRYQ3IkZBhJk1WW2BAUYCRA5DzW2EN62AEgDYDgQGQYQ3mkZBhKYhWW2EfllZbYEBRYQ34kZBhJk1WW2BAUYCRA5DzW2EOG2AEgDYDgQGQYQ4WkZBhJhFWW2Ef5FZbYEBRYQ4okZBhJk1WW2BAUYCRA5DzW2EOS2AEgDYDgQGQYQ5GkZBhJhFWW2EgH1ZbYEBRYQ5YkZBhJk1WW2BAUYCRA5DzW2EOe2AEgDYDgQGQYQ52kZBhJhFWW2EgWlZbYEBRYQ6IkZBhJk1WW2BAUYCRA5DzW2EOq2AEgDYDgQGQYQ6mkZBhJhFWW2EglVZbYEBRYQ64kZBhJk1WW2BAUYCRA5DzW2EO22AEgDYDgQGQYQ7WkZBhJhFWW2Eg0FZbYEBRYQ7okZBhJk1WW2BAUYCRA5DzW2EPC2AEgDYDgQGQYQ8GkZBhJhFWW2EhFFZbYEBRYQ8YkZBhJk1WW2BAUYCRA5DzW2EPO2AEgDYDgQGQYQ82kZBhJhFWW2EhUFZbYEBRYQ9IkZBhJk1WW2BAUYCRA5DzW2EPa2AEgDYDgQGQYQ9mkZBhJhFWW2Ehi1ZbYEBRYQ94kZBhJk1WW2BAUYCRA5DzW2EPm2AEgDYDgQGQYQ+WkZBhJhFWW2EhyVZbYEBRYQ+okZBhJk1WW2BAUYCRA5DzW2EPy2AEgDYDgQGQYQ/GkZBhJhFWW2EiBlZbYEBRYQ/YkZBhJk1WW2BAUYCRA5DzW2EP+2AEgDYDgQGQYQ/2kZBhJhFWW2EiQFZbYEBRYRAIkZBhJk1WW2BAUYCRA5DzW2EQK2AEgDYDgQGQYRAmkZBhJhFWW2EifFZbYEBRYRA4kZBhJk1WW2BAUYCRA5DzW2EQW2AEgDYDgQGQYRBWkZBhJhFWW2EiuFZbYEBRYRBokZBhJk1WW2BAUYCRA5DzW2EQi2AEgDYDgQGQYRCGkZBhJhFWW2EjE1ZbYEBRYRCYkZBhJk1WW2BAUYCRA5DzW2EQu2AEgDYDgQGQYRC2kZBhJhFWW2EjVVZbYEBRYRDIkZBhJk1WW2BAUYCRA5DzW2EQ62AEgDYDgQGQYRDmkZBhJhFWW2EjkVZbYEBRYRD4kZBhJk1WW2BAUYCRA5DzW2ERG2AEgDYDgQGQYREWkZBhJhFWW2EjzlZbYEBRYREokZBhJk1WW2BAUYCRA5DzW2ERS2AEgDYDgQGQYRFGkZBhJ65WW2EkEFZbYEBRYRFYkZBhKHZWW2BAUYCRA5DzW2ERe2AEgDYDgQGQYRF2kZBhJhFWW2Ekf1ZbYEBRYRGIkZBhJk1WW2BAUYCRA5DzW2ERq2AEgDYDgQGQYRGmkZBhJhFWW2Eku1ZbYEBRYRG4kZBhJk1WW2BAUYCRA5DzW2ER22AEgDYDgQGQYRHWkZBhJhFWW2Ek+VZbYEBRYRHokZBhJk1WW2BAUYCRA5DzW2ESC2AEgDYDgQGQYRIGkZBhJ65WW2ElOFZbYEBRYRIYkZBhKhBWW2BAUYCRA5DzW2ESO2AEgDYDgQGQYRI2kZBhJhFWW2ElalZbYEBRYRJIkZBhJk1WW2BAUYCRA5DzW2AAYRJbYRejVltQYABl3q2+7wA2kFBgAIBbhIEQFWESgVc2kVBgAYEBkFBhEmtWW1BQgJFQUJGQUFZbYABhEpZhF6NWW1BgAGXerb7vADKQUGAAgFuEgRAVYRK8VzKRUGABgQGQUGESplZbUFCAkVBQkZBQVltgAGES0WEXo1ZbUGAAZd6tvu8AUpBQYABbg4EQFWES91eBYABSYAGBAZBQYRLgVltQgJFQUJGQUFZbYGBgAGAIkFBgQIKEUWAghgFgAIVa8YBhEyFXYACA/VtQUJGQUFZbYABhEzJhF6NWW1BgAGXerb7vAAGQUGAAW4OBEBVhE1pXYACCAZFQYAGBAZBQYRNBVltQgJFQUJGQUFZbYACAVJBQkFZbYABhE3dhF6NWW1BgAGXerb7vABeQUGAAW4OBEBVhE59XYACCF5FQYAGBAZBQYROGVltQgJFQUJGQUFZbYABhE7NhF6NWW1BgAGXerb7vADSQUGAAgFuEgRAVYRPZVzSRUGABgQGQUGETw1ZbUFCAkVBQkZBQVltgAGET7mEXo1ZbUGAAZd6tvu8ABpBQYABbg4EQFWEUNVd///////////////////////////////////////////+CBpFQYAGBAZBQYRP9VltQgJFQUJGQUFZbYABhFElhF6NWW1BgAGXerb7vABOQUGAAgFuEgRAVYRRyV2ABgxORUGABgQGQUGEUWVZbUFCAkVBQkZBQVltgAGEUh2EXo1ZbUGAAZd6tvu8AIJBQf/////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYABSYACAW4SBEBVhFNVXYARgACCRUGABgQGQUGEUu1ZbUH8pBFpZIAfQwkbvAsIiNXDalSLQzw9zKCx5obyPC7LCOIEUYRUCV2AAkVBbUICRUFCRkFBWW2AAYRUWYRejVltQYABl3q2+7wCkkFCAYBBSYABbg4EQFWEVSFdgBGADYAKDYAZgEKRgAYEBkFBhFSlWW1CAkVBQkZBQVltgAGEVXGEXo1ZbUGAAZd6tvu8AGpBQYACAW4SBEBVhFYVXgmAAGpFQYAGBAZBQYRVsVltQUICRUFCRkFBWW2AAYRWaYRejVltQYABl3q2+7wAbkFBgAFuDgRAVYRXCV4FgABuRUGABgQGQUGEVqVZbUICRUFCRkFBWW2AAYRXWYRejVltQYABl3q2+7wBCkFBgAIBbhIEQFWEV/FdCkVBgAYEBkFBhFeZWW1BQgJFQUJGQUFZbYABhFhFhF6NWW1BgAGXerb7vADGQUGAAMGAAW4WBEBVhFjpXgTGSUGABgQGQUGEWI1ZbUFBQgJFQUJGQUFZbYABhFlBhF6NWW1BgAGXerb7vAEiQUGAAgFuEgRAVYRZ2V0iRUGABgQGQUGEWYFZbUFCAkVBQkZBQVltgAGEWi2EXo1ZbUGAAZd6tvu8APZBQYACAW4SBEBVhFrFXPZFQYAGBAZBQYRabVltQUICRUFCRkFBWW2AAYRbGYRejVltQYABl3q2+7wBDkFBgAIBbhIEQFWEW7FdDkVBgAYEBkFBhFtZWW1BQgJFQUJGQUFZbYAKBgVSBEGEXB1dgAID9W5BgAFJgIGAAIAFgAJFQkFCAVGEXIpBhKlpWW4BgHwFgIICRBAJgIAFgQFGQgQFgQFKAkpGQgYFSYCABgoBUYRdOkGEqWlZbgBVhF5tXgGAfEGEXcFdhAQCAg1QEAoNSkWAgAZFhF5tWW4IBkZBgAFJgIGAAIJBbgVSBUpBgAQGQYCABgIMRYRd+V4KQA2AfFoIBkVtQUFBQUIFWW2AAYAFgAFRhF7SRkGEqulZbYACBkFVQYABUkFCQVltgAGEXzGEXo1ZbUGAAZd6tvu8ABJBQYABbg4EQFWEX9FdgAYIEkVBgAYEBkFBhF9tWW1CAkVBQkZBQVltgAGEYCGEXo1ZbUGAAZd6tvu8AN5BQYABbg4EQFWEYMFdgIGAAgDdgAYEBkFBhGBdWW1CAkVBQkZBQVltgAGEYRGEXo1ZbUGAAZd6tvu8AoJBQgGAQUmAAW4OBEBVhGG9XYAZgEKBgAYEBkFBhGFdWW1CAkVBQkZBQVltgAGEYg2EXo1ZbUGAAZd6tvu8AM5BQYACAW4SBEBVhGKlXM5FQYAGBAZBQYRiTVltQUICRUFCRkFBWW2AAYRi+YRejVltQYABl3q2+7wBTkFBgAFuDgRAVYRjoV2Perb7vYABSYAGBAZBQYRjNVltQgJFQUJGQUFZbYABhGPxhF6NWW1BgAGXerb7vADqQUGAAgFuEgRAVYRkiVzqRUGABgQGQUGEZDFZbUFCAkVBQkZBQVltgAGEZN2EXo1ZbUGAAZd6tvu8AUZBQYACBYABSYABbhIEQFWEZZFdgAFGRUGABgQGQUGEZTFZbUICRUFCAkVBQkZBQVltgAGEZfGEXo1ZbUGAAZd6tvu8AHZBQYABbg4EQFWEZpFeBYAAdkVBgAYEBkFBhGYtWW1CAkVBQkZBQVltgYGAAYAWQUGAggwGDUWBAUWAggYOFYACIWvGAYRnTV2AAgP1bgZVQUFBQUFCRkFBWW2AAgGACkFBgIIMBg1GDYCCBg4VgAIha8YBhGgJXYACA/VtQUFBQUJGQUFZbYABhGhZhF6NWW1BbYQPoWhEVYRpAV2ABgGAAgoJUYRo0kZBhKrpWW5JQUIGQVVBhGhhWW2ABVJBQkFZbYABhGlJhF6NWW1BgAGXerb7vABCQUGAAgFuEgRAVYRp7V4JgARCRUGABgQGQUGEaYlZbUFCAkVBQkZBQVltgAGEakGEXo1ZbUGAAZd6tvu8ARJBQYACAW4SBEBVhGrZXRJFQYAGBAZBQYRqgVltQUICRUFCRkFBWW2AAYRrLYRejVltQYABl3q2+7wARkFBgAIBbhIEQFWEa9FdgAYMRkVBgAYEBkFBhGttWW1BQgJFQUJGQUFZbYABhGwlhF6NWW1BgAGXerb7vAD6QUGAAW4OBEBVhGzFXYCBgAIA+YAGBAZBQYRsYVltQgJFQUJGQUFZbYABhG0VhF6NWW1BgAGXerb7vAEWQUGAAgFuEgRAVYRtrV0WRUGABgQGQUGEbVVZbUFCAkVBQkZBQVltgAGEbgGEXo1ZbUGAAZd6tvu8AApBQYABbg4EQFWEbqFdgAYICkVBgAYEBkFBhG49WW1CAkVBQkZBQVltgAGEbvGEXo1ZbUGAAZd6tvu8ACJBQYABbg4EQFWEcBVd///////////////////////////////////////////9gAIMIkVBgAYEBkFBhG8tWW1CAkVBQkZBQVltgAGEcGWEXo1ZbUGAAZd6tvu8AVJBQgGAAVWAAW4OBEBVhHERXYABUkVBgAYEBkFBhHCxWW1CAkVBQkZBQVltgAGEcWGEXo1ZbUGAAZd6tvu8AWpBQYACAW4SBEBVhHH5XWpFQYAGBAZBQYRxoVltQUICRUFCRkFBWW2AAYRyTYRejVltQYABl3q2+7wAZkFBgAFuDgRAVYRy5V4EZkVBgAYEBkFBhHKJWW1Bl3q2+7wAZgRRhHMxXgBmQUFuAkVBQkZBQVltgYICCURRhHRpXYEBRfwjDeaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgVJgBAFhHRGQYStLVltgQFGAkQOQ/VtgAGAHkFBgIIMBg1FgQISChGAAh1rxgGEdOldgAID9W1BQUFCRkFBWW2AAYR1NYRejVltQYABl3q2+7wChkFCAYBBSYABbg4EQFWEdeVeAYAZgEKFgAYEBkFBhHWBWW1CAkVBQkZBQVltgAGEdjWEXo1ZbUGAAZd6tvu8AFpBQYABbg4EQFWEdtFeBghaRUGABgQGQUGEdnFZbUICRUFCRkFBWW2BgYABgBJBQYCCDAYNRYEBRgYGDhWAAiFrxgGEd4ldgAID9W4GVUFBQUFBQkZBQVltgYGAAYAiQUGBAgoRRYCCGAWAAhVrxgGEeD1dgAID9W1BQkZBQVltgAGCAglEUYR5cV2BAUX8Iw3mgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFSYAQBYR5TkGErt1ZbYEBRgJEDkP1bYABgAZBQYCCDAWAggQFRYB8aYCCCAVJgIGBAUWCAg2AAhlrxgGEeildgAID9W2BAUVGTUFBQUJGQUFZbYABhHqJhF6NWW1BbYQPoWhEVYR7bV2ABgGAAgoJUYR7AkZBhKrpWW5JQUIGQVVBDYAFUYR7VkZBhLAZWW1BhHqRWW2ABVJBQkFZbYABhHu1hF6NWW1BgAGXerb7vAEaQUGAAgFuEgRAVYR8TV0aRUGABgQGQUGEe/VZbUFCAkVBQkZBQVltgAGEfKGEXo1ZbUGAAZd6tvu8ABZBQYABbg4EQFWEfUFdgAYIFkVBgAYEBkFBhHzdWW1CAkVBQkZBQVltgAGEfZGEXo1ZbUGAAZd6tvu8AOZBQYABbg4EQFWEfjFdgIGAAgDlgAYEBkFBhH3NWW1CAkVBQkZBQVltgAGACg4OQkYBgAYFUAYCCVYCRUFBgAZADkGAAUmAgYAAgAWAAkJGSkJGSkJGSkJGSUJGCYR/VkpGQYS3uVltQYAKAVJBQkFCSkVBQVltgAGEf7mEXo1ZbUGAAZd6tvu8AWZBQYACAW4SBEBVhIBRXWZFQYAGBAZBQYR/+VltQUICRUFCRkFBWW2AAYSApYRejVltQYABl3q2+7wA4kFBgAIBbhIEQFWEgT1c4kVBgAYEBkFBhIDlWW1BQgJFQUJGQUFZbYABhIGRhF6NWW1BgAGXerb7vAEGQUGAAgFuEgRAVYSCKV0GRUGABgQGQUGEgdFZbUFCAkVBQkZBQVltgAGEgn2EXo1ZbUGAAZd6tvu8AMJBQYACAW4SBEBVhIMVXMJFQYAGBAZBQYSCvVltQUICRUFCRkFBWW2AAYSDaYRejVltQYABl3q2+7wCjkFCAYBBSYABbg4EQFWEhCldgA2ACgmAGYBCjYAGBAZBQYSDtVltQgJFQUJGQUFZbYABhIR5hF6NWW1BgAGXerb7vAAuQUGAAW4OBEBVhIUZXgWAgC5FQYAGBAZBQYSEtVltQgJFQUJGQUFZbYABhIVphF6NWW1BgAGXerb7vAEeQUGAAgFuEgRAVYSGAV0eRUGABgQGQUGEhalZbUFCAkVBQkZBQVltgAGEhlWEXo1ZbUGAAZd6tvu8AHJBQYACAW4SBEBVhIb5XgmAAHJJQYAGBAZBQYSGlVltQUICRUFCRkFBWW2AAYSHTYRejVltQYABl3q2+7wA1kFBgAIBbhIEQFWEh+1dgADWRUGABgQGQUGEh41ZbUFCAkVBQkZBQVltgAGEiEGEXo1ZbUGAAZd6tvu8AVZBQYABbg4EQFWEiNleBYABVYAGBAZBQYSIfVltQgJFQUJGQUFZbYABhIkphF6NWW1BgAGXerb7vABiQUGAAW4OBEBVhInJXYACCGJFQYAGBAZBQYSJZVltQgJFQUJGQUFZbYABhIoZhF6NWW1BgAGXerb7vAAOQUGAAW4OBEBVhIq5XYACCA5FQYAGBAZBQYSKVVltQgJFQUJGQUFZbYABhIsJhF6NWW1BgAGXerb7vAAeQUGAAW4OBEBVhIwlXf///////////////////////////////////////////ggeRUGABgQGQUGEi0VZbUICRUFCRkFBWW2AAYSMdYRejVltQYABl3q2+7wCikFCAYBBSYABbg4EQFWEjS1dgAoFgBmAQomABgQGQUGEjMFZbUICRUFCRkFBWW2AAYSNfYRejVltQYABl3q2+7wAKkFBgAFuDgRAVYSOHV2ABggqRUGABgQGQUGEjblZbUICRUFCRkFBWW2AAYSObYRejVltQYABl3q2+7wAUkFBgAIBbhIEQFWEjw1eCgxSRUGABgQGQUGEjq1ZbUFCAkVBQkZBQVltgAGEj2GEXo1ZbUGAAZd6tvu8AQJBQYABgAUMDYABbhYEQFWEkBFeBQJJQYAGBAZBQYSPtVltQUFCAkVBQkZBQVltgYGCAglEUYSRWV2BAUX8Iw3mgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFSYAQBYSRNkGErS1ZbYEBRgJEDkP1bYABgBpBQYCCDAYNRYECEgoRgAIda8YBhJHZXYACA/VtQUFBQkZBQVltgAGEkiWEXo1ZbUGAAZd6tvu8AFZBQYACAW4SBEBVhJLBXghWRUGABgQGQUGEkmVZbUFCAkVBQkZBQVltgAGEkxWEXo1ZbUGAAZd6tvu8AEpBQYACAW4SBEBVhJO5XgmABEpFQYAGBAZBQYSTVVltQUICRUFCRkFBWW2AAYSUDYRejVltQYABl3q2+7wA7kFBgADBgAFuFgRAVYSUsV4E7klBgAYEBkFBhJRVWW1BQUICRUFCRkFBWW2AAgGADkFBgIIMBg1FgQFFgFIGDhWAAiFrxgGElXFdgAID9W4FRlVBQUFBQUJGQUFZbYABhJXRhF6NWW1BgAGXerb7vAAmQUGAAW4OBEBVhJb1Xf///////////////////////////////////////////YAGDCZFQYAGBAZBQYSWDVltQgJFQUJGQUFZbYABgQFGQUJBWW2AAgP1bYACA/VtgAIGQUJGQUFZbYSXugWEl21ZbgRRhJflXYACA/VtQVltgAIE1kFBhJguBYSXlVluSkVBQVltgAGAggoQDEhVhJidXYSYmYSXRVltbYABhJjWEgoUBYSX8VluRUFCSkVBQVlthJkeBYSXbVluCUlBQVltgAGAgggGQUGEmYmAAgwGEYSY+VluSkVBQVltgAID9W2AAgP1bYABgHxlgH4MBFpBQkZBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgQWAEUmAkYAD9W2Emu4JhJnJWW4EBgYEQZ///////////ghEXFWEm2ldhJtlhJoNWW1uAYEBSUFBQVltgAGEm7WElx1ZbkFBhJvmCgmEmslZbkZBQVltgAGf//////////4IRFWEnGVdhJxhhJoNWW1thJyKCYSZyVluQUGAggQGQUJGQUFZbgoGDN2AAg4MBUlBQUFZbYABhJ1FhJ0yEYSb+VlthJuNWW5BQgoFSYCCBAYSEhAERFWEnbVdhJ2xhJm1WW1thJ3iEgoVhJy9WW1CTklBQUFZbYACCYB+DARJhJ5VXYSeUYSZoVltbgTVhJ6WEgmAghgFhJz5WW5FQUJKRUFBWW2AAYCCChAMSFWEnxFdhJ8NhJdFWW1tgAIIBNWf//////////4ERFWEn4ldhJ+FhJdZWW1thJ+6EgoUBYSeAVluRUFCSkVBQVltgAIFRkFCRkFBWW2AAgoJSYCCCAZBQkpFQUFZbYABbg4EQFWEoMVeAggFRgYQBUmAggQGQUGEoFlZbYACEhAFSUFBQUFZbYABhKEiCYSf3VlthKFKBhWEoAlZbk1BhKGKBhWAghgFhKBNWW2Eoa4FhJnJWW4QBkVBQkpFQUFZbYABgIIIBkFCBgQNgAIMBUmEokIGEYSg9VluQUJKRUFBWW2AAgZBQkZBQVlthKKuBYSiYVluCUlBQVltgAGAgggGQUGEoxmAAgwGEYSiiVluSkVBQVltgAHP//////////////////////////4IWkFCRkFBWW2AAYSj3gmEozFZbkFCRkFBWW2EpB4FhKOxWW4JSUFBWW2AAYCCCAZBQYSkiYACDAYRhKP5WW5KRUFBWW2AAgP1bYACA/VtgAICDYB+EARJhKUhXYSlHYSZoVltbgjWQUGf//////////4ERFWEpZVdhKWRhKShWW1tgIIMBkVCDYAGCAoMBERVhKYFXYSmAYSktVltbklCSkFBWW2AAgGAgg4UDEhVhKZ9XYSmeYSXRVltbYACDATVn//////////+BERVhKb1XYSm8YSXWVltbYSnJhYKGAWEpMlZbklCSUFCSUJKQUFZbYAB///////////////////////////8AAAAAAAAAAAAAAACCFpBQkZBQVlthKgqBYSnVVluCUlBQVltgAGAgggGQUGEqJWAAgwGEYSoBVluSkVBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgImAEUmAkYAD9W2AAYAKCBJBQYAGCFoBhKnJXYH+CFpFQW2AgghCBA2EqhVdhKoRhKitWW1tQkZBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgEWAEUmAkYAD9W2AAYSrFgmEl21ZbkVBhKtCDYSXbVluSUIKCAZBQgIIRFWEq6FdhKudhKotWW1uSkVBQVltgAIKCUmAgggGQUJKRUFBWW39JbnZhbGlkIGlucHV0IGxlbmd0aAAAAAAAAAAAAAAAAGAAggFSUFZbYABhKzVgFINhKu5WW5FQYStAgmEq/1ZbYCCCAZBQkZBQVltgAGAgggGQUIGBA2AAgwFSYStkgWErKFZbkFCRkFBWW39JbnZhbGlkIGlucHV0IGRhdGEgbGVuZ3RoLgAAAAAAAGAAggFSUFZbYABhK6FgGoNhKu5WW5FQYSusgmEra1ZbYCCCAZBQkZBQVltgAGAgggGQUIGBA2AAgwFSYSvQgWErlFZbkFCRkFBWW39OSHtxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAUmASYARSYCRgAP1bYABhLBGCYSXbVluRUGEsHINhJdtWW5JQgmEsLFdhLCthK9dWW1uCggaQUJKRUFBWW2AAgpBQkpFQUFZbYACBkFCBYABSYCBgACCQUJGQUFZbYABgIGAfgwEEkFCRkFBWW2AAgoIbkFCSkVBQVltgAGAIgwJhLKR///////////////////////////////////////////+CYSxnVlthLK6Gg2EsZ1ZblVCAGYQWk1CAhhaEF5JQUFCTklBQUFZbYACBkFCRkFBWW2AAYSzrYSzmYSzhhGEl21ZbYSzGVlthJdtWW5BQkZBQVltgAIGQUJGQUFZbYS0Fg2Es0FZbYS0ZYS0RgmEs8lZbhIRUYSx0VluCVVBQUFBWW2AAkFZbYS0uYS0hVlthLTmBhIRhLPxWW1BQUFZbW4GBEBVhLV1XYS1SYACCYS0mVltgAYEBkFBhLT9WW1BQVltgH4IRFWEtoldhLXOBYSxCVlthLXyEYSxXVluBAWAghRAVYS2LV4GQUFthLZ9hLZeFYSxXVluDAYJhLT5WW1BQW1BQUFZbYACCghyQUJKRUFBWW2AAYS3FYAAZhGAIAmEtp1ZbGYCDFpFQUJKRUFBWW2AAYS3eg4NhLbRWW5FQgmACAoIXkFCSkVBQVlthLfiDg2EsN1ZbZ///////////gREVYS4RV2EuEGEmg1ZbW2EuG4JUYSpaVlthLiaCgoVhLWFWW2AAYB+DEWABgRRhLlVXYACEFWEuQ1eChwE1kFBbYS5NhYJhLdJWW4ZVUGEutVZbYB8ZhBZhLmOGYSxCVltgAFuCgRAVYS6LV4SJATWCVWABggGRUGAghQGUUGAggQGQUGEuZlZbhoMQFWEuqFeEiQE1YS6kYB+JFoJhLbRWW4NVUFtgAWACiAIBiFVQUFBbUFBQUFBQUFb+omRpcGZzWCISIDEkITSIwvH8pZaHh/DD6W+6hGkSmoB5jhHudSkDtL/cZHNvbGNDAAgTADM=", + "touched": true, + "read": true + }, + "0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6": { + "address": "0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6", + "balance": 1e+27, + "nonce": 18641, + "read": true + }, + "0xe4f2Dea6e117FCBa4eC4FDd1D090245110763Dd9": { + "address": "0xe4f2Dea6e117FCBa4eC4FDd1D090245110763Dd9", + "balance": 1e+24, + "read": true + } + } + }, + { + "txn": "0xf904aa8248d180830ad21e946fda56c57b0acadb96ed5624ac500c0429d5942980b90444b374012b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de820fc5a0679af9c447e4b6bb929d52a99b2ce1fda507ecf8ee1008fb28b67b4a28195168a029c35951e3e7e4916b0481cb6e2a726876ece8fbb052058086228d78117a6efc", + "delta": { + "0x0000000000000000000000000000000000000000": { + "address": "0x0000000000000000000000000000000000000000", + "balance": 1000000000000092200000000, + "read": true + }, + "0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429": { + "address": "0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429", + "balance": 0, + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000048d1", + "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bba39e": "0x0000000000000000000000000000000000000000000000000000000000000801", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64b": "0x000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64c": "0xbaaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ff", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64d": "0xcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabe", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64e": "0xdeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeed", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64f": "0xdecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabe", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a650": "0xfeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabe", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a651": "0xb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0ba", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a652": "0xb0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a653": "0xdead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00d", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a654": "0xdeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeed", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a655": "0xfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a656": "0x1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00d", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a657": "0xbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00d", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a658": "0xcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeef", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a659": "0xdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8ed", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65a": "0xd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65b": "0xf00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b5", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65c": "0x0b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabe", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65d": "0xc00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaad", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65e": "0xdeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10cc", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65f": "0xdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1dead", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a660": "0xfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00d", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a661": "0xabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafe", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a662": "0xcafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5e", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a663": "0xdabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddead", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a664": "0xdeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a665": "0xfacefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a666": "0x00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaad", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a667": "0xbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabe", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a668": "0xcafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeaf", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a669": "0xdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbad", + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a66a": "0xdefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de" + }, + "storage_read": { + "0x0000000000000000000000000000000000000000000000000000000000000002": {}, + "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bba39e": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64b": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64c": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64d": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64e": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a64f": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a650": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a651": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a652": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a653": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a654": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a655": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a656": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a657": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a658": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a659": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65a": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65b": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65c": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65d": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65e": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a65f": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a660": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a661": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a662": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a663": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a664": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a665": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a666": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a667": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a668": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a669": {}, + "0xea7df19a8b53839bd1a13079a19ef91aa56e3bdb5a6bf15ff454e5037bc1a66a": {} + }, + "code_read": "YIBgQFI0gBVhABBXYACA/VtQYAQ2EGEEVFdgADVg4ByAY4CUf4ARYQJBV4Bjv1KcoRFhATtXgGPdm+9gEWEAw1eAY/J5yoERYQCHV4Bj8nnKgRRhEWFXgGP00fxhFGERkVeAY/WPw2oUYRHBV4Bj9rC79xRhEfFXgGP953IcFGESIVdhBFRWW4Bj3ZvvYBRhEHFXgGPel6NjFGEQoVeAY+n5s/IUYRDRV4Bj6lFB5hRhEQFXgGPt8APPFGERMVdhBFRWW4Bjzjz07xFhAQpXgGPOPPTvFGEPgVeAY9EXMgsUYQ+xV4Bj1R57WxRhD+FXgGPVP/P9FGEQEVeAY9k81VgUYRBBV2EEVFZbgGO/UpyhFGEOwVeAY8Ngq6YUYQ7xV4BjxCDrYRRhDyFXgGPEvWXVFGEPUVdhBFRWW4BjoYaDyxFhAclXgGOzdAErEWEBjVeAY7N0ASsUYQ3RV4Bjs9hH8hRhDgFXgGO3uGIHFGEOMVeAY7gcFIQUYQ5hV4Bjvch1/BRhDpFXYQRUVluAY6GGg8sUYQzzV4BjonG3IRRhDSNXgGOmChCHFGENQVeAY6ZFycIUYQ1xV4BjrK699hRhDaFXYQRUVluAY5YuTcIRYQIQV4Bjli5NwhRhDANXgGOYRW8+FGEMM1eAY5orfIEUYQxjV4BjnM58+RRhDJNXgGOgQK7GFGEMw1dhBFRWW4BjgJR/gBRhC0NXgGOIDv85FGELc1eAY5GKX80UYQujV4BjkeeydxRhC9NXYQRUVluAYzQw7AYRYQNSV4BjYOE83hFhAtpXgGNvCZyNEWECnleAY28JnI0UYQpTV4BjcdkdKBRhCoNXgGN7bgsOFGEKs1eAY3wZHSAUYQrjV4BjfejG+BRhCxNXYQRUVluAY2DhPN4UYQl1V4BjYT0KghRhCaVXgGNjE41PFGEJ1VeAY2Wbu08UYQoFV4Bjbn8f5xRhCiNXYQRUVluAY0D+JmIRYQMhV4BjQP4mYhRhCIVXgGNEzzvHFGEItVeAY0phrx8UYQjlV4BjTSx0sxRhCRVXgGNVkMLZFGEJRVdhBFRWW4BjNDDsBhRhB9dXgGM3EwPAFGEIB1eAYzpBHxIUYQglV4BjOkJd/BRhCFVXYQRUVluAYxgJO0YRYQPgV4BjIZzd6xFhA6RXgGMhnN3rFGEG51eAYyKU/H8UYQcXV4BjKHHvhRRhB0dXgGMrIe9EFGEHd1eAYy0055gUYQenV2EEVFZbgGMYCTtGFGEF91eAYxm2IdYUYQYnV4BjGroH6hRhBldXgGMd4vNDFGEGh1eAYyAHMy4UYQa3V2EEVFZbgGMLqKc7EWEEJ1eAYwuopzsUYQUZV4BjEoemjBRhBUlXgGMTXVL3FGEFZ1eAYxWBzxkUYQWXV4BjFlghUBRhBcdXYQRUVluAYwNK73EUYQRZV4BjBQCC+BRhBIlXgGMIe06EFGEEuVeAYws7mWoUYQTpV1tgAID9W2EEc2AEgDYDgQGQYQRukZBhJhFWW2ESUVZbYEBRYQSAkZBhJk1WW2BAUYCRA5DzW2EEo2AEgDYDgQGQYQSekZBhJhFWW2ESjFZbYEBRYQSwkZBhJk1WW2BAUYCRA5DzW2EE02AEgDYDgQGQYQTOkZBhJhFWW2ESx1ZbYEBRYQTgkZBhJk1WW2BAUYCRA5DzW2EFA2AEgDYDgQGQYQT+kZBhJ65WW2ETAVZbYEBRYQUQkZBhKHZWW2BAUYCRA5DzW2EFM2AEgDYDgQGQYQUukZBhJhFWW2ETKFZbYEBRYQVAkZBhJk1WW2BAUYCRA5DzW2EFUWETZFZbYEBRYQVekZBhJk1WW2BAUYCRA5DzW2EFgWAEgDYDgQGQYQV8kZBhJhFWW2ETbVZbYEBRYQWOkZBhJk1WW2BAUYCRA5DzW2EFsWAEgDYDgQGQYQWskZBhJhFWW2ETqVZbYEBRYQW+kZBhJk1WW2BAUYCRA5DzW2EF4WAEgDYDgQGQYQXckZBhJhFWW2ET5FZbYEBRYQXukZBhJk1WW2BAUYCRA5DzW2EGEWAEgDYDgQGQYQYMkZBhJhFWW2EUP1ZbYEBRYQYekZBhJk1WW2BAUYCRA5DzW2EGQWAEgDYDgQGQYQY8kZBhJhFWW2EUfVZbYEBRYQZOkZBhJk1WW2BAUYCRA5DzW2EGcWAEgDYDgQGQYQZskZBhJhFWW2EVDFZbYEBRYQZ+kZBhJk1WW2BAUYCRA5DzW2EGoWAEgDYDgQGQYQackZBhJhFWW2EVUlZbYEBRYQaukZBhJk1WW2BAUYCRA5DzW2EG0WAEgDYDgQGQYQbMkZBhJhFWW2EVkFZbYEBRYQbekZBhJk1WW2BAUYCRA5DzW2EHAWAEgDYDgQGQYQb8kZBhJhFWW2EVzFZbYEBRYQcOkZBhJk1WW2BAUYCRA5DzW2EHMWAEgDYDgQGQYQcskZBhJhFWW2EWB1ZbYEBRYQc+kZBhJk1WW2BAUYCRA5DzW2EHYWAEgDYDgQGQYQdckZBhJhFWW2EWRlZbYEBRYQdukZBhJk1WW2BAUYCRA5DzW2EHkWAEgDYDgQGQYQeMkZBhJhFWW2EWgVZbYEBRYQeekZBhJk1WW2BAUYCRA5DzW2EHwWAEgDYDgQGQYQe8kZBhJhFWW2EWvFZbYEBRYQfOkZBhJk1WW2BAUYCRA5DzW2EH8WAEgDYDgQGQYQfskZBhJhFWW2EW91ZbYEBRYQf+kZBhKHZWW2BAUYCRA5DzW2EID2EXo1ZbYEBRYQgckZBhJk1WW2BAUYCRA5DzW2EIP2AEgDYDgQGQYQg6kZBhJhFWW2EXwlZbYEBRYQhMkZBhJk1WW2BAUYCRA5DzW2EIb2AEgDYDgQGQYQhqkZBhJhFWW2EX/lZbYEBRYQh8kZBhJk1WW2BAUYCRA5DzW2EIn2AEgDYDgQGQYQiakZBhJhFWW2EYOlZbYEBRYQiskZBhJk1WW2BAUYCRA5DzW2EIz2AEgDYDgQGQYQjKkZBhJhFWW2EYeVZbYEBRYQjckZBhJk1WW2BAUYCRA5DzW2EI/2AEgDYDgQGQYQj6kZBhJhFWW2EYtFZbYEBRYQkMkZBhJk1WW2BAUYCRA5DzW2EJL2AEgDYDgQGQYQkqkZBhJhFWW2EY8lZbYEBRYQk8kZBhJk1WW2BAUYCRA5DzW2EJX2AEgDYDgQGQYQlakZBhJhFWW2EZLVZbYEBRYQlskZBhJk1WW2BAUYCRA5DzW2EJj2AEgDYDgQGQYQmKkZBhJhFWW2EZclZbYEBRYQmckZBhJk1WW2BAUYCRA5DzW2EJv2AEgDYDgQGQYQm6kZBhJ65WW2EZrlZbYEBRYQnMkZBhKHZWW2BAUYCRA5DzW2EJ72AEgDYDgQGQYQnqkZBhJ65WW2EZ4FZbYEBRYQn8kZBhKLFWW2BAUYCRA5DzW2EKDWEaDFZbYEBRYQoakZBhJk1WW2BAUYCRA5DzW2EKPWAEgDYDgQGQYQo4kZBhJhFWW2EaSFZbYEBRYQpKkZBhJk1WW2BAUYCRA5DzW2EKbWAEgDYDgQGQYQpokZBhJhFWW2EahlZbYEBRYQp6kZBhJk1WW2BAUYCRA5DzW2EKnWAEgDYDgQGQYQqYkZBhJhFWW2EawVZbYEBRYQqqkZBhJk1WW2BAUYCRA5DzW2EKzWAEgDYDgQGQYQrIkZBhJhFWW2Ea/1ZbYEBRYQrakZBhJk1WW2BAUYCRA5DzW2EK/WAEgDYDgQGQYQr4kZBhJhFWW2EbO1ZbYEBRYQsKkZBhJk1WW2BAUYCRA5DzW2ELLWAEgDYDgQGQYQsokZBhJhFWW2EbdlZbYEBRYQs6kZBhJk1WW2BAUYCRA5DzW2ELXWAEgDYDgQGQYQtYkZBhJhFWW2EbslZbYEBRYQtqkZBhJk1WW2BAUYCRA5DzW2ELjWAEgDYDgQGQYQuIkZBhJhFWW2EcD1ZbYEBRYQuakZBhJk1WW2BAUYCRA5DzW2ELvWAEgDYDgQGQYQu4kZBhJhFWW2EcTlZbYEBRYQvKkZBhJk1WW2BAUYCRA5DzW2EL7WAEgDYDgQGQYQvokZBhJhFWW2EciVZbYEBRYQv6kZBhJk1WW2BAUYCRA5DzW2EMHWAEgDYDgQGQYQwYkZBhJ65WW2Ec1VZbYEBRYQwqkZBhKHZWW2BAUYCRA5DzW2EMTWAEgDYDgQGQYQxIkZBhJhFWW2EdQ1ZbYEBRYQxakZBhJk1WW2BAUYCRA5DzW2EMfWAEgDYDgQGQYQx4kZBhJhFWW2Edg1ZbYEBRYQyKkZBhJk1WW2BAUYCRA5DzW2EMrWAEgDYDgQGQYQyokZBhJ65WW2EdvlZbYEBRYQy6kZBhKHZWW2BAUYCRA5DzW2EM3WAEgDYDgQGQYQzYkZBhJ65WW2Ed71ZbYEBRYQzqkZBhKHZWW2BAUYCRA5DzW2ENDWAEgDYDgQGQYQ0IkZBhJ65WW2EeFlZbYEBRYQ0akZBhKQ1WW2BAUYCRA5DzW2ENK2EemFZbYEBRYQ04kZBhJk1WW2BAUYCRA5DzW2ENW2AEgDYDgQGQYQ1WkZBhJhFWW2Ee41ZbYEBRYQ1okZBhJk1WW2BAUYCRA5DzW2ENi2AEgDYDgQGQYQ2GkZBhJhFWW2EfHlZbYEBRYQ2YkZBhJk1WW2BAUYCRA5DzW2ENu2AEgDYDgQGQYQ22kZBhJhFWW2EfWlZbYEBRYQ3IkZBhJk1WW2BAUYCRA5DzW2EN62AEgDYDgQGQYQ3mkZBhKYhWW2EfllZbYEBRYQ34kZBhJk1WW2BAUYCRA5DzW2EOG2AEgDYDgQGQYQ4WkZBhJhFWW2Ef5FZbYEBRYQ4okZBhJk1WW2BAUYCRA5DzW2EOS2AEgDYDgQGQYQ5GkZBhJhFWW2EgH1ZbYEBRYQ5YkZBhJk1WW2BAUYCRA5DzW2EOe2AEgDYDgQGQYQ52kZBhJhFWW2EgWlZbYEBRYQ6IkZBhJk1WW2BAUYCRA5DzW2EOq2AEgDYDgQGQYQ6mkZBhJhFWW2EglVZbYEBRYQ64kZBhJk1WW2BAUYCRA5DzW2EO22AEgDYDgQGQYQ7WkZBhJhFWW2Eg0FZbYEBRYQ7okZBhJk1WW2BAUYCRA5DzW2EPC2AEgDYDgQGQYQ8GkZBhJhFWW2EhFFZbYEBRYQ8YkZBhJk1WW2BAUYCRA5DzW2EPO2AEgDYDgQGQYQ82kZBhJhFWW2EhUFZbYEBRYQ9IkZBhJk1WW2BAUYCRA5DzW2EPa2AEgDYDgQGQYQ9mkZBhJhFWW2Ehi1ZbYEBRYQ94kZBhJk1WW2BAUYCRA5DzW2EPm2AEgDYDgQGQYQ+WkZBhJhFWW2EhyVZbYEBRYQ+okZBhJk1WW2BAUYCRA5DzW2EPy2AEgDYDgQGQYQ/GkZBhJhFWW2EiBlZbYEBRYQ/YkZBhJk1WW2BAUYCRA5DzW2EP+2AEgDYDgQGQYQ/2kZBhJhFWW2EiQFZbYEBRYRAIkZBhJk1WW2BAUYCRA5DzW2EQK2AEgDYDgQGQYRAmkZBhJhFWW2EifFZbYEBRYRA4kZBhJk1WW2BAUYCRA5DzW2EQW2AEgDYDgQGQYRBWkZBhJhFWW2EiuFZbYEBRYRBokZBhJk1WW2BAUYCRA5DzW2EQi2AEgDYDgQGQYRCGkZBhJhFWW2EjE1ZbYEBRYRCYkZBhJk1WW2BAUYCRA5DzW2EQu2AEgDYDgQGQYRC2kZBhJhFWW2EjVVZbYEBRYRDIkZBhJk1WW2BAUYCRA5DzW2EQ62AEgDYDgQGQYRDmkZBhJhFWW2EjkVZbYEBRYRD4kZBhJk1WW2BAUYCRA5DzW2ERG2AEgDYDgQGQYREWkZBhJhFWW2EjzlZbYEBRYREokZBhJk1WW2BAUYCRA5DzW2ERS2AEgDYDgQGQYRFGkZBhJ65WW2EkEFZbYEBRYRFYkZBhKHZWW2BAUYCRA5DzW2ERe2AEgDYDgQGQYRF2kZBhJhFWW2Ekf1ZbYEBRYRGIkZBhJk1WW2BAUYCRA5DzW2ERq2AEgDYDgQGQYRGmkZBhJhFWW2Eku1ZbYEBRYRG4kZBhJk1WW2BAUYCRA5DzW2ER22AEgDYDgQGQYRHWkZBhJhFWW2Ek+VZbYEBRYRHokZBhJk1WW2BAUYCRA5DzW2ESC2AEgDYDgQGQYRIGkZBhJ65WW2ElOFZbYEBRYRIYkZBhKhBWW2BAUYCRA5DzW2ESO2AEgDYDgQGQYRI2kZBhJhFWW2ElalZbYEBRYRJIkZBhJk1WW2BAUYCRA5DzW2AAYRJbYRejVltQYABl3q2+7wA2kFBgAIBbhIEQFWESgVc2kVBgAYEBkFBhEmtWW1BQgJFQUJGQUFZbYABhEpZhF6NWW1BgAGXerb7vADKQUGAAgFuEgRAVYRK8VzKRUGABgQGQUGESplZbUFCAkVBQkZBQVltgAGES0WEXo1ZbUGAAZd6tvu8AUpBQYABbg4EQFWES91eBYABSYAGBAZBQYRLgVltQgJFQUJGQUFZbYGBgAGAIkFBgQIKEUWAghgFgAIVa8YBhEyFXYACA/VtQUJGQUFZbYABhEzJhF6NWW1BgAGXerb7vAAGQUGAAW4OBEBVhE1pXYACCAZFQYAGBAZBQYRNBVltQgJFQUJGQUFZbYACAVJBQkFZbYABhE3dhF6NWW1BgAGXerb7vABeQUGAAW4OBEBVhE59XYACCF5FQYAGBAZBQYROGVltQgJFQUJGQUFZbYABhE7NhF6NWW1BgAGXerb7vADSQUGAAgFuEgRAVYRPZVzSRUGABgQGQUGETw1ZbUFCAkVBQkZBQVltgAGET7mEXo1ZbUGAAZd6tvu8ABpBQYABbg4EQFWEUNVd///////////////////////////////////////////+CBpFQYAGBAZBQYRP9VltQgJFQUJGQUFZbYABhFElhF6NWW1BgAGXerb7vABOQUGAAgFuEgRAVYRRyV2ABgxORUGABgQGQUGEUWVZbUFCAkVBQkZBQVltgAGEUh2EXo1ZbUGAAZd6tvu8AIJBQf/////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYABSYACAW4SBEBVhFNVXYARgACCRUGABgQGQUGEUu1ZbUH8pBFpZIAfQwkbvAsIiNXDalSLQzw9zKCx5obyPC7LCOIEUYRUCV2AAkVBbUICRUFCRkFBWW2AAYRUWYRejVltQYABl3q2+7wCkkFCAYBBSYABbg4EQFWEVSFdgBGADYAKDYAZgEKRgAYEBkFBhFSlWW1CAkVBQkZBQVltgAGEVXGEXo1ZbUGAAZd6tvu8AGpBQYACAW4SBEBVhFYVXgmAAGpFQYAGBAZBQYRVsVltQUICRUFCRkFBWW2AAYRWaYRejVltQYABl3q2+7wAbkFBgAFuDgRAVYRXCV4FgABuRUGABgQGQUGEVqVZbUICRUFCRkFBWW2AAYRXWYRejVltQYABl3q2+7wBCkFBgAIBbhIEQFWEV/FdCkVBgAYEBkFBhFeZWW1BQgJFQUJGQUFZbYABhFhFhF6NWW1BgAGXerb7vADGQUGAAMGAAW4WBEBVhFjpXgTGSUGABgQGQUGEWI1ZbUFBQgJFQUJGQUFZbYABhFlBhF6NWW1BgAGXerb7vAEiQUGAAgFuEgRAVYRZ2V0iRUGABgQGQUGEWYFZbUFCAkVBQkZBQVltgAGEWi2EXo1ZbUGAAZd6tvu8APZBQYACAW4SBEBVhFrFXPZFQYAGBAZBQYRabVltQUICRUFCRkFBWW2AAYRbGYRejVltQYABl3q2+7wBDkFBgAIBbhIEQFWEW7FdDkVBgAYEBkFBhFtZWW1BQgJFQUJGQUFZbYAKBgVSBEGEXB1dgAID9W5BgAFJgIGAAIAFgAJFQkFCAVGEXIpBhKlpWW4BgHwFgIICRBAJgIAFgQFGQgQFgQFKAkpGQgYFSYCABgoBUYRdOkGEqWlZbgBVhF5tXgGAfEGEXcFdhAQCAg1QEAoNSkWAgAZFhF5tWW4IBkZBgAFJgIGAAIJBbgVSBUpBgAQGQYCABgIMRYRd+V4KQA2AfFoIBkVtQUFBQUIFWW2AAYAFgAFRhF7SRkGEqulZbYACBkFVQYABUkFCQVltgAGEXzGEXo1ZbUGAAZd6tvu8ABJBQYABbg4EQFWEX9FdgAYIEkVBgAYEBkFBhF9tWW1CAkVBQkZBQVltgAGEYCGEXo1ZbUGAAZd6tvu8AN5BQYABbg4EQFWEYMFdgIGAAgDdgAYEBkFBhGBdWW1CAkVBQkZBQVltgAGEYRGEXo1ZbUGAAZd6tvu8AoJBQgGAQUmAAW4OBEBVhGG9XYAZgEKBgAYEBkFBhGFdWW1CAkVBQkZBQVltgAGEYg2EXo1ZbUGAAZd6tvu8AM5BQYACAW4SBEBVhGKlXM5FQYAGBAZBQYRiTVltQUICRUFCRkFBWW2AAYRi+YRejVltQYABl3q2+7wBTkFBgAFuDgRAVYRjoV2Perb7vYABSYAGBAZBQYRjNVltQgJFQUJGQUFZbYABhGPxhF6NWW1BgAGXerb7vADqQUGAAgFuEgRAVYRkiVzqRUGABgQGQUGEZDFZbUFCAkVBQkZBQVltgAGEZN2EXo1ZbUGAAZd6tvu8AUZBQYACBYABSYABbhIEQFWEZZFdgAFGRUGABgQGQUGEZTFZbUICRUFCAkVBQkZBQVltgAGEZfGEXo1ZbUGAAZd6tvu8AHZBQYABbg4EQFWEZpFeBYAAdkVBgAYEBkFBhGYtWW1CAkVBQkZBQVltgYGAAYAWQUGAggwGDUWBAUWAggYOFYACIWvGAYRnTV2AAgP1bgZVQUFBQUFCRkFBWW2AAgGACkFBgIIMBg1GDYCCBg4VgAIha8YBhGgJXYACA/VtQUFBQUJGQUFZbYABhGhZhF6NWW1BbYQPoWhEVYRpAV2ABgGAAgoJUYRo0kZBhKrpWW5JQUIGQVVBhGhhWW2ABVJBQkFZbYABhGlJhF6NWW1BgAGXerb7vABCQUGAAgFuEgRAVYRp7V4JgARCRUGABgQGQUGEaYlZbUFCAkVBQkZBQVltgAGEakGEXo1ZbUGAAZd6tvu8ARJBQYACAW4SBEBVhGrZXRJFQYAGBAZBQYRqgVltQUICRUFCRkFBWW2AAYRrLYRejVltQYABl3q2+7wARkFBgAIBbhIEQFWEa9FdgAYMRkVBgAYEBkFBhGttWW1BQgJFQUJGQUFZbYABhGwlhF6NWW1BgAGXerb7vAD6QUGAAW4OBEBVhGzFXYCBgAIA+YAGBAZBQYRsYVltQgJFQUJGQUFZbYABhG0VhF6NWW1BgAGXerb7vAEWQUGAAgFuEgRAVYRtrV0WRUGABgQGQUGEbVVZbUFCAkVBQkZBQVltgAGEbgGEXo1ZbUGAAZd6tvu8AApBQYABbg4EQFWEbqFdgAYICkVBgAYEBkFBhG49WW1CAkVBQkZBQVltgAGEbvGEXo1ZbUGAAZd6tvu8ACJBQYABbg4EQFWEcBVd///////////////////////////////////////////9gAIMIkVBgAYEBkFBhG8tWW1CAkVBQkZBQVltgAGEcGWEXo1ZbUGAAZd6tvu8AVJBQgGAAVWAAW4OBEBVhHERXYABUkVBgAYEBkFBhHCxWW1CAkVBQkZBQVltgAGEcWGEXo1ZbUGAAZd6tvu8AWpBQYACAW4SBEBVhHH5XWpFQYAGBAZBQYRxoVltQUICRUFCRkFBWW2AAYRyTYRejVltQYABl3q2+7wAZkFBgAFuDgRAVYRy5V4EZkVBgAYEBkFBhHKJWW1Bl3q2+7wAZgRRhHMxXgBmQUFuAkVBQkZBQVltgYICCURRhHRpXYEBRfwjDeaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgVJgBAFhHRGQYStLVltgQFGAkQOQ/VtgAGAHkFBgIIMBg1FgQISChGAAh1rxgGEdOldgAID9W1BQUFCRkFBWW2AAYR1NYRejVltQYABl3q2+7wChkFCAYBBSYABbg4EQFWEdeVeAYAZgEKFgAYEBkFBhHWBWW1CAkVBQkZBQVltgAGEdjWEXo1ZbUGAAZd6tvu8AFpBQYABbg4EQFWEdtFeBghaRUGABgQGQUGEdnFZbUICRUFCRkFBWW2BgYABgBJBQYCCDAYNRYEBRgYGDhWAAiFrxgGEd4ldgAID9W4GVUFBQUFBQkZBQVltgYGAAYAiQUGBAgoRRYCCGAWAAhVrxgGEeD1dgAID9W1BQkZBQVltgAGCAglEUYR5cV2BAUX8Iw3mgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFSYAQBYR5TkGErt1ZbYEBRgJEDkP1bYABgAZBQYCCDAWAggQFRYB8aYCCCAVJgIGBAUWCAg2AAhlrxgGEeildgAID9W2BAUVGTUFBQUJGQUFZbYABhHqJhF6NWW1BbYQPoWhEVYR7bV2ABgGAAgoJUYR7AkZBhKrpWW5JQUIGQVVBDYAFUYR7VkZBhLAZWW1BhHqRWW2ABVJBQkFZbYABhHu1hF6NWW1BgAGXerb7vAEaQUGAAgFuEgRAVYR8TV0aRUGABgQGQUGEe/VZbUFCAkVBQkZBQVltgAGEfKGEXo1ZbUGAAZd6tvu8ABZBQYABbg4EQFWEfUFdgAYIFkVBgAYEBkFBhHzdWW1CAkVBQkZBQVltgAGEfZGEXo1ZbUGAAZd6tvu8AOZBQYABbg4EQFWEfjFdgIGAAgDlgAYEBkFBhH3NWW1CAkVBQkZBQVltgAGACg4OQkYBgAYFUAYCCVYCRUFBgAZADkGAAUmAgYAAgAWAAkJGSkJGSkJGSkJGSUJGCYR/VkpGQYS3uVltQYAKAVJBQkFCSkVBQVltgAGEf7mEXo1ZbUGAAZd6tvu8AWZBQYACAW4SBEBVhIBRXWZFQYAGBAZBQYR/+VltQUICRUFCRkFBWW2AAYSApYRejVltQYABl3q2+7wA4kFBgAIBbhIEQFWEgT1c4kVBgAYEBkFBhIDlWW1BQgJFQUJGQUFZbYABhIGRhF6NWW1BgAGXerb7vAEGQUGAAgFuEgRAVYSCKV0GRUGABgQGQUGEgdFZbUFCAkVBQkZBQVltgAGEgn2EXo1ZbUGAAZd6tvu8AMJBQYACAW4SBEBVhIMVXMJFQYAGBAZBQYSCvVltQUICRUFCRkFBWW2AAYSDaYRejVltQYABl3q2+7wCjkFCAYBBSYABbg4EQFWEhCldgA2ACgmAGYBCjYAGBAZBQYSDtVltQgJFQUJGQUFZbYABhIR5hF6NWW1BgAGXerb7vAAuQUGAAW4OBEBVhIUZXgWAgC5FQYAGBAZBQYSEtVltQgJFQUJGQUFZbYABhIVphF6NWW1BgAGXerb7vAEeQUGAAgFuEgRAVYSGAV0eRUGABgQGQUGEhalZbUFCAkVBQkZBQVltgAGEhlWEXo1ZbUGAAZd6tvu8AHJBQYACAW4SBEBVhIb5XgmAAHJJQYAGBAZBQYSGlVltQUICRUFCRkFBWW2AAYSHTYRejVltQYABl3q2+7wA1kFBgAIBbhIEQFWEh+1dgADWRUGABgQGQUGEh41ZbUFCAkVBQkZBQVltgAGEiEGEXo1ZbUGAAZd6tvu8AVZBQYABbg4EQFWEiNleBYABVYAGBAZBQYSIfVltQgJFQUJGQUFZbYABhIkphF6NWW1BgAGXerb7vABiQUGAAW4OBEBVhInJXYACCGJFQYAGBAZBQYSJZVltQgJFQUJGQUFZbYABhIoZhF6NWW1BgAGXerb7vAAOQUGAAW4OBEBVhIq5XYACCA5FQYAGBAZBQYSKVVltQgJFQUJGQUFZbYABhIsJhF6NWW1BgAGXerb7vAAeQUGAAW4OBEBVhIwlXf///////////////////////////////////////////ggeRUGABgQGQUGEi0VZbUICRUFCRkFBWW2AAYSMdYRejVltQYABl3q2+7wCikFCAYBBSYABbg4EQFWEjS1dgAoFgBmAQomABgQGQUGEjMFZbUICRUFCRkFBWW2AAYSNfYRejVltQYABl3q2+7wAKkFBgAFuDgRAVYSOHV2ABggqRUGABgQGQUGEjblZbUICRUFCRkFBWW2AAYSObYRejVltQYABl3q2+7wAUkFBgAIBbhIEQFWEjw1eCgxSRUGABgQGQUGEjq1ZbUFCAkVBQkZBQVltgAGEj2GEXo1ZbUGAAZd6tvu8AQJBQYABgAUMDYABbhYEQFWEkBFeBQJJQYAGBAZBQYSPtVltQUFCAkVBQkZBQVltgYGCAglEUYSRWV2BAUX8Iw3mgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFSYAQBYSRNkGErS1ZbYEBRgJEDkP1bYABgBpBQYCCDAYNRYECEgoRgAIda8YBhJHZXYACA/VtQUFBQkZBQVltgAGEkiWEXo1ZbUGAAZd6tvu8AFZBQYACAW4SBEBVhJLBXghWRUGABgQGQUGEkmVZbUFCAkVBQkZBQVltgAGEkxWEXo1ZbUGAAZd6tvu8AEpBQYACAW4SBEBVhJO5XgmABEpFQYAGBAZBQYSTVVltQUICRUFCRkFBWW2AAYSUDYRejVltQYABl3q2+7wA7kFBgADBgAFuFgRAVYSUsV4E7klBgAYEBkFBhJRVWW1BQUICRUFCRkFBWW2AAgGADkFBgIIMBg1FgQFFgFIGDhWAAiFrxgGElXFdgAID9W4FRlVBQUFBQUJGQUFZbYABhJXRhF6NWW1BgAGXerb7vAAmQUGAAW4OBEBVhJb1Xf///////////////////////////////////////////YAGDCZFQYAGBAZBQYSWDVltQgJFQUJGQUFZbYABgQFGQUJBWW2AAgP1bYACA/VtgAIGQUJGQUFZbYSXugWEl21ZbgRRhJflXYACA/VtQVltgAIE1kFBhJguBYSXlVluSkVBQVltgAGAggoQDEhVhJidXYSYmYSXRVltbYABhJjWEgoUBYSX8VluRUFCSkVBQVlthJkeBYSXbVluCUlBQVltgAGAgggGQUGEmYmAAgwGEYSY+VluSkVBQVltgAID9W2AAgP1bYABgHxlgH4MBFpBQkZBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgQWAEUmAkYAD9W2Emu4JhJnJWW4EBgYEQZ///////////ghEXFWEm2ldhJtlhJoNWW1uAYEBSUFBQVltgAGEm7WElx1ZbkFBhJvmCgmEmslZbkZBQVltgAGf//////////4IRFWEnGVdhJxhhJoNWW1thJyKCYSZyVluQUGAggQGQUJGQUFZbgoGDN2AAg4MBUlBQUFZbYABhJ1FhJ0yEYSb+VlthJuNWW5BQgoFSYCCBAYSEhAERFWEnbVdhJ2xhJm1WW1thJ3iEgoVhJy9WW1CTklBQUFZbYACCYB+DARJhJ5VXYSeUYSZoVltbgTVhJ6WEgmAghgFhJz5WW5FQUJKRUFBWW2AAYCCChAMSFWEnxFdhJ8NhJdFWW1tgAIIBNWf//////////4ERFWEn4ldhJ+FhJdZWW1thJ+6EgoUBYSeAVluRUFCSkVBQVltgAIFRkFCRkFBWW2AAgoJSYCCCAZBQkpFQUFZbYABbg4EQFWEoMVeAggFRgYQBUmAggQGQUGEoFlZbYACEhAFSUFBQUFZbYABhKEiCYSf3VlthKFKBhWEoAlZbk1BhKGKBhWAghgFhKBNWW2Eoa4FhJnJWW4QBkVBQkpFQUFZbYABgIIIBkFCBgQNgAIMBUmEokIGEYSg9VluQUJKRUFBWW2AAgZBQkZBQVlthKKuBYSiYVluCUlBQVltgAGAgggGQUGEoxmAAgwGEYSiiVluSkVBQVltgAHP//////////////////////////4IWkFCRkFBWW2AAYSj3gmEozFZbkFCRkFBWW2EpB4FhKOxWW4JSUFBWW2AAYCCCAZBQYSkiYACDAYRhKP5WW5KRUFBWW2AAgP1bYACA/VtgAICDYB+EARJhKUhXYSlHYSZoVltbgjWQUGf//////////4ERFWEpZVdhKWRhKShWW1tgIIMBkVCDYAGCAoMBERVhKYFXYSmAYSktVltbklCSkFBWW2AAgGAgg4UDEhVhKZ9XYSmeYSXRVltbYACDATVn//////////+BERVhKb1XYSm8YSXWVltbYSnJhYKGAWEpMlZbklCSUFCSUJKQUFZbYAB///////////////////////////8AAAAAAAAAAAAAAACCFpBQkZBQVlthKgqBYSnVVluCUlBQVltgAGAgggGQUGEqJWAAgwGEYSoBVluSkVBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgImAEUmAkYAD9W2AAYAKCBJBQYAGCFoBhKnJXYH+CFpFQW2AgghCBA2EqhVdhKoRhKitWW1tQkZBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgEWAEUmAkYAD9W2AAYSrFgmEl21ZbkVBhKtCDYSXbVluSUIKCAZBQgIIRFWEq6FdhKudhKotWW1uSkVBQVltgAIKCUmAgggGQUJKRUFBWW39JbnZhbGlkIGlucHV0IGxlbmd0aAAAAAAAAAAAAAAAAGAAggFSUFZbYABhKzVgFINhKu5WW5FQYStAgmEq/1ZbYCCCAZBQkZBQVltgAGAgggGQUIGBA2AAgwFSYStkgWErKFZbkFCRkFBWW39JbnZhbGlkIGlucHV0IGRhdGEgbGVuZ3RoLgAAAAAAAGAAggFSUFZbYABhK6FgGoNhKu5WW5FQYSusgmEra1ZbYCCCAZBQkZBQVltgAGAgggGQUIGBA2AAgwFSYSvQgWErlFZbkFCRkFBWW39OSHtxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAUmASYARSYCRgAP1bYABhLBGCYSXbVluRUGEsHINhJdtWW5JQgmEsLFdhLCthK9dWW1uCggaQUJKRUFBWW2AAgpBQkpFQUFZbYACBkFCBYABSYCBgACCQUJGQUFZbYABgIGAfgwEEkFCRkFBWW2AAgoIbkFCSkVBQVltgAGAIgwJhLKR///////////////////////////////////////////+CYSxnVlthLK6Gg2EsZ1ZblVCAGYQWk1CAhhaEF5JQUFCTklBQUFZbYACBkFCRkFBWW2AAYSzrYSzmYSzhhGEl21ZbYSzGVlthJdtWW5BQkZBQVltgAIGQUJGQUFZbYS0Fg2Es0FZbYS0ZYS0RgmEs8lZbhIRUYSx0VluCVVBQUFBWW2AAkFZbYS0uYS0hVlthLTmBhIRhLPxWW1BQUFZbW4GBEBVhLV1XYS1SYACCYS0mVltgAYEBkFBhLT9WW1BQVltgH4IRFWEtoldhLXOBYSxCVlthLXyEYSxXVluBAWAghRAVYS2LV4GQUFthLZ9hLZeFYSxXVluDAYJhLT5WW1BQW1BQUFZbYACCghyQUJKRUFBWW2AAYS3FYAAZhGAIAmEtp1ZbGYCDFpFQUJKRUFBWW2AAYS3eg4NhLbRWW5FQgmACAoIXkFCSkVBQVlthLfiDg2EsN1ZbZ///////////gREVYS4RV2EuEGEmg1ZbW2EuG4JUYSpaVlthLiaCgoVhLWFWW2AAYB+DEWABgRRhLlVXYACEFWEuQ1eChwE1kFBbYS5NhYJhLdJWW4ZVUGEutVZbYB8ZhBZhLmOGYSxCVltgAFuCgRAVYS6LV4SJATWCVWABggGRUGAghQGUUGAggQGQUGEuZlZbhoMQFWEuqFeEiQE1YS6kYB+JFoJhLbRWW4NVUFtgAWACiAIBiFVQUFBbUFBQUFBQUFb+omRpcGZzWCISIDEkITSIwvH8pZaHh/DD6W+6hGkSmoB5jhHudSkDtL/cZHNvbGNDAAgTADM=", + "touched": true, + "read": true + }, + "0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6": { + "address": "0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6", + "balance": 1e+27, + "nonce": 18642, + "read": true + }, + "0xe4f2Dea6e117FCBa4eC4FDd1D090245110763Dd9": { + "address": "0xe4f2Dea6e117FCBa4eC4FDd1D090245110763Dd9", + "balance": 1e+24, + "read": true + } + } + }, + { + "txn": "0xf904aa8248d280830ad21e946fda56c57b0acadb96ed5624ac500c0429d5942980b90444b374012b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de820fc5a02e7447cfb47da129cc74d577531ab6c794351fc0add960ac570483f82a3e0b94a01da25789ee38a368d3316ffe9f74b85fa41f70f11739ab054a00f2f460b053d5", + "delta": { + "0x0000000000000000000000000000000000000000": { + "address": "0x0000000000000000000000000000000000000000", + "balance": 1000000000000092200000000, + "read": true + }, + "0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429": { + "address": "0x6FdA56C57B0Acadb96Ed5624aC500C0429d59429", + "balance": 0, + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000048d2", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b08": "0x000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b09": "0xbaaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ff", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0a": "0xcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabe", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0b": "0xdeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeed", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0c": "0xdecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabe", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0d": "0xfeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00dabadbabe", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0e": "0xb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafecafeb0ba", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0f": "0xb0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b10": "0xdead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00d", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b11": "0xdeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeed", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b12": "0xfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b13": "0x1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00d", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b14": "0xbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabecafed00d", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b15": "0xcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeef", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b16": "0xdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8ed", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b17": "0xd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b18": "0xf00dbabe000ff1ce00bab10c1badb0028badf00dabadbabeb105f00db16b00b5", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b19": "0x0b00b135baaaaaadbaadf00dbad22222baddcafecafeb0bab0bababebeefbabe", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1a": "0xc00010ffcafebabecafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaad", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1b": "0xdeadbabedeadbeafdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10cc", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1c": "0xdeadfeeddecafbaddefec8edd0d0cacae011cfd0facefeedfbadbeeffee1dead", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1d": "0xfeedbabefeedc0deffbadd11f00dbabe000ff1ce00bab10c1badb0028badf00d", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1e": "0xabadbabeb105f00db16b00b50b00b135baaaaaadbaadf00dbad22222baddcafe", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1f": "0xcafeb0bab0bababebeefbabec00010ffcafebabecafed00dcefaedfe0d15ea5e", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b20": "0xdabbad00dead2baddeadbaaddeadbabedeadbeafdeadbeefdeadc0dedeaddead", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b21": "0xdeadd00ddeadfa11dead10ccdeadfeeddecafbaddefec8edd0d0cacae011cfd0", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b22": "0xfacefeedfbadbeeffee1deadfeedbabefeedc0deffbadd11f00dbabe000ff1ce", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b23": "0x00bab10c1badb0028badf00dabadbabeb105f00db16b00b50b00b135baaaaaad", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b24": "0xbaadf00dbad22222baddcafecafeb0bab0bababebeefbabec00010ffcafebabe", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b25": "0xcafed00dcefaedfe0d15ea5edabbad00dead2baddeadbaaddeadbabedeadbeaf", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b26": "0xdeadbeefdeadc0dedeaddeaddeadd00ddeadfa11dead10ccdeadfeeddecafbad", + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b27": "0xdefec8edd0d0cacae011cfd0facefeedfbadbeeffee1deadfeedbabefeedc0de", + "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bba39f": "0x0000000000000000000000000000000000000000000000000000000000000801" + }, + "storage_read": { + "0x0000000000000000000000000000000000000000000000000000000000000002": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b08": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b09": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0a": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0b": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0c": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0d": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0e": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b0f": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b10": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b11": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b12": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b13": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b14": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b15": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b16": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b17": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b18": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b19": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1a": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1b": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1c": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1d": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1e": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b1f": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b20": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b21": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b22": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b23": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b24": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b25": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b26": {}, + "0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b27": {}, + "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bba39f": {} + }, + "code_read": "YIBgQFI0gBVhABBXYACA/VtQYAQ2EGEEVFdgADVg4ByAY4CUf4ARYQJBV4Bjv1KcoRFhATtXgGPdm+9gEWEAw1eAY/J5yoERYQCHV4Bj8nnKgRRhEWFXgGP00fxhFGERkVeAY/WPw2oUYRHBV4Bj9rC79xRhEfFXgGP953IcFGESIVdhBFRWW4Bj3ZvvYBRhEHFXgGPel6NjFGEQoVeAY+n5s/IUYRDRV4Bj6lFB5hRhEQFXgGPt8APPFGERMVdhBFRWW4Bjzjz07xFhAQpXgGPOPPTvFGEPgVeAY9EXMgsUYQ+xV4Bj1R57WxRhD+FXgGPVP/P9FGEQEVeAY9k81VgUYRBBV2EEVFZbgGO/UpyhFGEOwVeAY8Ngq6YUYQ7xV4BjxCDrYRRhDyFXgGPEvWXVFGEPUVdhBFRWW4BjoYaDyxFhAclXgGOzdAErEWEBjVeAY7N0ASsUYQ3RV4Bjs9hH8hRhDgFXgGO3uGIHFGEOMVeAY7gcFIQUYQ5hV4Bjvch1/BRhDpFXYQRUVluAY6GGg8sUYQzzV4BjonG3IRRhDSNXgGOmChCHFGENQVeAY6ZFycIUYQ1xV4BjrK699hRhDaFXYQRUVluAY5YuTcIRYQIQV4Bjli5NwhRhDANXgGOYRW8+FGEMM1eAY5orfIEUYQxjV4BjnM58+RRhDJNXgGOgQK7GFGEMw1dhBFRWW4BjgJR/gBRhC0NXgGOIDv85FGELc1eAY5GKX80UYQujV4BjkeeydxRhC9NXYQRUVluAYzQw7AYRYQNSV4BjYOE83hFhAtpXgGNvCZyNEWECnleAY28JnI0UYQpTV4BjcdkdKBRhCoNXgGN7bgsOFGEKs1eAY3wZHSAUYQrjV4BjfejG+BRhCxNXYQRUVluAY2DhPN4UYQl1V4BjYT0KghRhCaVXgGNjE41PFGEJ1VeAY2Wbu08UYQoFV4Bjbn8f5xRhCiNXYQRUVluAY0D+JmIRYQMhV4BjQP4mYhRhCIVXgGNEzzvHFGEItVeAY0phrx8UYQjlV4BjTSx0sxRhCRVXgGNVkMLZFGEJRVdhBFRWW4BjNDDsBhRhB9dXgGM3EwPAFGEIB1eAYzpBHxIUYQglV4BjOkJd/BRhCFVXYQRUVluAYxgJO0YRYQPgV4BjIZzd6xFhA6RXgGMhnN3rFGEG51eAYyKU/H8UYQcXV4BjKHHvhRRhB0dXgGMrIe9EFGEHd1eAYy0055gUYQenV2EEVFZbgGMYCTtGFGEF91eAYxm2IdYUYQYnV4BjGroH6hRhBldXgGMd4vNDFGEGh1eAYyAHMy4UYQa3V2EEVFZbgGMLqKc7EWEEJ1eAYwuopzsUYQUZV4BjEoemjBRhBUlXgGMTXVL3FGEFZ1eAYxWBzxkUYQWXV4BjFlghUBRhBcdXYQRUVluAYwNK73EUYQRZV4BjBQCC+BRhBIlXgGMIe06EFGEEuVeAYws7mWoUYQTpV1tgAID9W2EEc2AEgDYDgQGQYQRukZBhJhFWW2ESUVZbYEBRYQSAkZBhJk1WW2BAUYCRA5DzW2EEo2AEgDYDgQGQYQSekZBhJhFWW2ESjFZbYEBRYQSwkZBhJk1WW2BAUYCRA5DzW2EE02AEgDYDgQGQYQTOkZBhJhFWW2ESx1ZbYEBRYQTgkZBhJk1WW2BAUYCRA5DzW2EFA2AEgDYDgQGQYQT+kZBhJ65WW2ETAVZbYEBRYQUQkZBhKHZWW2BAUYCRA5DzW2EFM2AEgDYDgQGQYQUukZBhJhFWW2ETKFZbYEBRYQVAkZBhJk1WW2BAUYCRA5DzW2EFUWETZFZbYEBRYQVekZBhJk1WW2BAUYCRA5DzW2EFgWAEgDYDgQGQYQV8kZBhJhFWW2ETbVZbYEBRYQWOkZBhJk1WW2BAUYCRA5DzW2EFsWAEgDYDgQGQYQWskZBhJhFWW2ETqVZbYEBRYQW+kZBhJk1WW2BAUYCRA5DzW2EF4WAEgDYDgQGQYQXckZBhJhFWW2ET5FZbYEBRYQXukZBhJk1WW2BAUYCRA5DzW2EGEWAEgDYDgQGQYQYMkZBhJhFWW2EUP1ZbYEBRYQYekZBhJk1WW2BAUYCRA5DzW2EGQWAEgDYDgQGQYQY8kZBhJhFWW2EUfVZbYEBRYQZOkZBhJk1WW2BAUYCRA5DzW2EGcWAEgDYDgQGQYQZskZBhJhFWW2EVDFZbYEBRYQZ+kZBhJk1WW2BAUYCRA5DzW2EGoWAEgDYDgQGQYQackZBhJhFWW2EVUlZbYEBRYQaukZBhJk1WW2BAUYCRA5DzW2EG0WAEgDYDgQGQYQbMkZBhJhFWW2EVkFZbYEBRYQbekZBhJk1WW2BAUYCRA5DzW2EHAWAEgDYDgQGQYQb8kZBhJhFWW2EVzFZbYEBRYQcOkZBhJk1WW2BAUYCRA5DzW2EHMWAEgDYDgQGQYQcskZBhJhFWW2EWB1ZbYEBRYQc+kZBhJk1WW2BAUYCRA5DzW2EHYWAEgDYDgQGQYQdckZBhJhFWW2EWRlZbYEBRYQdukZBhJk1WW2BAUYCRA5DzW2EHkWAEgDYDgQGQYQeMkZBhJhFWW2EWgVZbYEBRYQeekZBhJk1WW2BAUYCRA5DzW2EHwWAEgDYDgQGQYQe8kZBhJhFWW2EWvFZbYEBRYQfOkZBhJk1WW2BAUYCRA5DzW2EH8WAEgDYDgQGQYQfskZBhJhFWW2EW91ZbYEBRYQf+kZBhKHZWW2BAUYCRA5DzW2EID2EXo1ZbYEBRYQgckZBhJk1WW2BAUYCRA5DzW2EIP2AEgDYDgQGQYQg6kZBhJhFWW2EXwlZbYEBRYQhMkZBhJk1WW2BAUYCRA5DzW2EIb2AEgDYDgQGQYQhqkZBhJhFWW2EX/lZbYEBRYQh8kZBhJk1WW2BAUYCRA5DzW2EIn2AEgDYDgQGQYQiakZBhJhFWW2EYOlZbYEBRYQiskZBhJk1WW2BAUYCRA5DzW2EIz2AEgDYDgQGQYQjKkZBhJhFWW2EYeVZbYEBRYQjckZBhJk1WW2BAUYCRA5DzW2EI/2AEgDYDgQGQYQj6kZBhJhFWW2EYtFZbYEBRYQkMkZBhJk1WW2BAUYCRA5DzW2EJL2AEgDYDgQGQYQkqkZBhJhFWW2EY8lZbYEBRYQk8kZBhJk1WW2BAUYCRA5DzW2EJX2AEgDYDgQGQYQlakZBhJhFWW2EZLVZbYEBRYQlskZBhJk1WW2BAUYCRA5DzW2EJj2AEgDYDgQGQYQmKkZBhJhFWW2EZclZbYEBRYQmckZBhJk1WW2BAUYCRA5DzW2EJv2AEgDYDgQGQYQm6kZBhJ65WW2EZrlZbYEBRYQnMkZBhKHZWW2BAUYCRA5DzW2EJ72AEgDYDgQGQYQnqkZBhJ65WW2EZ4FZbYEBRYQn8kZBhKLFWW2BAUYCRA5DzW2EKDWEaDFZbYEBRYQoakZBhJk1WW2BAUYCRA5DzW2EKPWAEgDYDgQGQYQo4kZBhJhFWW2EaSFZbYEBRYQpKkZBhJk1WW2BAUYCRA5DzW2EKbWAEgDYDgQGQYQpokZBhJhFWW2EahlZbYEBRYQp6kZBhJk1WW2BAUYCRA5DzW2EKnWAEgDYDgQGQYQqYkZBhJhFWW2EawVZbYEBRYQqqkZBhJk1WW2BAUYCRA5DzW2EKzWAEgDYDgQGQYQrIkZBhJhFWW2Ea/1ZbYEBRYQrakZBhJk1WW2BAUYCRA5DzW2EK/WAEgDYDgQGQYQr4kZBhJhFWW2EbO1ZbYEBRYQsKkZBhJk1WW2BAUYCRA5DzW2ELLWAEgDYDgQGQYQsokZBhJhFWW2EbdlZbYEBRYQs6kZBhJk1WW2BAUYCRA5DzW2ELXWAEgDYDgQGQYQtYkZBhJhFWW2EbslZbYEBRYQtqkZBhJk1WW2BAUYCRA5DzW2ELjWAEgDYDgQGQYQuIkZBhJhFWW2EcD1ZbYEBRYQuakZBhJk1WW2BAUYCRA5DzW2ELvWAEgDYDgQGQYQu4kZBhJhFWW2EcTlZbYEBRYQvKkZBhJk1WW2BAUYCRA5DzW2EL7WAEgDYDgQGQYQvokZBhJhFWW2EciVZbYEBRYQv6kZBhJk1WW2BAUYCRA5DzW2EMHWAEgDYDgQGQYQwYkZBhJ65WW2Ec1VZbYEBRYQwqkZBhKHZWW2BAUYCRA5DzW2EMTWAEgDYDgQGQYQxIkZBhJhFWW2EdQ1ZbYEBRYQxakZBhJk1WW2BAUYCRA5DzW2EMfWAEgDYDgQGQYQx4kZBhJhFWW2Edg1ZbYEBRYQyKkZBhJk1WW2BAUYCRA5DzW2EMrWAEgDYDgQGQYQyokZBhJ65WW2EdvlZbYEBRYQy6kZBhKHZWW2BAUYCRA5DzW2EM3WAEgDYDgQGQYQzYkZBhJ65WW2Ed71ZbYEBRYQzqkZBhKHZWW2BAUYCRA5DzW2ENDWAEgDYDgQGQYQ0IkZBhJ65WW2EeFlZbYEBRYQ0akZBhKQ1WW2BAUYCRA5DzW2ENK2EemFZbYEBRYQ04kZBhJk1WW2BAUYCRA5DzW2ENW2AEgDYDgQGQYQ1WkZBhJhFWW2Ee41ZbYEBRYQ1okZBhJk1WW2BAUYCRA5DzW2ENi2AEgDYDgQGQYQ2GkZBhJhFWW2EfHlZbYEBRYQ2YkZBhJk1WW2BAUYCRA5DzW2ENu2AEgDYDgQGQYQ22kZBhJhFWW2EfWlZbYEBRYQ3IkZBhJk1WW2BAUYCRA5DzW2EN62AEgDYDgQGQYQ3mkZBhKYhWW2EfllZbYEBRYQ34kZBhJk1WW2BAUYCRA5DzW2EOG2AEgDYDgQGQYQ4WkZBhJhFWW2Ef5FZbYEBRYQ4okZBhJk1WW2BAUYCRA5DzW2EOS2AEgDYDgQGQYQ5GkZBhJhFWW2EgH1ZbYEBRYQ5YkZBhJk1WW2BAUYCRA5DzW2EOe2AEgDYDgQGQYQ52kZBhJhFWW2EgWlZbYEBRYQ6IkZBhJk1WW2BAUYCRA5DzW2EOq2AEgDYDgQGQYQ6mkZBhJhFWW2EglVZbYEBRYQ64kZBhJk1WW2BAUYCRA5DzW2EO22AEgDYDgQGQYQ7WkZBhJhFWW2Eg0FZbYEBRYQ7okZBhJk1WW2BAUYCRA5DzW2EPC2AEgDYDgQGQYQ8GkZBhJhFWW2EhFFZbYEBRYQ8YkZBhJk1WW2BAUYCRA5DzW2EPO2AEgDYDgQGQYQ82kZBhJhFWW2EhUFZbYEBRYQ9IkZBhJk1WW2BAUYCRA5DzW2EPa2AEgDYDgQGQYQ9mkZBhJhFWW2Ehi1ZbYEBRYQ94kZBhJk1WW2BAUYCRA5DzW2EPm2AEgDYDgQGQYQ+WkZBhJhFWW2EhyVZbYEBRYQ+okZBhJk1WW2BAUYCRA5DzW2EPy2AEgDYDgQGQYQ/GkZBhJhFWW2EiBlZbYEBRYQ/YkZBhJk1WW2BAUYCRA5DzW2EP+2AEgDYDgQGQYQ/2kZBhJhFWW2EiQFZbYEBRYRAIkZBhJk1WW2BAUYCRA5DzW2EQK2AEgDYDgQGQYRAmkZBhJhFWW2EifFZbYEBRYRA4kZBhJk1WW2BAUYCRA5DzW2EQW2AEgDYDgQGQYRBWkZBhJhFWW2EiuFZbYEBRYRBokZBhJk1WW2BAUYCRA5DzW2EQi2AEgDYDgQGQYRCGkZBhJhFWW2EjE1ZbYEBRYRCYkZBhJk1WW2BAUYCRA5DzW2EQu2AEgDYDgQGQYRC2kZBhJhFWW2EjVVZbYEBRYRDIkZBhJk1WW2BAUYCRA5DzW2EQ62AEgDYDgQGQYRDmkZBhJhFWW2EjkVZbYEBRYRD4kZBhJk1WW2BAUYCRA5DzW2ERG2AEgDYDgQGQYREWkZBhJhFWW2EjzlZbYEBRYREokZBhJk1WW2BAUYCRA5DzW2ERS2AEgDYDgQGQYRFGkZBhJ65WW2EkEFZbYEBRYRFYkZBhKHZWW2BAUYCRA5DzW2ERe2AEgDYDgQGQYRF2kZBhJhFWW2Ekf1ZbYEBRYRGIkZBhJk1WW2BAUYCRA5DzW2ERq2AEgDYDgQGQYRGmkZBhJhFWW2Eku1ZbYEBRYRG4kZBhJk1WW2BAUYCRA5DzW2ER22AEgDYDgQGQYRHWkZBhJhFWW2Ek+VZbYEBRYRHokZBhJk1WW2BAUYCRA5DzW2ESC2AEgDYDgQGQYRIGkZBhJ65WW2ElOFZbYEBRYRIYkZBhKhBWW2BAUYCRA5DzW2ESO2AEgDYDgQGQYRI2kZBhJhFWW2ElalZbYEBRYRJIkZBhJk1WW2BAUYCRA5DzW2AAYRJbYRejVltQYABl3q2+7wA2kFBgAIBbhIEQFWESgVc2kVBgAYEBkFBhEmtWW1BQgJFQUJGQUFZbYABhEpZhF6NWW1BgAGXerb7vADKQUGAAgFuEgRAVYRK8VzKRUGABgQGQUGESplZbUFCAkVBQkZBQVltgAGES0WEXo1ZbUGAAZd6tvu8AUpBQYABbg4EQFWES91eBYABSYAGBAZBQYRLgVltQgJFQUJGQUFZbYGBgAGAIkFBgQIKEUWAghgFgAIVa8YBhEyFXYACA/VtQUJGQUFZbYABhEzJhF6NWW1BgAGXerb7vAAGQUGAAW4OBEBVhE1pXYACCAZFQYAGBAZBQYRNBVltQgJFQUJGQUFZbYACAVJBQkFZbYABhE3dhF6NWW1BgAGXerb7vABeQUGAAW4OBEBVhE59XYACCF5FQYAGBAZBQYROGVltQgJFQUJGQUFZbYABhE7NhF6NWW1BgAGXerb7vADSQUGAAgFuEgRAVYRPZVzSRUGABgQGQUGETw1ZbUFCAkVBQkZBQVltgAGET7mEXo1ZbUGAAZd6tvu8ABpBQYABbg4EQFWEUNVd///////////////////////////////////////////+CBpFQYAGBAZBQYRP9VltQgJFQUJGQUFZbYABhFElhF6NWW1BgAGXerb7vABOQUGAAgFuEgRAVYRRyV2ABgxORUGABgQGQUGEUWVZbUFCAkVBQkZBQVltgAGEUh2EXo1ZbUGAAZd6tvu8AIJBQf/////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYABSYACAW4SBEBVhFNVXYARgACCRUGABgQGQUGEUu1ZbUH8pBFpZIAfQwkbvAsIiNXDalSLQzw9zKCx5obyPC7LCOIEUYRUCV2AAkVBbUICRUFCRkFBWW2AAYRUWYRejVltQYABl3q2+7wCkkFCAYBBSYABbg4EQFWEVSFdgBGADYAKDYAZgEKRgAYEBkFBhFSlWW1CAkVBQkZBQVltgAGEVXGEXo1ZbUGAAZd6tvu8AGpBQYACAW4SBEBVhFYVXgmAAGpFQYAGBAZBQYRVsVltQUICRUFCRkFBWW2AAYRWaYRejVltQYABl3q2+7wAbkFBgAFuDgRAVYRXCV4FgABuRUGABgQGQUGEVqVZbUICRUFCRkFBWW2AAYRXWYRejVltQYABl3q2+7wBCkFBgAIBbhIEQFWEV/FdCkVBgAYEBkFBhFeZWW1BQgJFQUJGQUFZbYABhFhFhF6NWW1BgAGXerb7vADGQUGAAMGAAW4WBEBVhFjpXgTGSUGABgQGQUGEWI1ZbUFBQgJFQUJGQUFZbYABhFlBhF6NWW1BgAGXerb7vAEiQUGAAgFuEgRAVYRZ2V0iRUGABgQGQUGEWYFZbUFCAkVBQkZBQVltgAGEWi2EXo1ZbUGAAZd6tvu8APZBQYACAW4SBEBVhFrFXPZFQYAGBAZBQYRabVltQUICRUFCRkFBWW2AAYRbGYRejVltQYABl3q2+7wBDkFBgAIBbhIEQFWEW7FdDkVBgAYEBkFBhFtZWW1BQgJFQUJGQUFZbYAKBgVSBEGEXB1dgAID9W5BgAFJgIGAAIAFgAJFQkFCAVGEXIpBhKlpWW4BgHwFgIICRBAJgIAFgQFGQgQFgQFKAkpGQgYFSYCABgoBUYRdOkGEqWlZbgBVhF5tXgGAfEGEXcFdhAQCAg1QEAoNSkWAgAZFhF5tWW4IBkZBgAFJgIGAAIJBbgVSBUpBgAQGQYCABgIMRYRd+V4KQA2AfFoIBkVtQUFBQUIFWW2AAYAFgAFRhF7SRkGEqulZbYACBkFVQYABUkFCQVltgAGEXzGEXo1ZbUGAAZd6tvu8ABJBQYABbg4EQFWEX9FdgAYIEkVBgAYEBkFBhF9tWW1CAkVBQkZBQVltgAGEYCGEXo1ZbUGAAZd6tvu8AN5BQYABbg4EQFWEYMFdgIGAAgDdgAYEBkFBhGBdWW1CAkVBQkZBQVltgAGEYRGEXo1ZbUGAAZd6tvu8AoJBQgGAQUmAAW4OBEBVhGG9XYAZgEKBgAYEBkFBhGFdWW1CAkVBQkZBQVltgAGEYg2EXo1ZbUGAAZd6tvu8AM5BQYACAW4SBEBVhGKlXM5FQYAGBAZBQYRiTVltQUICRUFCRkFBWW2AAYRi+YRejVltQYABl3q2+7wBTkFBgAFuDgRAVYRjoV2Perb7vYABSYAGBAZBQYRjNVltQgJFQUJGQUFZbYABhGPxhF6NWW1BgAGXerb7vADqQUGAAgFuEgRAVYRkiVzqRUGABgQGQUGEZDFZbUFCAkVBQkZBQVltgAGEZN2EXo1ZbUGAAZd6tvu8AUZBQYACBYABSYABbhIEQFWEZZFdgAFGRUGABgQGQUGEZTFZbUICRUFCAkVBQkZBQVltgAGEZfGEXo1ZbUGAAZd6tvu8AHZBQYABbg4EQFWEZpFeBYAAdkVBgAYEBkFBhGYtWW1CAkVBQkZBQVltgYGAAYAWQUGAggwGDUWBAUWAggYOFYACIWvGAYRnTV2AAgP1bgZVQUFBQUFCRkFBWW2AAgGACkFBgIIMBg1GDYCCBg4VgAIha8YBhGgJXYACA/VtQUFBQUJGQUFZbYABhGhZhF6NWW1BbYQPoWhEVYRpAV2ABgGAAgoJUYRo0kZBhKrpWW5JQUIGQVVBhGhhWW2ABVJBQkFZbYABhGlJhF6NWW1BgAGXerb7vABCQUGAAgFuEgRAVYRp7V4JgARCRUGABgQGQUGEaYlZbUFCAkVBQkZBQVltgAGEakGEXo1ZbUGAAZd6tvu8ARJBQYACAW4SBEBVhGrZXRJFQYAGBAZBQYRqgVltQUICRUFCRkFBWW2AAYRrLYRejVltQYABl3q2+7wARkFBgAIBbhIEQFWEa9FdgAYMRkVBgAYEBkFBhGttWW1BQgJFQUJGQUFZbYABhGwlhF6NWW1BgAGXerb7vAD6QUGAAW4OBEBVhGzFXYCBgAIA+YAGBAZBQYRsYVltQgJFQUJGQUFZbYABhG0VhF6NWW1BgAGXerb7vAEWQUGAAgFuEgRAVYRtrV0WRUGABgQGQUGEbVVZbUFCAkVBQkZBQVltgAGEbgGEXo1ZbUGAAZd6tvu8AApBQYABbg4EQFWEbqFdgAYICkVBgAYEBkFBhG49WW1CAkVBQkZBQVltgAGEbvGEXo1ZbUGAAZd6tvu8ACJBQYABbg4EQFWEcBVd///////////////////////////////////////////9gAIMIkVBgAYEBkFBhG8tWW1CAkVBQkZBQVltgAGEcGWEXo1ZbUGAAZd6tvu8AVJBQgGAAVWAAW4OBEBVhHERXYABUkVBgAYEBkFBhHCxWW1CAkVBQkZBQVltgAGEcWGEXo1ZbUGAAZd6tvu8AWpBQYACAW4SBEBVhHH5XWpFQYAGBAZBQYRxoVltQUICRUFCRkFBWW2AAYRyTYRejVltQYABl3q2+7wAZkFBgAFuDgRAVYRy5V4EZkVBgAYEBkFBhHKJWW1Bl3q2+7wAZgRRhHMxXgBmQUFuAkVBQkZBQVltgYICCURRhHRpXYEBRfwjDeaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgVJgBAFhHRGQYStLVltgQFGAkQOQ/VtgAGAHkFBgIIMBg1FgQISChGAAh1rxgGEdOldgAID9W1BQUFCRkFBWW2AAYR1NYRejVltQYABl3q2+7wChkFCAYBBSYABbg4EQFWEdeVeAYAZgEKFgAYEBkFBhHWBWW1CAkVBQkZBQVltgAGEdjWEXo1ZbUGAAZd6tvu8AFpBQYABbg4EQFWEdtFeBghaRUGABgQGQUGEdnFZbUICRUFCRkFBWW2BgYABgBJBQYCCDAYNRYEBRgYGDhWAAiFrxgGEd4ldgAID9W4GVUFBQUFBQkZBQVltgYGAAYAiQUGBAgoRRYCCGAWAAhVrxgGEeD1dgAID9W1BQkZBQVltgAGCAglEUYR5cV2BAUX8Iw3mgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFSYAQBYR5TkGErt1ZbYEBRgJEDkP1bYABgAZBQYCCDAWAggQFRYB8aYCCCAVJgIGBAUWCAg2AAhlrxgGEeildgAID9W2BAUVGTUFBQUJGQUFZbYABhHqJhF6NWW1BbYQPoWhEVYR7bV2ABgGAAgoJUYR7AkZBhKrpWW5JQUIGQVVBDYAFUYR7VkZBhLAZWW1BhHqRWW2ABVJBQkFZbYABhHu1hF6NWW1BgAGXerb7vAEaQUGAAgFuEgRAVYR8TV0aRUGABgQGQUGEe/VZbUFCAkVBQkZBQVltgAGEfKGEXo1ZbUGAAZd6tvu8ABZBQYABbg4EQFWEfUFdgAYIFkVBgAYEBkFBhHzdWW1CAkVBQkZBQVltgAGEfZGEXo1ZbUGAAZd6tvu8AOZBQYABbg4EQFWEfjFdgIGAAgDlgAYEBkFBhH3NWW1CAkVBQkZBQVltgAGACg4OQkYBgAYFUAYCCVYCRUFBgAZADkGAAUmAgYAAgAWAAkJGSkJGSkJGSkJGSUJGCYR/VkpGQYS3uVltQYAKAVJBQkFCSkVBQVltgAGEf7mEXo1ZbUGAAZd6tvu8AWZBQYACAW4SBEBVhIBRXWZFQYAGBAZBQYR/+VltQUICRUFCRkFBWW2AAYSApYRejVltQYABl3q2+7wA4kFBgAIBbhIEQFWEgT1c4kVBgAYEBkFBhIDlWW1BQgJFQUJGQUFZbYABhIGRhF6NWW1BgAGXerb7vAEGQUGAAgFuEgRAVYSCKV0GRUGABgQGQUGEgdFZbUFCAkVBQkZBQVltgAGEgn2EXo1ZbUGAAZd6tvu8AMJBQYACAW4SBEBVhIMVXMJFQYAGBAZBQYSCvVltQUICRUFCRkFBWW2AAYSDaYRejVltQYABl3q2+7wCjkFCAYBBSYABbg4EQFWEhCldgA2ACgmAGYBCjYAGBAZBQYSDtVltQgJFQUJGQUFZbYABhIR5hF6NWW1BgAGXerb7vAAuQUGAAW4OBEBVhIUZXgWAgC5FQYAGBAZBQYSEtVltQgJFQUJGQUFZbYABhIVphF6NWW1BgAGXerb7vAEeQUGAAgFuEgRAVYSGAV0eRUGABgQGQUGEhalZbUFCAkVBQkZBQVltgAGEhlWEXo1ZbUGAAZd6tvu8AHJBQYACAW4SBEBVhIb5XgmAAHJJQYAGBAZBQYSGlVltQUICRUFCRkFBWW2AAYSHTYRejVltQYABl3q2+7wA1kFBgAIBbhIEQFWEh+1dgADWRUGABgQGQUGEh41ZbUFCAkVBQkZBQVltgAGEiEGEXo1ZbUGAAZd6tvu8AVZBQYABbg4EQFWEiNleBYABVYAGBAZBQYSIfVltQgJFQUJGQUFZbYABhIkphF6NWW1BgAGXerb7vABiQUGAAW4OBEBVhInJXYACCGJFQYAGBAZBQYSJZVltQgJFQUJGQUFZbYABhIoZhF6NWW1BgAGXerb7vAAOQUGAAW4OBEBVhIq5XYACCA5FQYAGBAZBQYSKVVltQgJFQUJGQUFZbYABhIsJhF6NWW1BgAGXerb7vAAeQUGAAW4OBEBVhIwlXf///////////////////////////////////////////ggeRUGABgQGQUGEi0VZbUICRUFCRkFBWW2AAYSMdYRejVltQYABl3q2+7wCikFCAYBBSYABbg4EQFWEjS1dgAoFgBmAQomABgQGQUGEjMFZbUICRUFCRkFBWW2AAYSNfYRejVltQYABl3q2+7wAKkFBgAFuDgRAVYSOHV2ABggqRUGABgQGQUGEjblZbUICRUFCRkFBWW2AAYSObYRejVltQYABl3q2+7wAUkFBgAIBbhIEQFWEjw1eCgxSRUGABgQGQUGEjq1ZbUFCAkVBQkZBQVltgAGEj2GEXo1ZbUGAAZd6tvu8AQJBQYABgAUMDYABbhYEQFWEkBFeBQJJQYAGBAZBQYSPtVltQUFCAkVBQkZBQVltgYGCAglEUYSRWV2BAUX8Iw3mgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFSYAQBYSRNkGErS1ZbYEBRgJEDkP1bYABgBpBQYCCDAYNRYECEgoRgAIda8YBhJHZXYACA/VtQUFBQkZBQVltgAGEkiWEXo1ZbUGAAZd6tvu8AFZBQYACAW4SBEBVhJLBXghWRUGABgQGQUGEkmVZbUFCAkVBQkZBQVltgAGEkxWEXo1ZbUGAAZd6tvu8AEpBQYACAW4SBEBVhJO5XgmABEpFQYAGBAZBQYSTVVltQUICRUFCRkFBWW2AAYSUDYRejVltQYABl3q2+7wA7kFBgADBgAFuFgRAVYSUsV4E7klBgAYEBkFBhJRVWW1BQUICRUFCRkFBWW2AAgGADkFBgIIMBg1FgQFFgFIGDhWAAiFrxgGElXFdgAID9W4FRlVBQUFBQUJGQUFZbYABhJXRhF6NWW1BgAGXerb7vAAmQUGAAW4OBEBVhJb1Xf///////////////////////////////////////////YAGDCZFQYAGBAZBQYSWDVltQgJFQUJGQUFZbYABgQFGQUJBWW2AAgP1bYACA/VtgAIGQUJGQUFZbYSXugWEl21ZbgRRhJflXYACA/VtQVltgAIE1kFBhJguBYSXlVluSkVBQVltgAGAggoQDEhVhJidXYSYmYSXRVltbYABhJjWEgoUBYSX8VluRUFCSkVBQVlthJkeBYSXbVluCUlBQVltgAGAgggGQUGEmYmAAgwGEYSY+VluSkVBQVltgAID9W2AAgP1bYABgHxlgH4MBFpBQkZBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgQWAEUmAkYAD9W2Emu4JhJnJWW4EBgYEQZ///////////ghEXFWEm2ldhJtlhJoNWW1uAYEBSUFBQVltgAGEm7WElx1ZbkFBhJvmCgmEmslZbkZBQVltgAGf//////////4IRFWEnGVdhJxhhJoNWW1thJyKCYSZyVluQUGAggQGQUJGQUFZbgoGDN2AAg4MBUlBQUFZbYABhJ1FhJ0yEYSb+VlthJuNWW5BQgoFSYCCBAYSEhAERFWEnbVdhJ2xhJm1WW1thJ3iEgoVhJy9WW1CTklBQUFZbYACCYB+DARJhJ5VXYSeUYSZoVltbgTVhJ6WEgmAghgFhJz5WW5FQUJKRUFBWW2AAYCCChAMSFWEnxFdhJ8NhJdFWW1tgAIIBNWf//////////4ERFWEn4ldhJ+FhJdZWW1thJ+6EgoUBYSeAVluRUFCSkVBQVltgAIFRkFCRkFBWW2AAgoJSYCCCAZBQkpFQUFZbYABbg4EQFWEoMVeAggFRgYQBUmAggQGQUGEoFlZbYACEhAFSUFBQUFZbYABhKEiCYSf3VlthKFKBhWEoAlZbk1BhKGKBhWAghgFhKBNWW2Eoa4FhJnJWW4QBkVBQkpFQUFZbYABgIIIBkFCBgQNgAIMBUmEokIGEYSg9VluQUJKRUFBWW2AAgZBQkZBQVlthKKuBYSiYVluCUlBQVltgAGAgggGQUGEoxmAAgwGEYSiiVluSkVBQVltgAHP//////////////////////////4IWkFCRkFBWW2AAYSj3gmEozFZbkFCRkFBWW2EpB4FhKOxWW4JSUFBWW2AAYCCCAZBQYSkiYACDAYRhKP5WW5KRUFBWW2AAgP1bYACA/VtgAICDYB+EARJhKUhXYSlHYSZoVltbgjWQUGf//////////4ERFWEpZVdhKWRhKShWW1tgIIMBkVCDYAGCAoMBERVhKYFXYSmAYSktVltbklCSkFBWW2AAgGAgg4UDEhVhKZ9XYSmeYSXRVltbYACDATVn//////////+BERVhKb1XYSm8YSXWVltbYSnJhYKGAWEpMlZbklCSUFCSUJKQUFZbYAB///////////////////////////8AAAAAAAAAAAAAAACCFpBQkZBQVlthKgqBYSnVVluCUlBQVltgAGAgggGQUGEqJWAAgwGEYSoBVluSkVBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgImAEUmAkYAD9W2AAYAKCBJBQYAGCFoBhKnJXYH+CFpFQW2AgghCBA2EqhVdhKoRhKitWW1tQkZBQVlt/Tkh7cQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAFJgEWAEUmAkYAD9W2AAYSrFgmEl21ZbkVBhKtCDYSXbVluSUIKCAZBQgIIRFWEq6FdhKudhKotWW1uSkVBQVltgAIKCUmAgggGQUJKRUFBWW39JbnZhbGlkIGlucHV0IGxlbmd0aAAAAAAAAAAAAAAAAGAAggFSUFZbYABhKzVgFINhKu5WW5FQYStAgmEq/1ZbYCCCAZBQkZBQVltgAGAgggGQUIGBA2AAgwFSYStkgWErKFZbkFCRkFBWW39JbnZhbGlkIGlucHV0IGRhdGEgbGVuZ3RoLgAAAAAAAGAAggFSUFZbYABhK6FgGoNhKu5WW5FQYSusgmEra1ZbYCCCAZBQkZBQVltgAGAgggGQUIGBA2AAgwFSYSvQgWErlFZbkFCRkFBWW39OSHtxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAUmASYARSYCRgAP1bYABhLBGCYSXbVluRUGEsHINhJdtWW5JQgmEsLFdhLCthK9dWW1uCggaQUJKRUFBWW2AAgpBQkpFQUFZbYACBkFCBYABSYCBgACCQUJGQUFZbYABgIGAfgwEEkFCRkFBWW2AAgoIbkFCSkVBQVltgAGAIgwJhLKR///////////////////////////////////////////+CYSxnVlthLK6Gg2EsZ1ZblVCAGYQWk1CAhhaEF5JQUFCTklBQUFZbYACBkFCRkFBWW2AAYSzrYSzmYSzhhGEl21ZbYSzGVlthJdtWW5BQkZBQVltgAIGQUJGQUFZbYS0Fg2Es0FZbYS0ZYS0RgmEs8lZbhIRUYSx0VluCVVBQUFBWW2AAkFZbYS0uYS0hVlthLTmBhIRhLPxWW1BQUFZbW4GBEBVhLV1XYS1SYACCYS0mVltgAYEBkFBhLT9WW1BQVltgH4IRFWEtoldhLXOBYSxCVlthLXyEYSxXVluBAWAghRAVYS2LV4GQUFthLZ9hLZeFYSxXVluDAYJhLT5WW1BQW1BQUFZbYACCghyQUJKRUFBWW2AAYS3FYAAZhGAIAmEtp1ZbGYCDFpFQUJKRUFBWW2AAYS3eg4NhLbRWW5FQgmACAoIXkFCSkVBQVlthLfiDg2EsN1ZbZ///////////gREVYS4RV2EuEGEmg1ZbW2EuG4JUYSpaVlthLiaCgoVhLWFWW2AAYB+DEWABgRRhLlVXYACEFWEuQ1eChwE1kFBbYS5NhYJhLdJWW4ZVUGEutVZbYB8ZhBZhLmOGYSxCVltgAFuCgRAVYS6LV4SJATWCVWABggGRUGAghQGUUGAggQGQUGEuZlZbhoMQFWEuqFeEiQE1YS6kYB+JFoJhLbRWW4NVUFtgAWACiAIBiFVQUFBbUFBQUFBQUFb+omRpcGZzWCISIDEkITSIwvH8pZaHh/DD6W+6hGkSmoB5jhHudSkDtL/cZHNvbGNDAAgTADM=", + "touched": true, + "read": true + }, + "0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6": { + "address": "0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6", + "balance": 1e+27, + "nonce": 18643, + "read": true + }, + "0xe4f2Dea6e117FCBa4eC4FDd1D090245110763Dd9": { + "address": "0xe4f2Dea6e117FCBa4eC4FDd1D090245110763Dd9", + "balance": 1e+24, + "read": true + } + } + } + ] +} diff --git a/state/immutable-trie/trie_test.go b/state/immutable-trie/trie_test.go index ec109e0834..08fa4e7f14 100644 --- a/state/immutable-trie/trie_test.go +++ b/state/immutable-trie/trie_test.go @@ -55,8 +55,7 @@ func (traceStore) Close() error { return nil } func LoadTrace() (*types.Trace, error) { // Load Trace structure from JSON file. - // traceFile, err := os.Open("7410_readable.json") - traceFile, err := os.Open("../../test-chain-1/consensus/trace_140.json") + traceFile, err := os.Open("7410_readable.json") if err != nil { return nil, err } @@ -165,7 +164,10 @@ func TestTrie_Load(t *testing.T) { // Load the trie from the trace. txn := tt.Txn(ts) - txn.Insert(types.StringToBytes("0x0000000000000000000000000000000000000000000000000000000000000002"), types.StringToBytes("0x00000000000000000000000000000000000000000000000000000000000048d1")) + // txn.Insert(types.StringToBytes("0x0000000000000000000000000000000000000000000000000000000000000002"), types.StringToBytes("0x00000000000000000000000000000000000000000000000000000000000048d1")) + + b := txn.Lookup(types.StringToBytes("0x04e2f49b914b2b5972f4e339e6dc75455852ed61bac5676f58a2b7036def7b18")) + t.Logf("value: %s\n", hex.EncodeToString(b)) for _, txt := range ltr.TxnTraces { je := txt.Delta[addr] diff --git a/types/types.go b/types/types.go index 71b02e13eb..74f1f563ff 100644 --- a/types/types.go +++ b/types/types.go @@ -261,7 +261,7 @@ type JournalEntry struct { Addr Address `json:"address"` // Balance tracks changes in the account Balance - Balance *big.Int `json:"balance,omitempty"` + Balance *big.Int `json:"-"` // Nonce tracks changes in the account Nonce Nonce *uint64 `json:"nonce,omitempty"`