From 8095408e1b00295a545acea48a4f19f4c9275d9e Mon Sep 17 00:00:00 2001 From: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> Date: Thu, 19 Feb 2026 19:15:04 -0500 Subject: [PATCH] initialize branch --- artifacts/program_methods/amm.bin | Bin 531316 -> 531284 bytes .../authenticated_transfer.bin | Bin 385820 -> 385820 bytes artifacts/program_methods/pinata.bin | Bin 389120 -> 389120 bytes artifacts/program_methods/pinata_token.bin | Bin 399748 -> 399748 bytes .../privacy_preserving_circuit.bin | Bin 512656 -> 512668 bytes artifacts/program_methods/token.bin | Bin 481736 -> 481736 bytes artifacts/test_program_methods/burner.bin | Bin 384384 -> 384384 bytes .../test_program_methods/chain_caller.bin | Bin 402076 -> 402076 bytes .../test_program_methods/changer_claimer.bin | Bin 387204 -> 387204 bytes artifacts/test_program_methods/claimer.bin | Bin 383088 -> 383064 bytes .../test_program_methods/data_changer.bin | Bin 380620 -> 380620 bytes .../test_program_methods/extra_output.bin | Bin 383204 -> 383180 bytes .../malicious_authorization_changer.bin | Bin 389456 -> 389432 bytes artifacts/test_program_methods/minter.bin | Bin 383144 -> 383144 bytes .../test_program_methods/missing_output.bin | Bin 383120 -> 383168 bytes .../modified_transfer.bin | Bin 385060 -> 385060 bytes .../test_program_methods/nonce_changer.bin | Bin 383160 -> 383184 bytes artifacts/test_program_methods/noop.bin | Bin 383052 -> 383028 bytes .../program_owner_changer.bin | Bin 383132 -> 383156 bytes .../simple_balance_transfer.bin | Bin 385180 -> 385156 bytes nssa/Cargo.toml | 2 +- nssa/core/src/account.rs | 3 +- nssa/src/state.rs | 1355 +---------------- programs/amm/Cargo.toml | 1 + programs/amm/src/full_tests.rs | 1344 ++++++++++++++++ programs/amm/src/lib.rs | 1 + 26 files changed, 1359 insertions(+), 1347 deletions(-) create mode 100644 programs/amm/src/full_tests.rs diff --git a/artifacts/program_methods/amm.bin b/artifacts/program_methods/amm.bin index 72bab16253543a981a14d10b0797cb2ca2a02bfd..e7f77c1a13118320a9e9289f6637b45748d35fd8 100644 GIT binary patch delta 12271 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 Y{o~qDE4%yGp~Ww2Z`ivR#Xmm%zvMxhDF6Tf delta 12334 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 diff --git a/artifacts/program_methods/authenticated_transfer.bin b/artifacts/program_methods/authenticated_transfer.bin index 5fd291d7a449df95c44261ee2a4988c48c088830..c7c93a81074f6a787005eafabafaba7ae20f4945 100644 GIT binary patch delta 8749 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 ZQBmFWn6Mo;Jtkk%Ub3Igjd}H{{{;aIgSh|z delta 8751 zcmZvgdwdl|mVi%p--6q2+#0{h(mykfT9C5%tXNv z)-a%n8h(JwuFMz&U8F$;eQ)o zPE~dJ`_0SWZ@#2h+otcU(vCYHSLts@?DjPxTP;(HL`2s$nfSFx!tkhcgf(54^>F>L zsH7_Mk7M?y^4$v@D&{-nskko+0A4xXX83$`^${$3=nohfB% zz%sZF-l6y)oD=du^HU-lJD3uQDbS=Iev1_*)8F-2?;k`yf*UJd2%ikecf&8Uplny( zlmS|;NE{OkQ3JA_HlOQu#7;kr<)N*Z4etrLek)vXZ{Vr3@Pu?z4lBbZ|A?oMN0i_Cd)zT_7-!H&XH> zr_E7)j%Kf8RN%ik|1vepA+v7B@(K9srBG%^(G-a>hIdeAFcD>V-bY;bGtTMArNl|nq(vI$aptBX2CU~{#)R>fNlAShVDUwWL~dHRfy-q+wL)? z?=_w$E8sNp%TyEeZ?4I{k-@@76DTV%xUZ6z!c}mt;xFJi=${

vf55rAh6HsC17t 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 delta 913 zcmZp8Al?8(EsQNpEzDb3W*!hWH?}Y|F*Px>Ff=eTGBGqZH!_{R<^anytP+8jSk$N2 z9Ax3ZExYd^3nw<&?Y9oH#IR$P@jS^=$B0d4I?z51DZQMWvRpkwYz~z<&2k#6#$Tsd z0+LSXIVP2O6a$+*i4T)$0C7Mw*5Mb%k-1DWG}X{1mp8W;(3;I zti~?<$Q*}H;~p(mrRk*?a5xGSSIUNFxI>R2KFZI`EPndJb1X{Jik$`+K*mg*?#m2tF<%$KL_wg diff --git a/artifacts/program_methods/pinata_token.bin b/artifacts/program_methods/pinata_token.bin index 51692ae193fff24e2cff7fa791961f2174460833..8b1bb8bda86644f4ef569ab5d684da3f218962c8 100644 GIT binary patch delta 1127 zcmaiyze_?<6vy#(Zm*#Tba*n4m7T%AAn`#s-t&sQ{~q8YsqA)$$xJ4m)7+)8nq+Zor+I@Wrc zXPpe@TVPT^R$8EkNYZ$LBcKQ_yuvLByeTU&*DRIFr=}uBBF-)41G)JIhh!S8{y-Yr z?~o@4do&`qKVX#>Uyr<8j&dwMw4q1(1`BbuaJ~bVl(4qTT>0FAnil^54_IZegO6R9 zrKH&D!T||x7TJE7xb6KXoRETz3fn@_gENvoCD{_1eK1JsZJxmMKFpDH_^TM163oB` zV-cAfKv^Tj{xxv$1-hDALj^7B%#g())agU}spD=+eK7w)Y#O(x=qD5+D9i-^y>B=s n*A9|%wX@$S%#9TN_r7$Ev<;fCcEx~amHS>5#vlu0W-k8$3REQc delta 1121 zcmaiyze_?<6vxrd zbn@sBIQRyQRFKphDri|_x+o9fmcDUhI-R%Fw~8L5rg3}9{DdyZu1wJ1{efdLwlwA{ im7_9YVWen&_-AXRs_eW{)JDmDW!&r17({8zjO9PerXbt^ diff --git a/artifacts/program_methods/privacy_preserving_circuit.bin b/artifacts/program_methods/privacy_preserving_circuit.bin index 28bbaba42638e05b19791d4d07cff2c7404e9ac7..f7ba63322ed44495bccd5fce5fec1d4f4f694230 100644 GIT binary patch delta 9776 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 delta 9781 zcmZvie|%SC`@paB+4*d%rrIoG;d4G`Uq;c&9#V^~_GL6$nTlunr3h0i>FY;1>la~Z zJh4%rSJn9aU%`=Qd|uT{lTGxWqUQe!AA=)`i+VF3d2JNWhL`&NmOOifCh6-V z(wHC;3Tcv@r%7{DL^8D)PlD$mptTaP3SJ!GU*R%qlw&k!&TU5kCB_&nZ`;1^t~=e+k@-yi_&+w5v2Z2)9){1RnCNDV<|% z$ul$*(%=QmPPiq&C0A>50y56YC#3LxA7WfWsIOx1FSK>staxxkbHHU10u=UP)nxNQG0Q17l;PZN-DEcC6n16~r~B;55$r5`U3V5M4Y zA3=y?g+j*)uyY_BKD$(t8s>Xe91710aKg=+jDn-C5+Qp*i9S`cGDveZ$%Zs3DVZFz z;jIj5Ry+pYlH~Vi_tKBC4HiZmXr3B7_lNb5h+G1}Vq<2lQ-WsY&N7~hSl@su;Q;c{J9xO&OKND`xZPz14g2f-1$uHMDiDyTtTg6! z+)4k{O2EsuF+$&yppCM%(R#bE)#olYaK9lF)%Zu@+R28iuw#!;;pG92jAa9`=Y_lA zO#xmFH^W6ro<5EZO)+GN;<0choEu|HR?(3Bpdm}ufM_|F%gg>XF&f?!;3ZB!BNT%{k{di4sU-1oc9G(w*7VJ3zi%%uqU5j6=$zwE(3JhqNf<;+y5DPdaPk4|l zO}}$Y9lo+U|4x1Lh^;g?Kjeq!8I~rkUNt3A4Z8_$2eXVjZ62H)xIK2kLC>C5LI1;k z_>Z>7mpKu(@eacJ5kEp&-%Hp(;jdc`>#(yw$6=qqDR4w_@B45da&r`qg^OXY|2eoz zV1Cm5C&{JxP z2Tx|cm;9>Wj<5Ujw!v9GTax}Tn+_~E2u}6~NDVw=F6WB)bHd=PS!BP*Oo^b76SWnO za&DhB;x}aL$1uuL(>;eye?K@G`6X)nZ1^R3xXY)84pWz_^{>$T< zv|nJzn3#M^#?ep_D5Kwi>zDg=;y>Uz*ju2-927vIJa*<->Mi(U`kjpCSmGBrFEBp0 zN|WEQw5o39L3ld~4R^;Ugk)WHxBK+9)@D3Vz6`l45$R9h!lnMf90_N`dCD*!z(Efs zJ;}xb9xH^K(ZdUoN8qM_ULV3^R>b!ek_q3jU0^l8`j5%_zSK|eJlQLcR3Dwf+oYR4 z;6Z&{8|_Vd-6IqM-KIT_ch@pkor{0MweR_7vrn}qzr7LPq%>9=v-M@E(`in5({B#j z`)Jmzl~1wtb%qouAM`+6Q-i;iuWB^u!935V<}>&xAZHZZ6yU{h3-i6g)OeQ5<9$O; zDEU+2fDc3RzMWd7|CrM4hD8L~+y13d4Y$Bv5Ej*OkHg+2^SIsZIemd<4SAk%pZVAC zBKQQHu6(f_p0U~w)(#7>-!A`lD2KCl8p0*u`tDV@it!h?!5Wh9VR^^bqiZce=krLJ zK*K~Pc#77;wO{xS(H4@2{0UM3U�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 C!hwze delta 556 zcmX@HS@y(c*@hOz7N!>F7M2#)Eo@SJ!Y0OMMyBRK(!kuvz}&*j+}LEgB0rnDw2@v; zPFb#=AvOhuEo{Qm=SQ+BOkc#uwoVd@5{CFFKNI8Wy3bh@r#tkp2~D5F&(?v{vgvUG zY@9e{WsHsSxCP``8DkUNDz*u-bueQ!9N~>~B5V#=l_-j`8DN*-XVaM8Bg)2sTlPFY zS!qMuE(S$_2EGW`ULeM1%81qGkK$~?+fR$LNn-ahD72=_Nn>|*yQMVSc1vmYemejx Cy?<^1 diff --git a/artifacts/test_program_methods/burner.bin b/artifacts/test_program_methods/burner.bin index e2c3bdf1bd1e53c31edcbdbc9c912f5bfbf6756d..6e6d6670229e7c576fa0da98f79e47bb7a62bede 100644 GIT binary patch delta 733 zcmZqJE#3e`EsQNpEzDb3>XE}vc;=&^q#Z|B*?@`@3wX3jk)C^y3a`#;psB_SiWGj9q1=@DI?q#fI>XE}vc;=&^q#Z|B*?@`@3wX3jk)C^y3a`#;psB_SiWGj9q1=@DI?q#fI diff --git a/artifacts/test_program_methods/chain_caller.bin b/artifacts/test_program_methods/chain_caller.bin index f02b062100bfd1811def5d207571476745223dc0..50284178e96a113a6e1fb9052be03edc5d7f6258 100644 GIT binary patch delta 821 zcmbPpRASCiiG~)&7N!>FEi9*hi5MChSsIyJn3$Vd8X6iH7@Ap_Fid9@XHl2Z%gHIr z)x#yPCT(blQ^oeg-zL3sW6{SY zp&?~~+t`%FEi9*hi5MH2SXdewT3VVLS{Rubm>U`xF-&I^XHl2Z%gHIr z)x#yPCT(blQ^oeg-zL3sW6{SY zp&?~~+t`%c#uV1 z+R#8RC#Nh|51USi0%M#Cwx8R-Gp9=*W;rE^#Wf7^ zQGON%(*+(fyG{RKz$!RB^ax7=RvS(nVL66XV&PGiV5}17&#|~n_ddoVj#c)cI7_f3 zZU;X+#*&6r-$PlJI6V3;9%r${st*$E7PxJUKY_!>!tX2+(?6VGiN$TM5gv2F78@Jl zwiv9y#00;B>At5}*l{{wdLLfd^LS+iPP1T5Zs0^EZD@|)VbaEg(z*%mwBG*lG|Tpn Jr&%Y<002^5<)8on delta 886 zcmZpc#uV1 z+R#8RC#Nh|51USi0%M#Cwx8R-Gp9=*W;rE^#Wf7^ zQGON%(*+(fyG{RKz$!RB^ax7=RvS(nVL66XV&PGiV5}17&#|~n_ddoVj#c)cI7_f3 zZU;X+#*&6r-$PlJI6V3;9%r${st*$E7PxJUKY_!>!tX2+(?6VGiN$TM5gv2F78@Jl zwiv9y#00;B>At5}*l{{wdLLfd^LS+iPP1T5Zs0^EZD@|)VbaEg(z*%mwBG*lG|Tpn Jr&%Y<000Cu=vV*% diff --git a/artifacts/test_program_methods/claimer.bin b/artifacts/test_program_methods/claimer.bin index c7885bbaf97ad7e10744ed40392b42ff5f232762..d08ae5df3b81deab8c534d7e3a7357ecffe8a1f2 100644 GIT binary patch delta 9558 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 N+RNtt(P1w?`F|w&EK&df delta 9593 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 diff --git a/artifacts/test_program_methods/extra_output.bin b/artifacts/test_program_methods/extra_output.bin index c149d5724c9e9fe3e54a1a3b73c052783707ff03..3b3e2ba7dd2b7cf200e55ed245465641db5d7a22 100644 GIT binary patch delta 9618 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 delta 9615 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 Wx?7oJx4J)Hr5!R;MufdI|9=6um^8cq diff --git a/artifacts/test_program_methods/malicious_authorization_changer.bin b/artifacts/test_program_methods/malicious_authorization_changer.bin index 2aa1b51857f9f2101b42a855f92d62b66457f4d2..ff9f1d893d7211006052cec903199c2cd0c29ed0 100644 GIT binary patch delta 9796 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 HFE9TeObL1y delta 9779 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 diff --git a/artifacts/test_program_methods/minter.bin b/artifacts/test_program_methods/minter.bin index 9b454fc24a0c56c4dfe8c990b517e3cff2785b83..41f1b4b2745f70123fe8ebaae6c5b6f3148e0480 100644 GIT binary patch delta 769 zcmZ3nQGCTl@rD-07N!>FEi9{62^$$%8X6j!n3-Cd8W@;Z7#UlbOy9eTWgb?EjjLHS zq)qg4a>{b`46*41DlovNbNiRoEPQO(WTpePs86@q#KM79HhdGyX{-_#PqGM4@4LyO zFg;^4%X+LzKqkwW5OA)Bv>|@~Xh<92Q2=+wcD1c6uNkqrLuETlHC74lLY81DJcb(< zvm{Kf-@(F;RX0%9VY-1NEAR9N>MVkI%-JrulSLl8(?CHaZG^`O;MiHS3rFmLW#8eE o)sQwLV7QD4f$#@LAt49Km>A=>W!h2}nRdfHEZYtDu$IdJ02GFEi9{637c9NnOPc{n46fHSO6(=BU6j%dsnf{!z!_HHH(I{ ziC#`lS+1TTHl08P2H13N|FW8ej}4p5bf6aX={B2KIIzlwZ(=zuh+)(8^CwwEr}y1t zQJ9{wnPojzogi~%Ob9quL)s9(Z!{zga4A4IV!PT_me-6}U7@m_r5dY*cOgr#6fUEI zabQ@?k}$n~2Maq^-9TA~=?0Rlywe}3vk2lbXS?7|7J2MW0|k(@5gsRiV`j}R95Dly reTPR@L)wgh;W8!!LLV4`gd8YiVvO6CX-ipT+70)xY&YD)S}p?s2(Qa+ diff --git a/artifacts/test_program_methods/missing_output.bin b/artifacts/test_program_methods/missing_output.bin index eb41b0afca75ceaf72888712d56583a87705c53d..338f646a5251007f4039d6b1b4eb613d90ddfb22 100644 GIT binary patch delta 9670 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 delta 9586 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 delta 8739 zcmZvhdw3PqwZPY$IR}D9k|4nVL1qr1ARq|@K?xc#C}_ZdL0%C8gohG=i%=hM8Bjsg zD5*k|N-AkDTD($-*Wh43lvu%{2Cy|=k!QpZkfMZVL9zBXXZB=<`(6Iw`|Y*&dhNB> z-eoC}*IbJ0Pu(iWCPH zjD}P0^%Wk3t1;MG8643dQVXXlu7Vrku8O0_Sl`8$zXWH%Gd0IyOOxiuao`3+%G83z zaK?>>Y*G9v{CL2D`0qrHcQYg$Q=rL7xPDkv5}5B~tmg@lv+&i5XTymEGtd(Q!_kWFrqN zy(MsYPeamRXRG$YHE_J*=no=$VU^k5az6ucH~Xpl3!IkbM}GW_$X{`2iZXCh>9l>J z!%2^v#ZI~*MN02arK9(U)(-mDDUqGG7*em?`{Oy0zPV9pu2#Qr9_@YE2PJQRK_nCT zRZ9Mo-SmV1noNM7Uyz zU+3H5tpQH^7rP6)b+5^raMs;^*&BA3y3n4mH7m)Q~#GQ;DeLem|Y- z;FGZDM+2NSjP$C&+9qidpXXQc1b98{&Ho*|#b-+nGjKVe&}^kinLk0M!WZu`B(s^D z$yebVs?fke=lu0(qerjjp%%iui4e}(&@zaYlfhU7ezRn-ucjMzX} za_mS$Xivy$Y_5rMzh77#<1h?6^PDZsg_i_)DO?46jU=gsCfTF?!YzUyf56YgMmYZg zKht$^<`_fvy810?b(JQq#~PBW3=V}01H2fng6ow0U3k?vpMQYokLNtAt?6;KCgl?h z>96=-lLMtAPlWE&CYP>05!y4keKUL>6BTM8w(0qBGnmmB{|;Uh=zWLaU=!%b zUe288dp-j$gHvOnYO=}R@sChK#QOLbkt)XLtMQgt2v6o%D;@{84)8j-Gwk)$({NgV zZ`asUI7i%?Spjc{*DF2)uYjFmWeY6HWFLyA7_vc4cmvKD>-UN8;G6*W&^1Y!>fh%J z;T3S_kZZ6%*Vb0%d&h4foI1`w&L6-Vrg>euk0uEbP3l?Twa-y-A^ZRiImc}^ToZ6$ zuN^rP>J_pUwAQ5fR~S|evJuXmM`U5wkx)l6F^gM5$v?P(%#M#rH>Fo@)Z`qFd5#W- z(~x`o3|t?Oe+;jmO@DLsS>lv=x!*D6PB?2qRFaf|jP;O=D(!ndw9VR2e~Povt9D>D^Qss6r|c}e z6V6hJ7}NdAepUv@2m0IBa3OwsFSK@CIeCFNCcx)>4vB6rxDZMRS@YVHkY^2boHaQJ z=Lh(%R2+r9e)bq#v)p&|4R}#teo_Z^Fu+g3waoX{zXfmi*O%&-Lf<4+Uw`GU>?%Ef zDKtr&Wsm+bH0NsV9eYPa@1>_dm8MDKOW5W>JDYI)&cSC0B4y>XRwUQRnv_*DTtg>c?P-`wl)64ra| z!sPK$_p%`umHwr0;7$t3M|N_&zAZlelL4Bno9Z9mt25~zg}&nIfgDfd-suY2k+%9; z&8q1~U~l++rwu)OJ=|Iaa5r3u9<7+G8yhM z&G+NK;7p&VNCN{E0Y|&u#&P~{e?u0)W&Q%$0*_;UwleS|+z{YQ5|P7v@2ap$m$ldD zXm8o)+v_W}k>|;a@jr%?sD$Q|m$E|z$-VHfzizxet&4s*VjUf!$>*#qR_kVu;_m)mLryB* z2v^VY*EPbKMSj=peLpuHa<7ZdhYP`+?8(wE zyX&V$b{Ve8*kjSyn_de=WEPzJwcl*Y-~#;cn%q7(8*cCFl~m$d!FtL9I}w>@C->Ah zg{?K@p=3Y#Rrx;-uRCbSapiB{Z2UW9$WT>JPrd9U;3I_;wRL+n?PYN&_X!z8v;-c{s!)R#OIxG|8IT% z5zeVMWL-=@Z=L4|t&st*o23jx!BImBl)^v4$8oT&itq%i;edB?d){-U!yo-09)ItZ z^3y>M)01AXhxE}C^g&zM`O0I4G%CY~Mr-m+1EsDq@%9)Tffp%mfD4(Qqd2*A^)0l< zzmMcGINMLqI(u|KeUfgqVEh2%US;OM$0vCe5t5Z~;v9e7uyLHs6aFJ~B|H~SQ|6kF zr*Z-n^*mgI{+7s{YjhW!ddiR`?)=`;FoD(+xZk?vbFs6ahgwhs2Nv)&n>K(>G5O{P z$irzad{>cNMcf6AJUCRIrorVH+OFhh&{Gr$q|bwtXn^O#2JCgD&34~``dWSRT@&#q zFz;D-(OG_GE4|y{vF8kVMje&mldv$$isy5|DUV@J~JuDD5&rKb*8Km#Zn>lq?l?wViyQzOA{n@gE{HQ%vcvmiIz^ zT%y_3!N#zzCg4VEI@aD+$W;e@kuuwh+^vfUzf{D0s)KcK z`AcT(W^(TSf5PDLjdwTHZ*&uOkbW^aC3KO8st{dw%q z$EJu%SkGUv0|(8fhVf^3?kA?4R2%d56I?BUx;O({%cBxe`ujY|%X`1s^y_SZeSVET zDPko*rb*jpqe8f`JdK4@VARHV4ctD!hv3w}e3Lu>9Co}`JQZ#ekiP+U46OeSzTRg` zdf;e6V8LwI^e4#E3pI%bIN?8eu)^de=HN*9+5o=-C&6AoU&2OUead2|ftjkK*rWcS zw`y)KBsP<1LNJE;Q^2w6+;F57(94&H1;vTIX>^fFT+vf4*vvK{f6ID ziU%&^IKCW}vC6Im7sH<`{t(W8B`OW>eCKCFq)Oiw8kF@Y88o9ZUm4y97nS)APe-r_ zZl@HTg5QC?Cq}j%vGqGNZM!{Wi*7a3eztdfpl{N(<@SQV@HXd5beHY=sfaeCH2G7W zx+Cn(pK_e7%7c8r`m_7QZY7$`J0!Axk13V7;qVqX|1&doO*s7UVUdiHZd-P^0Uo-P zCpm68d=8#@qkFA5+@(&Wb02=GQ-%(A`-acFU81pT6t*Ovfy!UgN0fq9aM2m}3F<7^ z39sM66I;or9N`OI755FL;>bhaV&DZc_F!=MR=DvOx2zpL4A;?zs@3|!dICsy@3U6I z?w20rdvC2N293~JaAN~s{N6WXN5J7_-|@vS(|toaynv2h*4_QR=5Q^1yumHyB-%{o zDZT)%HY87T^;N?eFZ%OK8u`S?{9GJLvRJT#fdi$6R4NaLpB6buhs##{DqQ!G8GEEV z20wwrub8nf=?-^4!#C0ZZ$2wB_HSGvD&+;|SijedJ;t5+b1vZ^TW*j+%NdCL$fsH+ zIBzhAhr<`&CxUpFck7hq40nMe-xWt`=DAY!rm6{>p%csn6byBGe7Bi9xq4PGUf2SaASih^RXX`U^xSquW{Rkvmmo0 zw+mHVtK_f2wVaYN#XrMEFZ-Ntppf}#O1=#a)<{Q_+c;1o7QAztDVFnH$T7Hufx0q2 zQYr=AX>i3bdlZxZ7Os4PW2uVjj!w+4p-5FkC9tuZW2N-%gx5W9NR?XOwllv(*rEc( zqu`1orX?v#;YtR!)SFVFCM0(u#q4>J;#_!UY|mVWehudaxE5aVC-Fd=gOT$ukp=fM5c?3K_(5mFG53M#oa+j>4tD29$@jNw^2Hi5NPtPaO9tNI^#8!+ za^Mag%Ug`tO;olko>@R$+(ZTx?|{$IDT~ypSvvX3lz$5c z&-sukY@udKky`%*oDpYAs$y#s1M^$bN>vIwOr>bTrYuoB4sJ|vTBV!fwQx8>qfrXF z6{4`28GF7v5p9Go!zF5d_i6Nz=5#v6Z^MEE87^DWeLBae1y!pengMUP+IL_jT-(+Z zLn$}~Zy}}5Id+a^`3#=1I9ROYk37T=upvBPRMF`Vld)bf3mgY$I*h)|*nIZCl7X~# zey_d=uY$)ag;}%MbJ)9#o`;JAMRgKx-QI7-w~^}&aGmE6e3JRzv8;!SQ^}wsx9}+W z5q_~TutF_34$tgJL@LGkv+>yQJVrU3*~N^#y`6{-!u2UpsZkMMH-|lkV+N4t!CRBu z2Zu9%75sPtZ*?*ryZ_(kCs^=unK#QoXBwYsw-% zJ~#%}!-?z37=PP!IDG*pWeY{90(=&(blJWC_cM_Co^DOHcE_p!IH05iYmSf2D^HU3<%|x1{$@>zkg@zh7Ga^xo-d>3!{M-VM*v{y#}+ cK~=b&{e~T$zTUp7AhKA~mf6ouj;vYyZ~U`v2mk;8 diff --git a/artifacts/test_program_methods/nonce_changer.bin b/artifacts/test_program_methods/nonce_changer.bin index e1f1284efaf4fa40b0c70954c6382226489a0484..0d9da91be913f9611966cefc265fa78838b30786 100644 GIT binary patch delta 9617 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 Nj+pHxMm)FR{{Z~nIkW%( delta 9617 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 A*Z=?k delta 9664 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 SpL%28*6z3792)V~w0{AJH(2Qa diff --git a/artifacts/test_program_methods/program_owner_changer.bin b/artifacts/test_program_methods/program_owner_changer.bin index 06e83e8acd6cae50e50eb16220a023d79b7b7c82..596032e3407d0da4b1acd87e91124f182eb14664 100644 GIT binary patch delta 9637 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 b;_GHj(>Gi(MyE2@!B@3k3~hYKD^LC(%nUoc delta 9608 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 delta 9680 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 Uc&mP;fB!P=RqKagfu+y?AF|m|bN~PV diff --git a/nssa/Cargo.toml b/nssa/Cargo.toml index fe74b7a3..64060447 100644 --- a/nssa/Cargo.toml +++ b/nssa/Cargo.toml @@ -24,7 +24,6 @@ risc0-binfmt = "3.0.2" [dev-dependencies] token_core.workspace = true -amm_core.workspace = true test_program_methods.workspace = true env_logger.workspace = true @@ -34,3 +33,4 @@ test-case = "3.3.1" [features] default = [] prove = ["risc0-zkvm/prove"] +test-utils = [] \ No newline at end of file diff --git a/nssa/core/src/account.rs b/nssa/core/src/account.rs index 9bcdcd4b..282f7fe3 100644 --- a/nssa/core/src/account.rs +++ b/nssa/core/src/account.rs @@ -11,6 +11,7 @@ use crate::program::ProgramId; pub mod data; pub type Nonce = u128; +pub type Balance = u128; /// Account to be used both in public and private contexts #[derive( @@ -18,7 +19,7 @@ pub type Nonce = u128; )] pub struct Account { pub program_owner: ProgramId, - pub balance: u128, + pub balance: Balance, pub data: Data, pub nonce: Nonce, } diff --git a/nssa/src/state.rs b/nssa/src/state.rs index f5ec2b46..ec9dfe91 100644 --- a/nssa/src/state.rs +++ b/nssa/src/state.rs @@ -306,19 +306,26 @@ impl V02State { } } + #[cfg(test)] +impl V02State { + pub fn force_insert_account(&mut self, account_id: AccountId, account: Account) { + self.public_state.insert(account_id, account); + } +} + #[cfg(test)] pub mod tests { use std::collections::HashMap; - use amm_core::PoolDefinition; + use token_core::{TokenDefinition, TokenHolding}; + use nssa_core::{ Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey, account::{Account, AccountId, AccountWithMetadata, Nonce, data::Data}, encryption::{EphemeralPublicKey, Scalar, ViewingPublicKey}, program::{PdaSeed, ProgramId}, }; - use token_core::{TokenDefinition, TokenHolding}; use crate::{ PublicKey, PublicTransaction, V02State, @@ -533,9 +540,7 @@ pub mod tests { } impl V02State { - pub fn force_insert_account(&mut self, account_id: AccountId, account: Account) { - self.public_state.insert(account_id, account); - } + /// Include test programs in the builtin programs map pub fn with_test_programs(mut self) -> Self { @@ -2328,1346 +2333,6 @@ pub mod tests { )); } - struct PrivateKeysForTests; - - impl PrivateKeysForTests { - fn user_token_a_key() -> PrivateKey { - PrivateKey::try_new([31; 32]).expect("Keys constructor expects valid private key") - } - - fn user_token_b_key() -> PrivateKey { - PrivateKey::try_new([32; 32]).expect("Keys constructor expects valid private key") - } - - fn user_token_lp_key() -> PrivateKey { - PrivateKey::try_new([33; 32]).expect("Keys constructor expects valid private key") - } - } - - struct BalanceForTests; - - impl BalanceForTests { - fn user_token_a_holding_init() -> u128 { - 10_000 - } - - fn user_token_b_holding_init() -> u128 { - 10_000 - } - - fn user_token_lp_holding_init() -> u128 { - 2_000 - } - - fn vault_a_balance_init() -> u128 { - 5_000 - } - - fn vault_b_balance_init() -> u128 { - 2_500 - } - - fn pool_lp_supply_init() -> u128 { - 5_000 - } - - fn token_a_supply() -> u128 { - 100_000 - } - - fn token_b_supply() -> u128 { - 100_000 - } - - fn token_lp_supply() -> u128 { - 5_000 - } - - fn remove_lp() -> u128 { - 1_000 - } - - fn remove_min_amount_a() -> u128 { - 500 - } - - fn remove_min_amount_b() -> u128 { - 500 - } - - fn add_min_amount_lp() -> u128 { - 1_000 - } - - fn add_max_amount_a() -> u128 { - 2_000 - } - - fn add_max_amount_b() -> u128 { - 1_000 - } - - fn swap_amount_in() -> u128 { - 1_000 - } - - fn swap_min_amount_out() -> u128 { - 200 - } - - fn vault_a_balance_swap_1() -> u128 { - 3_572 - } - - fn vault_b_balance_swap_1() -> u128 { - 3_500 - } - - fn user_token_a_holding_swap_1() -> u128 { - 11_428 - } - - fn user_token_b_holding_swap_1() -> u128 { - 9_000 - } - - fn vault_a_balance_swap_2() -> u128 { - 6_000 - } - - fn vault_b_balance_swap_2() -> u128 { - 2_084 - } - - fn user_token_a_holding_swap_2() -> u128 { - 9_000 - } - - fn user_token_b_holding_swap_2() -> u128 { - 10_416 - } - - fn vault_a_balance_add() -> u128 { - 7_000 - } - - fn vault_b_balance_add() -> u128 { - 3_500 - } - - fn user_token_a_holding_add() -> u128 { - 8_000 - } - - fn user_token_b_holding_add() -> u128 { - 9_000 - } - - fn user_token_lp_holding_add() -> u128 { - 4_000 - } - - fn token_lp_supply_add() -> u128 { - 7_000 - } - - fn vault_a_balance_remove() -> u128 { - 4_000 - } - - fn vault_b_balance_remove() -> u128 { - 2_000 - } - - fn user_token_a_holding_remove() -> u128 { - 11_000 - } - - fn user_token_b_holding_remove() -> u128 { - 10_500 - } - - fn user_token_lp_holding_remove() -> u128 { - 1_000 - } - - fn token_lp_supply_remove() -> u128 { - 4_000 - } - - fn user_token_a_holding_new_definition() -> u128 { - 5_000 - } - - fn user_token_b_holding_new_definition() -> u128 { - 7_500 - } - } - - struct IdForTests; - - impl IdForTests { - fn pool_definition_id() -> AccountId { - amm_core::compute_pool_pda( - Program::amm().id(), - IdForTests::token_a_definition_id(), - IdForTests::token_b_definition_id(), - ) - } - - fn token_lp_definition_id() -> AccountId { - amm_core::compute_liquidity_token_pda( - Program::amm().id(), - IdForTests::pool_definition_id(), - ) - } - - fn token_a_definition_id() -> AccountId { - AccountId::new([3; 32]) - } - - fn token_b_definition_id() -> AccountId { - AccountId::new([4; 32]) - } - - fn user_token_a_id() -> AccountId { - AccountId::from(&PublicKey::new_from_private_key( - &PrivateKeysForTests::user_token_a_key(), - )) - } - - fn user_token_b_id() -> AccountId { - AccountId::from(&PublicKey::new_from_private_key( - &PrivateKeysForTests::user_token_b_key(), - )) - } - - fn user_token_lp_id() -> AccountId { - AccountId::from(&PublicKey::new_from_private_key( - &PrivateKeysForTests::user_token_lp_key(), - )) - } - - fn vault_a_id() -> AccountId { - amm_core::compute_vault_pda( - Program::amm().id(), - IdForTests::pool_definition_id(), - IdForTests::token_a_definition_id(), - ) - } - - fn vault_b_id() -> AccountId { - amm_core::compute_vault_pda( - Program::amm().id(), - IdForTests::pool_definition_id(), - IdForTests::token_b_definition_id(), - ) - } - } - - struct AccountForTests; - - impl AccountForTests { - fn user_token_a_holding() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::user_token_a_holding_init(), - }), - nonce: 0, - } - } - - fn user_token_b_holding() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::user_token_b_holding_init(), - }), - nonce: 0, - } - } - - fn pool_definition_init() -> Account { - Account { - program_owner: Program::amm().id(), - balance: 0u128, - data: Data::from(&PoolDefinition { - definition_token_a_id: IdForTests::token_a_definition_id(), - definition_token_b_id: IdForTests::token_b_definition_id(), - vault_a_id: IdForTests::vault_a_id(), - vault_b_id: IdForTests::vault_b_id(), - liquidity_pool_id: IdForTests::token_lp_definition_id(), - liquidity_pool_supply: BalanceForTests::pool_lp_supply_init(), - reserve_a: BalanceForTests::vault_a_balance_init(), - reserve_b: BalanceForTests::vault_b_balance_init(), - fees: 0u128, - active: true, - }), - nonce: 0, - } - } - - fn token_a_definition_account() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenDefinition::Fungible { - name: String::from("test"), - total_supply: BalanceForTests::token_a_supply(), - metadata_id: None, - }), - nonce: 0, - } - } - - fn token_b_definition_acc() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenDefinition::Fungible { - name: String::from("test"), - total_supply: BalanceForTests::token_b_supply(), - metadata_id: None, - }), - nonce: 0, - } - } - - fn token_lp_definition_acc() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenDefinition::Fungible { - name: String::from("LP Token"), - total_supply: BalanceForTests::token_lp_supply(), - metadata_id: None, - }), - nonce: 0, - } - } - - fn vault_a_init() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::vault_a_balance_init(), - }), - nonce: 0, - } - } - - fn vault_b_init() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::vault_b_balance_init(), - }), - nonce: 0, - } - } - - fn user_token_lp_holding() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_lp_definition_id(), - balance: BalanceForTests::user_token_lp_holding_init(), - }), - nonce: 0, - } - } - - fn vault_a_swap_1() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::vault_a_balance_swap_1(), - }), - nonce: 0, - } - } - - fn vault_b_swap_1() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::vault_b_balance_swap_1(), - }), - nonce: 0, - } - } - - fn pool_definition_swap_1() -> Account { - Account { - program_owner: Program::amm().id(), - balance: 0u128, - data: Data::from(&PoolDefinition { - definition_token_a_id: IdForTests::token_a_definition_id(), - definition_token_b_id: IdForTests::token_b_definition_id(), - vault_a_id: IdForTests::vault_a_id(), - vault_b_id: IdForTests::vault_b_id(), - liquidity_pool_id: IdForTests::token_lp_definition_id(), - liquidity_pool_supply: BalanceForTests::pool_lp_supply_init(), - reserve_a: BalanceForTests::vault_a_balance_swap_1(), - reserve_b: BalanceForTests::vault_b_balance_swap_1(), - fees: 0u128, - active: true, - }), - nonce: 0, - } - } - - fn user_token_a_holding_swap_1() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::user_token_a_holding_swap_1(), - }), - nonce: 0, - } - } - - fn user_token_b_holding_swap_1() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::user_token_b_holding_swap_1(), - }), - nonce: 1, - } - } - - fn vault_a_swap_2() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::vault_a_balance_swap_2(), - }), - nonce: 0, - } - } - - fn vault_b_swap_2() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::vault_b_balance_swap_2(), - }), - nonce: 0, - } - } - - fn pool_definition_swap_2() -> Account { - Account { - program_owner: Program::amm().id(), - balance: 0u128, - data: Data::from(&PoolDefinition { - definition_token_a_id: IdForTests::token_a_definition_id(), - definition_token_b_id: IdForTests::token_b_definition_id(), - vault_a_id: IdForTests::vault_a_id(), - vault_b_id: IdForTests::vault_b_id(), - liquidity_pool_id: IdForTests::token_lp_definition_id(), - liquidity_pool_supply: BalanceForTests::pool_lp_supply_init(), - reserve_a: BalanceForTests::vault_a_balance_swap_2(), - reserve_b: BalanceForTests::vault_b_balance_swap_2(), - fees: 0u128, - active: true, - }), - nonce: 0, - } - } - - fn user_token_a_holding_swap_2() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::user_token_a_holding_swap_2(), - }), - nonce: 1, - } - } - - fn user_token_b_holding_swap_2() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::user_token_b_holding_swap_2(), - }), - nonce: 0, - } - } - - fn vault_a_add() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::vault_a_balance_add(), - }), - nonce: 0, - } - } - - fn vault_b_add() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::vault_b_balance_add(), - }), - nonce: 0, - } - } - - fn pool_definition_add() -> Account { - Account { - program_owner: Program::amm().id(), - balance: 0u128, - data: Data::from(&PoolDefinition { - definition_token_a_id: IdForTests::token_a_definition_id(), - definition_token_b_id: IdForTests::token_b_definition_id(), - vault_a_id: IdForTests::vault_a_id(), - vault_b_id: IdForTests::vault_b_id(), - liquidity_pool_id: IdForTests::token_lp_definition_id(), - liquidity_pool_supply: BalanceForTests::token_lp_supply_add(), - reserve_a: BalanceForTests::vault_a_balance_add(), - reserve_b: BalanceForTests::vault_b_balance_add(), - fees: 0u128, - active: true, - }), - nonce: 0, - } - } - - fn user_token_a_holding_add() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::user_token_a_holding_add(), - }), - nonce: 1, - } - } - - fn user_token_b_holding_add() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::user_token_b_holding_add(), - }), - nonce: 1, - } - } - - fn user_token_lp_holding_add() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_lp_definition_id(), - balance: BalanceForTests::user_token_lp_holding_add(), - }), - nonce: 0, - } - } - - fn token_lp_definition_add() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenDefinition::Fungible { - name: String::from("LP Token"), - total_supply: BalanceForTests::token_lp_supply_add(), - metadata_id: None, - }), - nonce: 0, - } - } - - fn vault_a_remove() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::vault_a_balance_remove(), - }), - nonce: 0, - } - } - - fn vault_b_remove() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::vault_b_balance_remove(), - }), - nonce: 0, - } - } - - fn pool_definition_remove() -> Account { - Account { - program_owner: Program::amm().id(), - balance: 0u128, - data: Data::from(&PoolDefinition { - definition_token_a_id: IdForTests::token_a_definition_id(), - definition_token_b_id: IdForTests::token_b_definition_id(), - vault_a_id: IdForTests::vault_a_id(), - vault_b_id: IdForTests::vault_b_id(), - liquidity_pool_id: IdForTests::token_lp_definition_id(), - liquidity_pool_supply: BalanceForTests::token_lp_supply_remove(), - reserve_a: BalanceForTests::vault_a_balance_remove(), - reserve_b: BalanceForTests::vault_b_balance_remove(), - fees: 0u128, - active: true, - }), - nonce: 0, - } - } - - fn user_token_a_holding_remove() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::user_token_a_holding_remove(), - }), - nonce: 0, - } - } - - fn user_token_b_holding_remove() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::user_token_b_holding_remove(), - }), - nonce: 0, - } - } - - fn user_token_lp_holding_remove() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_lp_definition_id(), - balance: BalanceForTests::user_token_lp_holding_remove(), - }), - nonce: 1, - } - } - - fn token_lp_definition_remove() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenDefinition::Fungible { - name: String::from("LP Token"), - total_supply: BalanceForTests::token_lp_supply_remove(), - metadata_id: None, - }), - nonce: 0, - } - } - - fn token_lp_definition_init_inactive() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenDefinition::Fungible { - name: String::from("LP Token"), - total_supply: 0, - metadata_id: None, - }), - nonce: 0, - } - } - - fn vault_a_init_inactive() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: 0, - }), - nonce: 0, - } - } - - fn vault_b_init_inactive() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: 0, - }), - nonce: 0, - } - } - - fn pool_definition_inactive() -> Account { - Account { - program_owner: Program::amm().id(), - balance: 0u128, - data: Data::from(&PoolDefinition { - definition_token_a_id: IdForTests::token_a_definition_id(), - definition_token_b_id: IdForTests::token_b_definition_id(), - vault_a_id: IdForTests::vault_a_id(), - vault_b_id: IdForTests::vault_b_id(), - liquidity_pool_id: IdForTests::token_lp_definition_id(), - liquidity_pool_supply: 0, - reserve_a: 0, - reserve_b: 0, - fees: 0u128, - active: false, - }), - nonce: 0, - } - } - - fn user_token_a_holding_new_init() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_a_definition_id(), - balance: BalanceForTests::user_token_a_holding_new_definition(), - }), - nonce: 1, - } - } - - fn user_token_b_holding_new_init() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_b_definition_id(), - balance: BalanceForTests::user_token_b_holding_new_definition(), - }), - nonce: 1, - } - } - - fn user_token_lp_holding_new_init() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_lp_definition_id(), - balance: BalanceForTests::user_token_a_holding_new_definition(), - }), - nonce: 0, - } - } - - fn token_lp_definition_new_init() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenDefinition::Fungible { - name: String::from("LP Token"), - total_supply: BalanceForTests::vault_a_balance_init(), - metadata_id: None, - }), - nonce: 0, - } - } - - fn pool_definition_new_init() -> Account { - Account { - program_owner: Program::amm().id(), - balance: 0u128, - data: Data::from(&PoolDefinition { - definition_token_a_id: IdForTests::token_a_definition_id(), - definition_token_b_id: IdForTests::token_b_definition_id(), - vault_a_id: IdForTests::vault_a_id(), - vault_b_id: IdForTests::vault_b_id(), - liquidity_pool_id: IdForTests::token_lp_definition_id(), - liquidity_pool_supply: BalanceForTests::user_token_a_holding_new_definition(), - reserve_a: BalanceForTests::vault_a_balance_init(), - reserve_b: BalanceForTests::vault_b_balance_init(), - fees: 0u128, - active: true, - }), - nonce: 0, - } - } - - fn user_token_lp_holding_init_zero() -> Account { - Account { - program_owner: Program::token().id(), - balance: 0u128, - data: Data::from(&TokenHolding::Fungible { - definition_id: IdForTests::token_lp_definition_id(), - balance: 0, - }), - nonce: 0, - } - } - } - - fn state_for_amm_tests() -> V02State { - let initial_data = []; - let mut state = - V02State::new_with_genesis_accounts(&initial_data, &[]).with_test_programs(); - state.force_insert_account( - IdForTests::pool_definition_id(), - AccountForTests::pool_definition_init(), - ); - state.force_insert_account( - IdForTests::token_a_definition_id(), - AccountForTests::token_a_definition_account(), - ); - state.force_insert_account( - IdForTests::token_b_definition_id(), - AccountForTests::token_b_definition_acc(), - ); - state.force_insert_account( - IdForTests::token_lp_definition_id(), - AccountForTests::token_lp_definition_acc(), - ); - state.force_insert_account( - IdForTests::user_token_a_id(), - AccountForTests::user_token_a_holding(), - ); - state.force_insert_account( - IdForTests::user_token_b_id(), - AccountForTests::user_token_b_holding(), - ); - state.force_insert_account( - IdForTests::user_token_lp_id(), - AccountForTests::user_token_lp_holding(), - ); - state.force_insert_account(IdForTests::vault_a_id(), AccountForTests::vault_a_init()); - state.force_insert_account(IdForTests::vault_b_id(), AccountForTests::vault_b_init()); - - state - } - - fn state_for_amm_tests_with_new_def() -> V02State { - let initial_data = []; - let mut state = - V02State::new_with_genesis_accounts(&initial_data, &[]).with_test_programs(); - state.force_insert_account( - IdForTests::token_a_definition_id(), - AccountForTests::token_a_definition_account(), - ); - state.force_insert_account( - IdForTests::token_b_definition_id(), - AccountForTests::token_b_definition_acc(), - ); - state.force_insert_account( - IdForTests::user_token_a_id(), - AccountForTests::user_token_a_holding(), - ); - state.force_insert_account( - IdForTests::user_token_b_id(), - AccountForTests::user_token_b_holding(), - ); - state - } - - #[test] - fn test_simple_amm_remove() { - let mut state = state_for_amm_tests(); - - let instruction = amm_core::Instruction::RemoveLiquidity { - remove_liquidity_amount: BalanceForTests::remove_lp(), - min_amount_to_remove_token_a: BalanceForTests::remove_min_amount_a(), - min_amount_to_remove_token_b: BalanceForTests::remove_min_amount_b(), - }; - - let message = public_transaction::Message::try_new( - Program::amm().id(), - vec![ - IdForTests::pool_definition_id(), - IdForTests::vault_a_id(), - IdForTests::vault_b_id(), - IdForTests::token_lp_definition_id(), - IdForTests::user_token_a_id(), - IdForTests::user_token_b_id(), - IdForTests::user_token_lp_id(), - ], - vec![0], - instruction, - ) - .unwrap(); - - let witness_set = public_transaction::WitnessSet::for_message( - &message, - &[&PrivateKeysForTests::user_token_lp_key()], - ); - - let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx).unwrap(); - - let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); - let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); - let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); - let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); - let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); - let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); - let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); - - let expected_pool = AccountForTests::pool_definition_remove(); - let expected_vault_a = AccountForTests::vault_a_remove(); - let expected_vault_b = AccountForTests::vault_b_remove(); - let expected_token_lp = AccountForTests::token_lp_definition_remove(); - let expected_user_token_a = AccountForTests::user_token_a_holding_remove(); - let expected_user_token_b = AccountForTests::user_token_b_holding_remove(); - let expected_user_token_lp = AccountForTests::user_token_lp_holding_remove(); - - assert_eq!(pool_post, expected_pool); - assert_eq!(vault_a_post, expected_vault_a); - assert_eq!(vault_b_post, expected_vault_b); - assert_eq!(token_lp_post, expected_token_lp); - assert_eq!(user_token_a_post, expected_user_token_a); - assert_eq!(user_token_b_post, expected_user_token_b); - assert_eq!(user_token_lp_post, expected_user_token_lp); - } - - #[test] - fn test_simple_amm_new_definition_inactive_initialized_pool_and_uninit_user_lp() { - let mut state = state_for_amm_tests_with_new_def(); - - // Uninitialized in constructor - state.force_insert_account( - IdForTests::vault_a_id(), - AccountForTests::vault_a_init_inactive(), - ); - state.force_insert_account( - IdForTests::vault_b_id(), - AccountForTests::vault_b_init_inactive(), - ); - state.force_insert_account( - IdForTests::pool_definition_id(), - AccountForTests::pool_definition_inactive(), - ); - state.force_insert_account( - IdForTests::token_lp_definition_id(), - AccountForTests::token_lp_definition_init_inactive(), - ); - - let instruction = amm_core::Instruction::NewDefinition { - token_a_amount: BalanceForTests::vault_a_balance_init(), - token_b_amount: BalanceForTests::vault_b_balance_init(), - amm_program_id: Program::amm().id(), - }; - - let message = public_transaction::Message::try_new( - Program::amm().id(), - vec![ - IdForTests::pool_definition_id(), - IdForTests::vault_a_id(), - IdForTests::vault_b_id(), - IdForTests::token_lp_definition_id(), - IdForTests::user_token_a_id(), - IdForTests::user_token_b_id(), - IdForTests::user_token_lp_id(), - ], - vec![0, 0], - instruction, - ) - .unwrap(); - - let witness_set = public_transaction::WitnessSet::for_message( - &message, - &[ - &PrivateKeysForTests::user_token_a_key(), - &PrivateKeysForTests::user_token_b_key(), - ], - ); - - let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx).unwrap(); - - let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); - let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); - let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); - let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); - let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); - let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); - let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); - - let expected_pool = AccountForTests::pool_definition_new_init(); - let expected_vault_a = AccountForTests::vault_a_init(); - let expected_vault_b = AccountForTests::vault_b_init(); - let expected_token_lp = AccountForTests::token_lp_definition_new_init(); - let expected_user_token_a = AccountForTests::user_token_a_holding_new_init(); - let expected_user_token_b = AccountForTests::user_token_b_holding_new_init(); - let expected_user_token_lp = AccountForTests::user_token_lp_holding_new_init(); - - assert_eq!(pool_post, expected_pool); - assert_eq!(vault_a_post, expected_vault_a); - assert_eq!(vault_b_post, expected_vault_b); - assert_eq!(token_lp_post, expected_token_lp); - assert_eq!(user_token_a_post, expected_user_token_a); - assert_eq!(user_token_b_post, expected_user_token_b); - assert_eq!(user_token_lp_post, expected_user_token_lp); - } - - #[test] - fn test_simple_amm_new_definition_inactive_initialized_pool_init_user_lp() { - let mut state = state_for_amm_tests_with_new_def(); - - // Uninitialized in constructor - state.force_insert_account( - IdForTests::vault_a_id(), - AccountForTests::vault_a_init_inactive(), - ); - state.force_insert_account( - IdForTests::vault_b_id(), - AccountForTests::vault_b_init_inactive(), - ); - state.force_insert_account( - IdForTests::pool_definition_id(), - AccountForTests::pool_definition_inactive(), - ); - state.force_insert_account( - IdForTests::token_lp_definition_id(), - AccountForTests::token_lp_definition_init_inactive(), - ); - state.force_insert_account( - IdForTests::user_token_lp_id(), - AccountForTests::user_token_lp_holding_init_zero(), - ); - - let instruction = amm_core::Instruction::NewDefinition { - token_a_amount: BalanceForTests::vault_a_balance_init(), - token_b_amount: BalanceForTests::vault_b_balance_init(), - amm_program_id: Program::amm().id(), - }; - - let message = public_transaction::Message::try_new( - Program::amm().id(), - vec![ - IdForTests::pool_definition_id(), - IdForTests::vault_a_id(), - IdForTests::vault_b_id(), - IdForTests::token_lp_definition_id(), - IdForTests::user_token_a_id(), - IdForTests::user_token_b_id(), - IdForTests::user_token_lp_id(), - ], - vec![0, 0], - instruction, - ) - .unwrap(); - - let witness_set = public_transaction::WitnessSet::for_message( - &message, - &[ - &PrivateKeysForTests::user_token_a_key(), - &PrivateKeysForTests::user_token_b_key(), - ], - ); - - let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx).unwrap(); - - let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); - let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); - let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); - let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); - let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); - let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); - let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); - - let expected_pool = AccountForTests::pool_definition_init(); - let expected_vault_a = AccountForTests::vault_a_init(); - let expected_vault_b = AccountForTests::vault_b_init(); - let expected_token_lp = AccountForTests::token_lp_definition_new_init(); - let expected_user_token_a = AccountForTests::user_token_a_holding_new_init(); - let expected_user_token_b = AccountForTests::user_token_b_holding_new_init(); - let expected_user_token_lp = AccountForTests::user_token_lp_holding_new_init(); - - assert_eq!(pool_post, expected_pool); - assert_eq!(vault_a_post, expected_vault_a); - assert_eq!(vault_b_post, expected_vault_b); - assert_eq!(token_lp_post, expected_token_lp); - assert_eq!(user_token_a_post, expected_user_token_a); - assert_eq!(user_token_b_post, expected_user_token_b); - assert_eq!(user_token_lp_post, expected_user_token_lp); - } - - #[test] - fn test_simple_amm_new_definition_uninitialized_pool() { - let mut state = state_for_amm_tests_with_new_def(); - - // Uninitialized in constructor - state.force_insert_account( - IdForTests::vault_a_id(), - AccountForTests::vault_a_init_inactive(), - ); - state.force_insert_account( - IdForTests::vault_b_id(), - AccountForTests::vault_b_init_inactive(), - ); - - let instruction = amm_core::Instruction::NewDefinition { - token_a_amount: BalanceForTests::vault_a_balance_init(), - token_b_amount: BalanceForTests::vault_b_balance_init(), - amm_program_id: Program::amm().id(), - }; - - let message = public_transaction::Message::try_new( - Program::amm().id(), - vec![ - IdForTests::pool_definition_id(), - IdForTests::vault_a_id(), - IdForTests::vault_b_id(), - IdForTests::token_lp_definition_id(), - IdForTests::user_token_a_id(), - IdForTests::user_token_b_id(), - IdForTests::user_token_lp_id(), - ], - vec![0, 0], - instruction, - ) - .unwrap(); - - let witness_set = public_transaction::WitnessSet::for_message( - &message, - &[ - &PrivateKeysForTests::user_token_a_key(), - &PrivateKeysForTests::user_token_b_key(), - ], - ); - - let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx).unwrap(); - - let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); - let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); - let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); - let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); - let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); - let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); - let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); - - let expected_pool = AccountForTests::pool_definition_new_init(); - let expected_vault_a = AccountForTests::vault_a_init(); - let expected_vault_b = AccountForTests::vault_b_init(); - let expected_token_lp = AccountForTests::token_lp_definition_new_init(); - let expected_user_token_a = AccountForTests::user_token_a_holding_new_init(); - let expected_user_token_b = AccountForTests::user_token_b_holding_new_init(); - let expected_user_token_lp = AccountForTests::user_token_lp_holding_new_init(); - - assert_eq!(pool_post, expected_pool); - assert_eq!(vault_a_post, expected_vault_a); - assert_eq!(vault_b_post, expected_vault_b); - assert_eq!(token_lp_post, expected_token_lp); - assert_eq!(user_token_a_post, expected_user_token_a); - assert_eq!(user_token_b_post, expected_user_token_b); - assert_eq!(user_token_lp_post, expected_user_token_lp); - } - - #[test] - fn test_simple_amm_add() { - env_logger::init(); - let mut state = state_for_amm_tests(); - - let instruction = amm_core::Instruction::AddLiquidity { - min_amount_liquidity: BalanceForTests::add_min_amount_lp(), - max_amount_to_add_token_a: BalanceForTests::add_max_amount_a(), - max_amount_to_add_token_b: BalanceForTests::add_max_amount_b(), - }; - - let message = public_transaction::Message::try_new( - Program::amm().id(), - vec![ - IdForTests::pool_definition_id(), - IdForTests::vault_a_id(), - IdForTests::vault_b_id(), - IdForTests::token_lp_definition_id(), - IdForTests::user_token_a_id(), - IdForTests::user_token_b_id(), - IdForTests::user_token_lp_id(), - ], - vec![0, 0], - instruction, - ) - .unwrap(); - - let witness_set = public_transaction::WitnessSet::for_message( - &message, - &[ - &PrivateKeysForTests::user_token_a_key(), - &PrivateKeysForTests::user_token_b_key(), - ], - ); - - let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx).unwrap(); - - let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); - let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); - let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); - let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); - let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); - let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); - let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); - - let expected_pool = AccountForTests::pool_definition_add(); - let expected_vault_a = AccountForTests::vault_a_add(); - let expected_vault_b = AccountForTests::vault_b_add(); - let expected_token_lp = AccountForTests::token_lp_definition_add(); - let expected_user_token_a = AccountForTests::user_token_a_holding_add(); - let expected_user_token_b = AccountForTests::user_token_b_holding_add(); - let expected_user_token_lp = AccountForTests::user_token_lp_holding_add(); - - assert_eq!(pool_post, expected_pool); - assert_eq!(vault_a_post, expected_vault_a); - assert_eq!(vault_b_post, expected_vault_b); - assert_eq!(token_lp_post, expected_token_lp); - assert_eq!(user_token_a_post, expected_user_token_a); - assert_eq!(user_token_b_post, expected_user_token_b); - assert_eq!(user_token_lp_post, expected_user_token_lp); - } - - #[test] - fn test_simple_amm_swap_1() { - let mut state = state_for_amm_tests(); - - let instruction = amm_core::Instruction::Swap { - swap_amount_in: BalanceForTests::swap_amount_in(), - min_amount_out: BalanceForTests::swap_min_amount_out(), - token_definition_id_in: IdForTests::token_b_definition_id(), - }; - - let message = public_transaction::Message::try_new( - Program::amm().id(), - vec![ - IdForTests::pool_definition_id(), - IdForTests::vault_a_id(), - IdForTests::vault_b_id(), - IdForTests::user_token_a_id(), - IdForTests::user_token_b_id(), - ], - vec![0], - instruction, - ) - .unwrap(); - - let witness_set = public_transaction::WitnessSet::for_message( - &message, - &[&PrivateKeysForTests::user_token_b_key()], - ); - - let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx).unwrap(); - - let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); - let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); - let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); - let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); - let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); - - let expected_pool = AccountForTests::pool_definition_swap_1(); - let expected_vault_a = AccountForTests::vault_a_swap_1(); - let expected_vault_b = AccountForTests::vault_b_swap_1(); - let expected_user_token_a = AccountForTests::user_token_a_holding_swap_1(); - let expected_user_token_b = AccountForTests::user_token_b_holding_swap_1(); - - assert_eq!(pool_post, expected_pool); - assert_eq!(vault_a_post, expected_vault_a); - assert_eq!(vault_b_post, expected_vault_b); - assert_eq!(user_token_a_post, expected_user_token_a); - assert_eq!(user_token_b_post, expected_user_token_b); - } - - #[test] - fn test_simple_amm_swap_2() { - let mut state = state_for_amm_tests(); - - let instruction = amm_core::Instruction::Swap { - swap_amount_in: BalanceForTests::swap_amount_in(), - min_amount_out: BalanceForTests::swap_min_amount_out(), - token_definition_id_in: IdForTests::token_a_definition_id(), - }; - let message = public_transaction::Message::try_new( - Program::amm().id(), - vec![ - IdForTests::pool_definition_id(), - IdForTests::vault_a_id(), - IdForTests::vault_b_id(), - IdForTests::user_token_a_id(), - IdForTests::user_token_b_id(), - ], - vec![0], - instruction, - ) - .unwrap(); - - let witness_set = public_transaction::WitnessSet::for_message( - &message, - &[&PrivateKeysForTests::user_token_a_key()], - ); - - let tx = PublicTransaction::new(message, witness_set); - state.transition_from_public_transaction(&tx).unwrap(); - - let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); - let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); - let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); - let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); - let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); - - let expected_pool = AccountForTests::pool_definition_swap_2(); - let expected_vault_a = AccountForTests::vault_a_swap_2(); - let expected_vault_b = AccountForTests::vault_b_swap_2(); - let expected_user_token_a = AccountForTests::user_token_a_holding_swap_2(); - let expected_user_token_b = AccountForTests::user_token_b_holding_swap_2(); - - assert_eq!(pool_post, expected_pool); - assert_eq!(vault_a_post, expected_vault_a); - assert_eq!(vault_b_post, expected_vault_b); - assert_eq!(user_token_a_post, expected_user_token_a); - assert_eq!(user_token_b_post, expected_user_token_b); - } - #[test] fn test_execution_that_requires_authentication_of_a_program_derived_account_id_succeeds() { let chain_caller = Program::chain_caller(); diff --git a/programs/amm/Cargo.toml b/programs/amm/Cargo.toml index 54df6763..9d64a289 100644 --- a/programs/amm/Cargo.toml +++ b/programs/amm/Cargo.toml @@ -8,3 +8,4 @@ license = { workspace = true } nssa_core.workspace = true token_core.workspace = true amm_core.workspace = true +nssa.workspace = true \ No newline at end of file diff --git a/programs/amm/src/full_tests.rs b/programs/amm/src/full_tests.rs new file mode 100644 index 00000000..f3fed381 --- /dev/null +++ b/programs/amm/src/full_tests.rs @@ -0,0 +1,1344 @@ +#![cfg(all(test, feature = "test-utils"))] + +use amm_core::PoolDefinition; +use nssa::{Account, AccountId, Data, PrivateKey, PublicKey, PublicTransaction, V02State, program::Program, public_transaction}; +use token_core::{TokenDefinition, TokenHolding}; + + struct PrivateKeysForTests; + + impl PrivateKeysForTests { + fn user_token_a_key() -> PrivateKey { + PrivateKey::try_new([31; 32]).expect("Keys constructor expects valid private key") + } + + fn user_token_b_key() -> PrivateKey { + PrivateKey::try_new([32; 32]).expect("Keys constructor expects valid private key") + } + + fn user_token_lp_key() -> PrivateKey { + PrivateKey::try_new([33; 32]).expect("Keys constructor expects valid private key") + } + } + + struct BalanceForTests; + + impl BalanceForTests { + fn user_token_a_holding_init() -> u128 { + 10_000 + } + + fn user_token_b_holding_init() -> u128 { + 10_000 + } + + fn user_token_lp_holding_init() -> u128 { + 2_000 + } + + fn vault_a_balance_init() -> u128 { + 5_000 + } + + fn vault_b_balance_init() -> u128 { + 2_500 + } + + fn pool_lp_supply_init() -> u128 { + 5_000 + } + + fn token_a_supply() -> u128 { + 100_000 + } + + fn token_b_supply() -> u128 { + 100_000 + } + + fn token_lp_supply() -> u128 { + 5_000 + } + + fn remove_lp() -> u128 { + 1_000 + } + + fn remove_min_amount_a() -> u128 { + 500 + } + + fn remove_min_amount_b() -> u128 { + 500 + } + + fn add_min_amount_lp() -> u128 { + 1_000 + } + + fn add_max_amount_a() -> u128 { + 2_000 + } + + fn add_max_amount_b() -> u128 { + 1_000 + } + + fn swap_amount_in() -> u128 { + 1_000 + } + + fn swap_min_amount_out() -> u128 { + 200 + } + + fn vault_a_balance_swap_1() -> u128 { + 3_572 + } + + fn vault_b_balance_swap_1() -> u128 { + 3_500 + } + + fn user_token_a_holding_swap_1() -> u128 { + 11_428 + } + + fn user_token_b_holding_swap_1() -> u128 { + 9_000 + } + + fn vault_a_balance_swap_2() -> u128 { + 6_000 + } + + fn vault_b_balance_swap_2() -> u128 { + 2_084 + } + + fn user_token_a_holding_swap_2() -> u128 { + 9_000 + } + + fn user_token_b_holding_swap_2() -> u128 { + 10_416 + } + + fn vault_a_balance_add() -> u128 { + 7_000 + } + + fn vault_b_balance_add() -> u128 { + 3_500 + } + + fn user_token_a_holding_add() -> u128 { + 8_000 + } + + fn user_token_b_holding_add() -> u128 { + 9_000 + } + + fn user_token_lp_holding_add() -> u128 { + 4_000 + } + + fn token_lp_supply_add() -> u128 { + 7_000 + } + + fn vault_a_balance_remove() -> u128 { + 4_000 + } + + fn vault_b_balance_remove() -> u128 { + 2_000 + } + + fn user_token_a_holding_remove() -> u128 { + 11_000 + } + + fn user_token_b_holding_remove() -> u128 { + 10_500 + } + + fn user_token_lp_holding_remove() -> u128 { + 1_000 + } + + fn token_lp_supply_remove() -> u128 { + 4_000 + } + + fn user_token_a_holding_new_definition() -> u128 { + 5_000 + } + + fn user_token_b_holding_new_definition() -> u128 { + 7_500 + } + } + + struct IdForTests; + + impl IdForTests { + fn pool_definition_id() -> AccountId { + amm_core::compute_pool_pda( + Program::amm().id(), + IdForTests::token_a_definition_id(), + IdForTests::token_b_definition_id(), + ) + } + + fn token_lp_definition_id() -> AccountId { + amm_core::compute_liquidity_token_pda( + Program::amm().id(), + IdForTests::pool_definition_id(), + ) + } + + fn token_a_definition_id() -> AccountId { + AccountId::new([3; 32]) + } + + fn token_b_definition_id() -> AccountId { + AccountId::new([4; 32]) + } + + fn user_token_a_id() -> AccountId { + AccountId::from(&PublicKey::new_from_private_key( + &PrivateKeysForTests::user_token_a_key(), + )) + } + + fn user_token_b_id() -> AccountId { + AccountId::from(&PublicKey::new_from_private_key( + &PrivateKeysForTests::user_token_b_key(), + )) + } + + fn user_token_lp_id() -> AccountId { + AccountId::from(&PublicKey::new_from_private_key( + &PrivateKeysForTests::user_token_lp_key(), + )) + } + + fn vault_a_id() -> AccountId { + amm_core::compute_vault_pda( + Program::amm().id(), + IdForTests::pool_definition_id(), + IdForTests::token_a_definition_id(), + ) + } + + fn vault_b_id() -> AccountId { + amm_core::compute_vault_pda( + Program::amm().id(), + IdForTests::pool_definition_id(), + IdForTests::token_b_definition_id(), + ) + } + } + + struct AccountForTests; + + impl AccountForTests { + fn user_token_a_holding() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::user_token_a_holding_init(), + }), + nonce: 0, + } + } + + fn user_token_b_holding() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::user_token_b_holding_init(), + }), + nonce: 0, + } + } + + fn pool_definition_init() -> Account { + Account { + program_owner: Program::amm().id(), + balance: 0u128, + data: Data::from(&PoolDefinition { + definition_token_a_id: IdForTests::token_a_definition_id(), + definition_token_b_id: IdForTests::token_b_definition_id(), + vault_a_id: IdForTests::vault_a_id(), + vault_b_id: IdForTests::vault_b_id(), + liquidity_pool_id: IdForTests::token_lp_definition_id(), + liquidity_pool_supply: BalanceForTests::pool_lp_supply_init(), + reserve_a: BalanceForTests::vault_a_balance_init(), + reserve_b: BalanceForTests::vault_b_balance_init(), + fees: 0u128, + active: true, + }), + nonce: 0, + } + } + + fn token_a_definition_account() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenDefinition::Fungible { + name: String::from("test"), + total_supply: BalanceForTests::token_a_supply(), + metadata_id: None, + }), + nonce: 0, + } + } + + fn token_b_definition_acc() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenDefinition::Fungible { + name: String::from("test"), + total_supply: BalanceForTests::token_b_supply(), + metadata_id: None, + }), + nonce: 0, + } + } + + fn token_lp_definition_acc() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenDefinition::Fungible { + name: String::from("LP Token"), + total_supply: BalanceForTests::token_lp_supply(), + metadata_id: None, + }), + nonce: 0, + } + } + + fn vault_a_init() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::vault_a_balance_init(), + }), + nonce: 0, + } + } + + fn vault_b_init() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::vault_b_balance_init(), + }), + nonce: 0, + } + } + + fn user_token_lp_holding() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_lp_definition_id(), + balance: BalanceForTests::user_token_lp_holding_init(), + }), + nonce: 0, + } + } + + fn vault_a_swap_1() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::vault_a_balance_swap_1(), + }), + nonce: 0, + } + } + + fn vault_b_swap_1() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::vault_b_balance_swap_1(), + }), + nonce: 0, + } + } + + fn pool_definition_swap_1() -> Account { + Account { + program_owner: Program::amm().id(), + balance: 0u128, + data: Data::from(&PoolDefinition { + definition_token_a_id: IdForTests::token_a_definition_id(), + definition_token_b_id: IdForTests::token_b_definition_id(), + vault_a_id: IdForTests::vault_a_id(), + vault_b_id: IdForTests::vault_b_id(), + liquidity_pool_id: IdForTests::token_lp_definition_id(), + liquidity_pool_supply: BalanceForTests::pool_lp_supply_init(), + reserve_a: BalanceForTests::vault_a_balance_swap_1(), + reserve_b: BalanceForTests::vault_b_balance_swap_1(), + fees: 0u128, + active: true, + }), + nonce: 0, + } + } + + fn user_token_a_holding_swap_1() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::user_token_a_holding_swap_1(), + }), + nonce: 0, + } + } + + fn user_token_b_holding_swap_1() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::user_token_b_holding_swap_1(), + }), + nonce: 1, + } + } + + fn vault_a_swap_2() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::vault_a_balance_swap_2(), + }), + nonce: 0, + } + } + + fn vault_b_swap_2() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::vault_b_balance_swap_2(), + }), + nonce: 0, + } + } + + fn pool_definition_swap_2() -> Account { + Account { + program_owner: Program::amm().id(), + balance: 0u128, + data: Data::from(&PoolDefinition { + definition_token_a_id: IdForTests::token_a_definition_id(), + definition_token_b_id: IdForTests::token_b_definition_id(), + vault_a_id: IdForTests::vault_a_id(), + vault_b_id: IdForTests::vault_b_id(), + liquidity_pool_id: IdForTests::token_lp_definition_id(), + liquidity_pool_supply: BalanceForTests::pool_lp_supply_init(), + reserve_a: BalanceForTests::vault_a_balance_swap_2(), + reserve_b: BalanceForTests::vault_b_balance_swap_2(), + fees: 0u128, + active: true, + }), + nonce: 0, + } + } + + fn user_token_a_holding_swap_2() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::user_token_a_holding_swap_2(), + }), + nonce: 1, + } + } + + fn user_token_b_holding_swap_2() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::user_token_b_holding_swap_2(), + }), + nonce: 0, + } + } + + fn vault_a_add() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::vault_a_balance_add(), + }), + nonce: 0, + } + } + + fn vault_b_add() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::vault_b_balance_add(), + }), + nonce: 0, + } + } + + fn pool_definition_add() -> Account { + Account { + program_owner: Program::amm().id(), + balance: 0u128, + data: Data::from(&PoolDefinition { + definition_token_a_id: IdForTests::token_a_definition_id(), + definition_token_b_id: IdForTests::token_b_definition_id(), + vault_a_id: IdForTests::vault_a_id(), + vault_b_id: IdForTests::vault_b_id(), + liquidity_pool_id: IdForTests::token_lp_definition_id(), + liquidity_pool_supply: BalanceForTests::token_lp_supply_add(), + reserve_a: BalanceForTests::vault_a_balance_add(), + reserve_b: BalanceForTests::vault_b_balance_add(), + fees: 0u128, + active: true, + }), + nonce: 0, + } + } + + fn user_token_a_holding_add() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::user_token_a_holding_add(), + }), + nonce: 1, + } + } + + fn user_token_b_holding_add() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::user_token_b_holding_add(), + }), + nonce: 1, + } + } + + fn user_token_lp_holding_add() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_lp_definition_id(), + balance: BalanceForTests::user_token_lp_holding_add(), + }), + nonce: 0, + } + } + + fn token_lp_definition_add() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenDefinition::Fungible { + name: String::from("LP Token"), + total_supply: BalanceForTests::token_lp_supply_add(), + metadata_id: None, + }), + nonce: 0, + } + } + + fn vault_a_remove() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::vault_a_balance_remove(), + }), + nonce: 0, + } + } + + fn vault_b_remove() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::vault_b_balance_remove(), + }), + nonce: 0, + } + } + + fn pool_definition_remove() -> Account { + Account { + program_owner: Program::amm().id(), + balance: 0u128, + data: Data::from(&PoolDefinition { + definition_token_a_id: IdForTests::token_a_definition_id(), + definition_token_b_id: IdForTests::token_b_definition_id(), + vault_a_id: IdForTests::vault_a_id(), + vault_b_id: IdForTests::vault_b_id(), + liquidity_pool_id: IdForTests::token_lp_definition_id(), + liquidity_pool_supply: BalanceForTests::token_lp_supply_remove(), + reserve_a: BalanceForTests::vault_a_balance_remove(), + reserve_b: BalanceForTests::vault_b_balance_remove(), + fees: 0u128, + active: true, + }), + nonce: 0, + } + } + + fn user_token_a_holding_remove() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::user_token_a_holding_remove(), + }), + nonce: 0, + } + } + + fn user_token_b_holding_remove() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::user_token_b_holding_remove(), + }), + nonce: 0, + } + } + + fn user_token_lp_holding_remove() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_lp_definition_id(), + balance: BalanceForTests::user_token_lp_holding_remove(), + }), + nonce: 1, + } + } + + fn token_lp_definition_remove() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenDefinition::Fungible { + name: String::from("LP Token"), + total_supply: BalanceForTests::token_lp_supply_remove(), + metadata_id: None, + }), + nonce: 0, + } + } + + fn token_lp_definition_init_inactive() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenDefinition::Fungible { + name: String::from("LP Token"), + total_supply: 0, + metadata_id: None, + }), + nonce: 0, + } + } + + fn vault_a_init_inactive() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: 0, + }), + nonce: 0, + } + } + + fn vault_b_init_inactive() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: 0, + }), + nonce: 0, + } + } + + fn pool_definition_inactive() -> Account { + Account { + program_owner: Program::amm().id(), + balance: 0u128, + data: Data::from(&PoolDefinition { + definition_token_a_id: IdForTests::token_a_definition_id(), + definition_token_b_id: IdForTests::token_b_definition_id(), + vault_a_id: IdForTests::vault_a_id(), + vault_b_id: IdForTests::vault_b_id(), + liquidity_pool_id: IdForTests::token_lp_definition_id(), + liquidity_pool_supply: 0, + reserve_a: 0, + reserve_b: 0, + fees: 0u128, + active: false, + }), + nonce: 0, + } + } + + fn user_token_a_holding_new_init() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_a_definition_id(), + balance: BalanceForTests::user_token_a_holding_new_definition(), + }), + nonce: 1, + } + } + + fn user_token_b_holding_new_init() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_b_definition_id(), + balance: BalanceForTests::user_token_b_holding_new_definition(), + }), + nonce: 1, + } + } + + fn user_token_lp_holding_new_init() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_lp_definition_id(), + balance: BalanceForTests::user_token_a_holding_new_definition(), + }), + nonce: 0, + } + } + + fn token_lp_definition_new_init() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenDefinition::Fungible { + name: String::from("LP Token"), + total_supply: BalanceForTests::vault_a_balance_init(), + metadata_id: None, + }), + nonce: 0, + } + } + + fn pool_definition_new_init() -> Account { + Account { + program_owner: Program::amm().id(), + balance: 0u128, + data: Data::from(&PoolDefinition { + definition_token_a_id: IdForTests::token_a_definition_id(), + definition_token_b_id: IdForTests::token_b_definition_id(), + vault_a_id: IdForTests::vault_a_id(), + vault_b_id: IdForTests::vault_b_id(), + liquidity_pool_id: IdForTests::token_lp_definition_id(), + liquidity_pool_supply: BalanceForTests::user_token_a_holding_new_definition(), + reserve_a: BalanceForTests::vault_a_balance_init(), + reserve_b: BalanceForTests::vault_b_balance_init(), + fees: 0u128, + active: true, + }), + nonce: 0, + } + } + + fn user_token_lp_holding_init_zero() -> Account { + Account { + program_owner: Program::token().id(), + balance: 0u128, + data: Data::from(&TokenHolding::Fungible { + definition_id: IdForTests::token_lp_definition_id(), + balance: 0, + }), + nonce: 0, + } + } + } + + fn state_for_amm_tests() -> V02State { + let initial_data = []; + let mut state = + V02State::new_with_genesis_accounts(&initial_data, &[]); + state.force_insert_account( + IdForTests::pool_definition_id(), + AccountForTests::pool_definition_init(), + ); + state.force_insert_account( + IdForTests::token_a_definition_id(), + AccountForTests::token_a_definition_account(), + ); + state.force_insert_account( + IdForTests::token_b_definition_id(), + AccountForTests::token_b_definition_acc(), + ); + state.force_insert_account( + IdForTests::token_lp_definition_id(), + AccountForTests::token_lp_definition_acc(), + ); + state.force_insert_account( + IdForTests::user_token_a_id(), + AccountForTests::user_token_a_holding(), + ); + state.force_insert_account( + IdForTests::user_token_b_id(), + AccountForTests::user_token_b_holding(), + ); + state.force_insert_account( + IdForTests::user_token_lp_id(), + AccountForTests::user_token_lp_holding(), + ); + state.force_insert_account(IdForTests::vault_a_id(), AccountForTests::vault_a_init()); + state.force_insert_account(IdForTests::vault_b_id(), AccountForTests::vault_b_init()); + + state + } + + fn state_for_amm_tests_with_new_def() -> V02State { + let initial_data = []; + let mut state = + V02State::new_with_genesis_accounts(&initial_data, &[]); + state.force_insert_account( + IdForTests::token_a_definition_id(), + AccountForTests::token_a_definition_account(), + ); + state.force_insert_account( + IdForTests::token_b_definition_id(), + AccountForTests::token_b_definition_acc(), + ); + state.force_insert_account( + IdForTests::user_token_a_id(), + AccountForTests::user_token_a_holding(), + ); + state.force_insert_account( + IdForTests::user_token_b_id(), + AccountForTests::user_token_b_holding(), + ); + state + } + + #[test] + fn test_simple_amm_remove() { + let mut state = state_for_amm_tests(); + + let instruction = amm_core::Instruction::RemoveLiquidity { + remove_liquidity_amount: BalanceForTests::remove_lp(), + min_amount_to_remove_token_a: BalanceForTests::remove_min_amount_a(), + min_amount_to_remove_token_b: BalanceForTests::remove_min_amount_b(), + }; + + let message = public_transaction::Message::try_new( + Program::amm().id(), + vec![ + IdForTests::pool_definition_id(), + IdForTests::vault_a_id(), + IdForTests::vault_b_id(), + IdForTests::token_lp_definition_id(), + IdForTests::user_token_a_id(), + IdForTests::user_token_b_id(), + IdForTests::user_token_lp_id(), + ], + vec![0], + instruction, + ) + .unwrap(); + + let witness_set = public_transaction::WitnessSet::for_message( + &message, + &[&PrivateKeysForTests::user_token_lp_key()], + ); + + let tx = PublicTransaction::new(message, witness_set); + state.transition_from_public_transaction(&tx).unwrap(); + + let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); + let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); + let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); + let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); + let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); + let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); + let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); + + let expected_pool = AccountForTests::pool_definition_remove(); + let expected_vault_a = AccountForTests::vault_a_remove(); + let expected_vault_b = AccountForTests::vault_b_remove(); + let expected_token_lp = AccountForTests::token_lp_definition_remove(); + let expected_user_token_a = AccountForTests::user_token_a_holding_remove(); + let expected_user_token_b = AccountForTests::user_token_b_holding_remove(); + let expected_user_token_lp = AccountForTests::user_token_lp_holding_remove(); + + assert_eq!(pool_post, expected_pool); + assert_eq!(vault_a_post, expected_vault_a); + assert_eq!(vault_b_post, expected_vault_b); + assert_eq!(token_lp_post, expected_token_lp); + assert_eq!(user_token_a_post, expected_user_token_a); + assert_eq!(user_token_b_post, expected_user_token_b); + assert_eq!(user_token_lp_post, expected_user_token_lp); + } + + #[test] + fn test_simple_amm_new_definition_inactive_initialized_pool_and_uninit_user_lp() { + let mut state = state_for_amm_tests_with_new_def(); + + // Uninitialized in constructor + state.force_insert_account( + IdForTests::vault_a_id(), + AccountForTests::vault_a_init_inactive(), + ); + state.force_insert_account( + IdForTests::vault_b_id(), + AccountForTests::vault_b_init_inactive(), + ); + state.force_insert_account( + IdForTests::pool_definition_id(), + AccountForTests::pool_definition_inactive(), + ); + state.force_insert_account( + IdForTests::token_lp_definition_id(), + AccountForTests::token_lp_definition_init_inactive(), + ); + + let instruction = amm_core::Instruction::NewDefinition { + token_a_amount: BalanceForTests::vault_a_balance_init(), + token_b_amount: BalanceForTests::vault_b_balance_init(), + amm_program_id: Program::amm().id(), + }; + + let message = public_transaction::Message::try_new( + Program::amm().id(), + vec![ + IdForTests::pool_definition_id(), + IdForTests::vault_a_id(), + IdForTests::vault_b_id(), + IdForTests::token_lp_definition_id(), + IdForTests::user_token_a_id(), + IdForTests::user_token_b_id(), + IdForTests::user_token_lp_id(), + ], + vec![0, 0], + instruction, + ) + .unwrap(); + + let witness_set = public_transaction::WitnessSet::for_message( + &message, + &[ + &PrivateKeysForTests::user_token_a_key(), + &PrivateKeysForTests::user_token_b_key(), + ], + ); + + let tx = PublicTransaction::new(message, witness_set); + state.transition_from_public_transaction(&tx).unwrap(); + + let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); + let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); + let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); + let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); + let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); + let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); + let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); + + let expected_pool = AccountForTests::pool_definition_new_init(); + let expected_vault_a = AccountForTests::vault_a_init(); + let expected_vault_b = AccountForTests::vault_b_init(); + let expected_token_lp = AccountForTests::token_lp_definition_new_init(); + let expected_user_token_a = AccountForTests::user_token_a_holding_new_init(); + let expected_user_token_b = AccountForTests::user_token_b_holding_new_init(); + let expected_user_token_lp = AccountForTests::user_token_lp_holding_new_init(); + + assert_eq!(pool_post, expected_pool); + assert_eq!(vault_a_post, expected_vault_a); + assert_eq!(vault_b_post, expected_vault_b); + assert_eq!(token_lp_post, expected_token_lp); + assert_eq!(user_token_a_post, expected_user_token_a); + assert_eq!(user_token_b_post, expected_user_token_b); + assert_eq!(user_token_lp_post, expected_user_token_lp); + } + + #[test] + fn test_simple_amm_new_definition_inactive_initialized_pool_init_user_lp() { + let mut state = state_for_amm_tests_with_new_def(); + + // Uninitialized in constructor + state.force_insert_account( + IdForTests::vault_a_id(), + AccountForTests::vault_a_init_inactive(), + ); + state.force_insert_account( + IdForTests::vault_b_id(), + AccountForTests::vault_b_init_inactive(), + ); + state.force_insert_account( + IdForTests::pool_definition_id(), + AccountForTests::pool_definition_inactive(), + ); + state.force_insert_account( + IdForTests::token_lp_definition_id(), + AccountForTests::token_lp_definition_init_inactive(), + ); + state.force_insert_account( + IdForTests::user_token_lp_id(), + AccountForTests::user_token_lp_holding_init_zero(), + ); + + let instruction = amm_core::Instruction::NewDefinition { + token_a_amount: BalanceForTests::vault_a_balance_init(), + token_b_amount: BalanceForTests::vault_b_balance_init(), + amm_program_id: Program::amm().id(), + }; + + let message = public_transaction::Message::try_new( + Program::amm().id(), + vec![ + IdForTests::pool_definition_id(), + IdForTests::vault_a_id(), + IdForTests::vault_b_id(), + IdForTests::token_lp_definition_id(), + IdForTests::user_token_a_id(), + IdForTests::user_token_b_id(), + IdForTests::user_token_lp_id(), + ], + vec![0, 0], + instruction, + ) + .unwrap(); + + let witness_set = public_transaction::WitnessSet::for_message( + &message, + &[ + &PrivateKeysForTests::user_token_a_key(), + &PrivateKeysForTests::user_token_b_key(), + ], + ); + + let tx = PublicTransaction::new(message, witness_set); + state.transition_from_public_transaction(&tx).unwrap(); + + let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); + let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); + let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); + let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); + let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); + let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); + let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); + + let expected_pool = AccountForTests::pool_definition_init(); + let expected_vault_a = AccountForTests::vault_a_init(); + let expected_vault_b = AccountForTests::vault_b_init(); + let expected_token_lp = AccountForTests::token_lp_definition_new_init(); + let expected_user_token_a = AccountForTests::user_token_a_holding_new_init(); + let expected_user_token_b = AccountForTests::user_token_b_holding_new_init(); + let expected_user_token_lp = AccountForTests::user_token_lp_holding_new_init(); + + assert_eq!(pool_post, expected_pool); + assert_eq!(vault_a_post, expected_vault_a); + assert_eq!(vault_b_post, expected_vault_b); + assert_eq!(token_lp_post, expected_token_lp); + assert_eq!(user_token_a_post, expected_user_token_a); + assert_eq!(user_token_b_post, expected_user_token_b); + assert_eq!(user_token_lp_post, expected_user_token_lp); + } + + #[test] + fn test_simple_amm_new_definition_uninitialized_pool() { + let mut state = state_for_amm_tests_with_new_def(); + + // Uninitialized in constructor + state.force_insert_account( + IdForTests::vault_a_id(), + AccountForTests::vault_a_init_inactive(), + ); + state.force_insert_account( + IdForTests::vault_b_id(), + AccountForTests::vault_b_init_inactive(), + ); + + let instruction = amm_core::Instruction::NewDefinition { + token_a_amount: BalanceForTests::vault_a_balance_init(), + token_b_amount: BalanceForTests::vault_b_balance_init(), + amm_program_id: Program::amm().id(), + }; + + let message = public_transaction::Message::try_new( + Program::amm().id(), + vec![ + IdForTests::pool_definition_id(), + IdForTests::vault_a_id(), + IdForTests::vault_b_id(), + IdForTests::token_lp_definition_id(), + IdForTests::user_token_a_id(), + IdForTests::user_token_b_id(), + IdForTests::user_token_lp_id(), + ], + vec![0, 0], + instruction, + ) + .unwrap(); + + let witness_set = public_transaction::WitnessSet::for_message( + &message, + &[ + &PrivateKeysForTests::user_token_a_key(), + &PrivateKeysForTests::user_token_b_key(), + ], + ); + + let tx = PublicTransaction::new(message, witness_set); + state.transition_from_public_transaction(&tx).unwrap(); + + let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); + let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); + let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); + let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); + let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); + let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); + let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); + + let expected_pool = AccountForTests::pool_definition_new_init(); + let expected_vault_a = AccountForTests::vault_a_init(); + let expected_vault_b = AccountForTests::vault_b_init(); + let expected_token_lp = AccountForTests::token_lp_definition_new_init(); + let expected_user_token_a = AccountForTests::user_token_a_holding_new_init(); + let expected_user_token_b = AccountForTests::user_token_b_holding_new_init(); + let expected_user_token_lp = AccountForTests::user_token_lp_holding_new_init(); + + assert_eq!(pool_post, expected_pool); + assert_eq!(vault_a_post, expected_vault_a); + assert_eq!(vault_b_post, expected_vault_b); + assert_eq!(token_lp_post, expected_token_lp); + assert_eq!(user_token_a_post, expected_user_token_a); + assert_eq!(user_token_b_post, expected_user_token_b); + assert_eq!(user_token_lp_post, expected_user_token_lp); + } + + #[test] + fn test_simple_amm_add() { + let mut state = state_for_amm_tests(); + + let instruction = amm_core::Instruction::AddLiquidity { + min_amount_liquidity: BalanceForTests::add_min_amount_lp(), + max_amount_to_add_token_a: BalanceForTests::add_max_amount_a(), + max_amount_to_add_token_b: BalanceForTests::add_max_amount_b(), + }; + + let message = public_transaction::Message::try_new( + Program::amm().id(), + vec![ + IdForTests::pool_definition_id(), + IdForTests::vault_a_id(), + IdForTests::vault_b_id(), + IdForTests::token_lp_definition_id(), + IdForTests::user_token_a_id(), + IdForTests::user_token_b_id(), + IdForTests::user_token_lp_id(), + ], + vec![0, 0], + instruction, + ) + .unwrap(); + + let witness_set = public_transaction::WitnessSet::for_message( + &message, + &[ + &PrivateKeysForTests::user_token_a_key(), + &PrivateKeysForTests::user_token_b_key(), + ], + ); + + let tx = PublicTransaction::new(message, witness_set); + state.transition_from_public_transaction(&tx).unwrap(); + + let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); + let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); + let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); + let token_lp_post = state.get_account_by_id(IdForTests::token_lp_definition_id()); + let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); + let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); + let user_token_lp_post = state.get_account_by_id(IdForTests::user_token_lp_id()); + + let expected_pool = AccountForTests::pool_definition_add(); + let expected_vault_a = AccountForTests::vault_a_add(); + let expected_vault_b = AccountForTests::vault_b_add(); + let expected_token_lp = AccountForTests::token_lp_definition_add(); + let expected_user_token_a = AccountForTests::user_token_a_holding_add(); + let expected_user_token_b = AccountForTests::user_token_b_holding_add(); + let expected_user_token_lp = AccountForTests::user_token_lp_holding_add(); + + assert_eq!(pool_post, expected_pool); + assert_eq!(vault_a_post, expected_vault_a); + assert_eq!(vault_b_post, expected_vault_b); + assert_eq!(token_lp_post, expected_token_lp); + assert_eq!(user_token_a_post, expected_user_token_a); + assert_eq!(user_token_b_post, expected_user_token_b); + assert_eq!(user_token_lp_post, expected_user_token_lp); + } + + #[test] + fn test_simple_amm_swap_1() { + let mut state = state_for_amm_tests(); + + let instruction = amm_core::Instruction::Swap { + swap_amount_in: BalanceForTests::swap_amount_in(), + min_amount_out: BalanceForTests::swap_min_amount_out(), + token_definition_id_in: IdForTests::token_b_definition_id(), + }; + + let message = public_transaction::Message::try_new( + Program::amm().id(), + vec![ + IdForTests::pool_definition_id(), + IdForTests::vault_a_id(), + IdForTests::vault_b_id(), + IdForTests::user_token_a_id(), + IdForTests::user_token_b_id(), + ], + vec![0], + instruction, + ) + .unwrap(); + + let witness_set = public_transaction::WitnessSet::for_message( + &message, + &[&PrivateKeysForTests::user_token_b_key()], + ); + + let tx = PublicTransaction::new(message, witness_set); + state.transition_from_public_transaction(&tx).unwrap(); + + let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); + let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); + let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); + let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); + let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); + + let expected_pool = AccountForTests::pool_definition_swap_1(); + let expected_vault_a = AccountForTests::vault_a_swap_1(); + let expected_vault_b = AccountForTests::vault_b_swap_1(); + let expected_user_token_a = AccountForTests::user_token_a_holding_swap_1(); + let expected_user_token_b = AccountForTests::user_token_b_holding_swap_1(); + + assert_eq!(pool_post, expected_pool); + assert_eq!(vault_a_post, expected_vault_a); + assert_eq!(vault_b_post, expected_vault_b); + assert_eq!(user_token_a_post, expected_user_token_a); + assert_eq!(user_token_b_post, expected_user_token_b); + } + + #[test] + fn test_simple_amm_swap_2() { + let mut state = state_for_amm_tests(); + + let instruction = amm_core::Instruction::Swap { + swap_amount_in: BalanceForTests::swap_amount_in(), + min_amount_out: BalanceForTests::swap_min_amount_out(), + token_definition_id_in: IdForTests::token_a_definition_id(), + }; + let message = public_transaction::Message::try_new( + Program::amm().id(), + vec![ + IdForTests::pool_definition_id(), + IdForTests::vault_a_id(), + IdForTests::vault_b_id(), + IdForTests::user_token_a_id(), + IdForTests::user_token_b_id(), + ], + vec![0], + instruction, + ) + .unwrap(); + + let witness_set = public_transaction::WitnessSet::for_message( + &message, + &[&PrivateKeysForTests::user_token_a_key()], + ); + + let tx = PublicTransaction::new(message, witness_set); + state.transition_from_public_transaction(&tx).unwrap(); + + let pool_post = state.get_account_by_id(IdForTests::pool_definition_id()); + let vault_a_post = state.get_account_by_id(IdForTests::vault_a_id()); + let vault_b_post = state.get_account_by_id(IdForTests::vault_b_id()); + let user_token_a_post = state.get_account_by_id(IdForTests::user_token_a_id()); + let user_token_b_post = state.get_account_by_id(IdForTests::user_token_b_id()); + + let expected_pool = AccountForTests::pool_definition_swap_2(); + let expected_vault_a = AccountForTests::vault_a_swap_2(); + let expected_vault_b = AccountForTests::vault_b_swap_2(); + let expected_user_token_a = AccountForTests::user_token_a_holding_swap_2(); + let expected_user_token_b = AccountForTests::user_token_b_holding_swap_2(); + + assert_eq!(pool_post, expected_pool); + assert_eq!(vault_a_post, expected_vault_a); + assert_eq!(vault_b_post, expected_vault_b); + assert_eq!(user_token_a_post, expected_user_token_a); + assert_eq!(user_token_b_post, expected_user_token_b); + } diff --git a/programs/amm/src/lib.rs b/programs/amm/src/lib.rs index e50c738e..9666d6b4 100644 --- a/programs/amm/src/lib.rs +++ b/programs/amm/src/lib.rs @@ -8,3 +8,4 @@ pub mod remove; pub mod swap; mod tests; +mod full_tests; \ No newline at end of file