Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0xFF53042865dF617de4bB871bD0988E7B93439cCF
Balance 0 ETH
Nonce 1
Code Size 12282 bytes
Indexed Transactions 0 (1 on-chain, 0.8% indexed)
External Etherscan · Sourcify

Contract Bytecode

12282 bytes
0x5f3560e01c60026007820660011b612fec01601e395f51565b63ffa1ad7481186117c05734612fe85760208060805260056040527f312e322e3000000000000000000000000000000000000000000000000000000060605260408160800181518152602082015160208201528051806020830101601f825f03163682375050601f19601f8251602001011690509050810190506080f36117c0565b6383aa796a811861015657608436103417612fe85760043580600f0b8118612fe857610cc05260243580600f0b8118612fe857610ce0526064358060a01c612fe857610d0052610d00516329357750610d40526020610d406004610d5c845afa610106573d5f5f3e3d5ffd5b60203d10612fe857610d40905051610d20526020610cc05161054052610ce0516105605260443561058052610d00516105a0525f6105c052610d20516105e052610151610d40612038565b610d40f35b63c02c60a681186117c057608436103417612fe85760043580600f0b8118612fe8576110005260243580600f0b8118612fe857611020526064358060a01c612fe85761104052611040516329357750611080526020611080600461109c845afa6101c2573d5f5f3e3d5ffd5b60203d10612fe857611080905051611060526110605180607f1c612fe8576001810380600f0b8118612fe857905061108052611040516371511a5e6110c05260206110c060046110dc845afa61021a573d5f5f3e3d5ffd5b60203d10612fe8576110c0518060a01c612fe857611100526111009050516110a0526110405163c66106576110e05260016111005260206110e060246110fc845afa610268573d5f5f3e3d5ffd5b60203d10612fe8576110e0518060a01c612fe857611120526111209050516110c0525f6110e0525f611200525f6113205261104051604052611060516060526102b26114406117c4565b611440805160208160051b01806110e0828560045afa5050506101208101805160208160051b0180611200828560045afa505050506102408101805160208160051b0180611320828560045afa505050505060a03661144037611000511561033857611000516110805180820380600f0b8118612fe857905090506114605260016114a0525b611020511561036557611020516110805180820380600f0b8118612fe857905090506114805260016114c0525b611000516103d1576110005161132051811015612fe85760051b61134001516044356110e05115612fe8575f60051b6111000151808202811583838304141715612fe85790509050670de0b6b3a764000081049050808201828110612fe8579050905061144052610508565b611020516104b75761104051633da575a1611500526020611500600461151c845afa6103ff573d5f5f3e3d5ffd5b60203d10612fe8576115009050516114e052604435610e005261146051610e20526114e051610e40526110a051610e60526110c051610e80526001610ea052610449611500612d89565b6115005160026110e05110612fe857600160051b6111000151808202811583838304141715612fe85790509050670de0b6b3a764000081049050611440526114405160026113205110612fe857600160051b6113400151808201828110612fe8579050905061144052610508565b60206110a051635e0d443f6114e052611460516115005261148051611520526044356115405260206114e060646114fc845afa6104f6573d5f5f3e3d5ffd5b60203d10612fe8576114e09050610835565b6110405163f446c1d0611500526020611500600461151c845afa61052e573d5f5f3e3d5ffd5b60203d10612fe85761150090505160648102816064820418612fe85790506114e0526113205160208160051b018060408261132060045afa5050506114e051610160526110605161018052610584611520611994565b61152051611500526114a051610120526114c0516101405261144051610160526113205160208160051b01806101808261132060045afa5050506114e0516102a052611500516102c052611060516102e0526105e1611540611df8565b61154051611520526114c05161132051811015612fe85760051b611340015161152051808203828111612fe8579050905060018103818111612fe8579050611540526110405163ddca3f43611580526020611580600461159c845afa610649573d5f5f3e3d5ffd5b60203d10612fe8576115809050516115605261104051638edfdd5f6115a05260206115a060046115bc845afa610681573d5f5f3e3d5ffd5b60203d10612fe8576115a0905051611580526114a05161132051811015612fe85760051b611340015161144051808201828110612fe857905090508060011c90506040526114c05161132051811015612fe85760051b611340015161152051808201828110612fe857905090508060011c9050606052611560516080526115805160a0526107106115c0611c10565b6115c0516115a052611540516115a05161154051808202811583838304141715612fe857905090506402540be40081049050808203828111612fe8579050905061154052611020516107a65761154051670de0b6b3a7640000810281670de0b6b3a7640000820418612fe85790506110e05115612fe8575f60051b61110001518015612fe857808204905090506115405261082f565b6110a05163cc2b27d76115c05261154051670de0b6b3a7640000810281670de0b6b3a7640000820418612fe857905060026110e05110612fe857600160051b61110001518015612fe857808204905090506115e052611480516116005260206115c060446115dc845afa61081c573d5f5f3e3d5ffd5b60203d10612fe8576115c0905051611540525b60206115405bf36117c0565b630c601c2c81186117c057608436103417612fe85760043580600f0b8118612fe8576105405260243580600f0b8118612fe857610560526064358060a01c612fe857610580526105805163293577506105c05260206105c060046105dc845afa6108a7573d5f5f3e3d5ffd5b60203d10612fe8576105c09050516105a0525f6105c0525f6106e0525f61080052610580516040526105a0516060526108e16109206117c4565b610920805160208160051b01806105c0828560045afa5050506101208101805160208160051b01806106e0828560045afa505050506102408101805160208160051b0180610800828560045afa50505050506105805163f446c1d0610940526020610940600461095c845afa610959573d5f5f3e3d5ffd5b60203d10612fe85761094090505160648102816064820418612fe8579050610920526108005160208160051b018060408261080060045afa50505061092051610160526105a051610180526109af610960611994565b61096051610940526105405161080051811015612fe85760051b6108200151604435610540516105c051811015612fe85760051b6105e00151808202811583838304141715612fe85790509050670de0b6b3a764000081049050808201828110612fe85790509050610960526105405161012052610560516101405261096051610160526108005160208160051b01806101808261080060045afa505050610920516102a052610940516102c0526105a0516102e052610a706109a0611df8565b6109a051610980526105605161080051811015612fe85760051b610820015161098051808203828111612fe8579050905060018103818111612fe85790506109a0526105805163ddca3f436109e05260206109e060046109fc845afa610ad8573d5f5f3e3d5ffd5b60203d10612fe8576109e09050516109c05261058051638edfdd5f610a00526020610a006004610a1c845afa610b10573d5f5f3e3d5ffd5b60203d10612fe857610a009050516109e0526105405161080051811015612fe85760051b610820015161096051808201828110612fe857905090508060011c90506040526105605161080051811015612fe85760051b610820015161098051808201828110612fe857905090508060011c90506060526109c0516080526109e05160a052610b9f610a20611c10565b610a20516109a051808202811583838304141715612fe857905090506402540be40081049050610a00526109a051610a0051808203828111612fe85790509050670de0b6b3a7640000810281670de0b6b3a7640000820418612fe8579050610560516105c051811015612fe85760051b6105e001518015612fe85780820490509050610a20526020610a20f36117c0565b63d6fc10ab81186117c057608436103417612fe85760043580600f0b8118612fe8576110005260243580600f0b8118612fe857611020526064358060a01c612fe85761104052611040516371511a5e611080526020611080600461109c845afa610c9c573d5f5f3e3d5ffd5b60203d10612fe857611080518060a01c612fe8576110c0526110c09050516110605261104051633da575a16110a05260206110a060046110bc845afa610ce4573d5f5f3e3d5ffd5b60203d10612fe8576110a0905051611080526110405163293577506110c05260206110c060046110dc845afa610d1c573d5f5f3e3d5ffd5b60203d10612fe8576110c09050516110a05261106051604052610d406110e0612392565b6110e0516110c0526110405163c6610657611100526001611120526020611100602461111c845afa610d74573d5f5f3e3d5ffd5b60203d10612fe857611100518060a01c612fe857611140526111409050516110e052600161100051611020518082811882841202189050905012610e3c576023611100527f4e6f742061204d657461706f6f6c20537761702e20557365204261736520706f611120527f6f6c2e00000000000000000000000000000000000000000000000000000000006111405261110050611100518061112001601f825f031636823750506308c379a06110c05260206110e052601f19601f6111005101166044016110dcfd5b61100051610ed057604435610e0052611020516001810380600f0b8118612fe8579050610e205261108051610e405261106051610e60526110e051610e80525f610ea052610e8b611120612d89565b611120516111005260205f610540526001610560526111005161058052611040516105a0525f6105c0526110a0516105e052610ec8611120612038565b611120610f60565b6001610540525f6105605260443561058052611040516105a0525f6105c0526110a0516105e052610f02611120612038565b611120516111005260206110605163cc2b27d7611120526111005161114052611000516001810380600f0b8118612fe8579050611160526020611120604461113c845afa610f52573d5f5f3e3d5ffd5b60203d10612fe85761112090505bf36117c0565b63fb79eb27811861103657608436103417612fe8576004356004016008813511612fe857803560208160051b018083610e00375050506024358060011c612fe857610f20526044358060a01c612fe857610f40526020610e005160208160051b018061054082610e0060045afa505050610f205161066052610f405161068052610f40516106a052610f40516329357750610f60526020610f606004610f7c845afa611014573d5f5f3e3d5ffd5b60203d10612fe857610f609050516106c052611031610fa0612443565b610fa0f35b63a63530bd81186117c057606436103417612fe85760043580600f0b8118612fe8576105405260243580600f0b8118612fe857610560526044358060a01c612fe857610580526105805163293577506105c05260206105c060046105dc845afa6110a2573d5f5f3e3d5ffd5b60203d10612fe8576105c09050516105a0526105805163ddca3f436105e05260206105e060046105fc845afa6110da573d5f5f3e3d5ffd5b60203d10612fe8576105e09050516105c05261058051638edfdd5f610600526020610600600461061c845afa611112573d5f5f3e3d5ffd5b60203d10612fe8576106009050516105e0525f610600525f610720525f61084052610580516040526105a05160605261114c6109606117c4565b610960805160208160051b0180610600828560045afa5050506101208101805160208160051b0180610720828560045afa505050506102408101805160208160051b0180610840828560045afa505050505060206105405161084051811015612fe85760051b61086001516040526105605161084051811015612fe85760051b61086001516060526105c0516080526105e05160a0526111ed610960611c10565b610960f36117c0565b63b54e9f0581186117c057606436103417612fe85760243580600f0b8118612fe857610540526044358060a01c612fe857610560526105605163f446c1d06105a05260206105a060046105bc845afa611251573d5f5f3e3d5ffd5b60203d10612fe8576105a090505160648102816064820418612fe8579050610580526105605163293577506105c05260206105c060046105dc845afa611299573d5f5f3e3d5ffd5b60203d10612fe8576105c09050516105a0525f6105c0525f6106e0525f61080052610560516040526105a0516060526112d36109206117c4565b610920805160208160051b01806105c0828560045afa5050506101208101805160208160051b01806106e0828560045afa505050506102408101805160208160051b0180610800828560045afa50505050506108005160208160051b018060408261080060045afa50505061058051610160526105a05161018052611359610940611994565b6109405161092052610560516318160ddd610960526020610960600461097c845afa611387573d5f5f3e3d5ffd5b60203d10612fe857610960905051610940526109205160043561092051808202811583838304141715612fe85790509050610940518015612fe85780820490509050808203828111612fe8579050905061096052610580516101205261054051610140526108005160208160051b01806101608261080060045afa50505061096051610280526105a0516102a0526114206109a0612e00565b6109a051610980526109205161096051808201828110612fe857905090506105a0518060011b818160011c18612fe85790508015612fe857808204905090506109a0526105605163ddca3f436109e05260206109e060046109fc845afa611489573d5f5f3e3d5ffd5b60203d10612fe8576109e09050516105a051808202811583838304141715612fe857905090506105a05160018103818111612fe85790508060021b818160021c18612fe85790508015612fe857808204905090506109c05261056051638edfdd5f610a00526020610a006004610a1c845afa611507573d5f5f3e3d5ffd5b60203d10612fe857610a009050516109e0526108005160208160051b0180610a008261080060045afa505050606036610b20375f6008905b80610b80526105a051610b805118611556576116ee565b5f610ba052610b805161080051811015612fe85760051b6108200151610b205261054051610b805180607f1c612fe8571861160657610b205161096051808202811583838304141715612fe85790509050610920518015612fe8578082049050905061098051808203828111612fe85790509050610ba052610b805161080051811015612fe85760051b610820015161098051808201828110612fe857905090508060011c9050610b4052611665565b610b2051610b205161096051808202811583838304141715612fe85790509050610920518015612fe85780820490509050808203828111612fe85790509050610ba052610b805161080051811015612fe85760051b6108200151610b40525b610b40516040526109a0516060526109c0516080526109e05160a05261168c610bc0611c10565b610bc051610b6052610b2051610b6051610ba051808202811583838304141715612fe857905090506402540be40081049050808203828111612fe85790509050610b8051610a0051811015612fe85760051b610a20015260010181811861153f575b505061054051610a0051811015612fe85760051b610a20015161058051610120526105405161014052610a005160208160051b018061016082610a0060045afa50505061096051610280526105a0516102a05261174c610ba0612e00565b610ba051808203828111612fe85790509050610b8052610b805160018103818111612fe8579050670de0b6b3a7640000810281670de0b6b3a7640000820418612fe8579050610540516105c051811015612fe85760051b6105e001518015612fe85780820490509050610b80526020610b80f35b5f5ffd5b60405163fd0684b16101a0526101406101a060046101bc845afa6117ea573d5f5f3e3d5ffd5b60403d10612fe8576101a0516101a0016008815111612fe857805160208160051b0180610300828560045afa505050506103009050805160208160051b01806080828560045afa505050506040516314f059796102c0526101406102c060046102dc845afa61185b573d5f5f3e3d5ffd5b60403d10612fe8576102c0516102c0016008815111612fe857805160208160051b0180610420828560045afa505050506104209050805160208160051b01806101a0828560045afa505050505f6102c0525f6008905b806103e0526060516103e051186118c75761193d565b6102c05160078111612fe8576103e051608051811015612fe85760051b60a001516103e0516101a051811015612fe85760051b6101c00151808202811583838304141715612fe85790509050670de0b6b3a7640000810490508160051b6102e00152600181016102c052506001018181186118b1575b505060805160208160051b01808382608060045afa5050506101a05160208160051b0161012083018181836101a060045afa505050506102c05160208160051b0161024083018181836102c060045afa5050505050565b5f6101a0525f6008905b806101c052610180516101c051186119b5576119eb565b6101a0516101c051604051811015612fe85760051b60600151808201828110612fe857905090506101a05260010181811861199e575b50506101a0516119fe575f815250611c0e565b6101a0516101c0526101605161018051808202811583838304141715612fe857905090506101e0525f60ff905b80610200526101c051610220525f60405160088111612fe8578015611a9457905b8060051b6060015161024052610220516101c051808202811583838304141715612fe85790509050610240518015612fe8578082049050905061022052600101818118611a4c575b50506102205161018051610180510a8015612fe85780820490509050610220526101c051610240526101e0516101a051808202811583838304141715612fe857905090506064810490506102205161018051808202811583838304141715612fe85790509050808201828110612fe857905090506101c051808202811583838304141715612fe857905090506101e05160648103818111612fe85790506101c051808202811583838304141715612fe857905090506064810490506101805160018101818110612fe857905061022051808202811583838304141715612fe85790509050808201828110612fe857905090508015612fe857808204905090506101c052610240516101c05111611bd3576001610240516101c051808203828111612fe8579050905011611bfe576101c0518352505050611c0e56611bfe565b60016101c05161024051808203828111612fe8579050905011611bfe576101c0518352505050611c0e565b600101818118611a2b5750505f5ffd5b565b6402540be40060a05111611c2957608051815250611cfb565b604051606051808201828110612fe857905090506fffffffffffffffffffffffffffffffff8111612fe8576002810a905060c05260a051608051808202811583838304141715612fe8579050905060a0516402540be4008103818111612fe85790508060021b818160021c18612fe8579050604051808202811583838304141715612fe85790509050606051808202811583838304141715612fe8579050905060c0518015612fe857808204905090506402540be4008101818110612fe85790508015612fe857808204905090508152505b565b5f60c05260a05160e0525f60ff905b806101005260e05160c05260e05160e051808202811583838304141715612fe85790509050606051808201828110612fe8579050905060e0518060011b818160011c18612fe8579050604051808201828110612fe85790509050608051808203828111612fe857905090508015612fe8578082049050905060e05260c05160e05111611dbe57600160c05160e051808203828111612fe8579050905011611de65760e0518352505050611df656611de6565b600160e05160c051808203828111612fe8579050905011611de65760e0518352505050611df6565b600101818118611d0c5750505f5ffd5b565b610140516101205114612fe8575f6101405112612fe8576102e05180607f1c612fe857610140511215612fe8575f6101205112612fe8576102e05180607f1c612fe857610120511215612fe8576102a051610300526102c05161032052604036610340376103205161038052610300516102e051808202811583838304141715612fe857905090506103a0525f6008905b806103c0526102e0516103c05118611ea057611f6a565b610120516103c05180607f1c612fe85718611ec2576101605161036052611efb565b610140516103c05180607f1c612fe85714611f5f576103c05161018051811015612fe85760051b6101a0015161036052611efb56611f5f565b6103405161036051808201828110612fe85790509050610340526103805161032051808202811583838304141715612fe85790509050610360516102e051808202811583838304141715612fe857905090508015612fe85780820490509050610380525b600101818118611e89575b50506103805161032051808202811583838304141715612fe8579050905060648102816064820418612fe85790506103a0516102e051808202811583838304141715612fe857905090508015612fe8578082049050905061038052610340516103205160648102816064820418612fe85790506103a0518015612fe85780820490509050808201828110612fe857905090506103c052610320516103e0526103c05160405261038051606052610320516080526103e05160a05261202f610400611cfd565b61040051815250565b5f610600525f610720525f610840526105a0516040526105e0516060526120606109606117c4565b610960805160208160051b0180610600828560045afa5050506101208101805160208160051b0180610720828560045afa505050506102408101805160208160051b0180610840828560045afa50505050506105a05163f446c1d0610980526020610980600461099c845afa6120d8573d5f5f3e3d5ffd5b60203d10612fe85761098090505160648102816064820418612fe8579050610960526108405160208160051b018060408261084060045afa50505061096051610160526105e0516101805261212e6109a0611994565b6109a051610980526105a05163ddca3f436109c05260206109c060046109dc845afa61215c573d5f5f3e3d5ffd5b60203d10612fe8576109c09050516109a052610580516105605161060051811015612fe85760051b6106200151808202811583838304141715612fe85790509050670de0b6b3a76400008104905060018101818110612fe85790506109c0526109a0516109e0526105c051612259576105a051638edfdd5f610a20526020610a206004610a3c845afa6121f1573d5f5f3e3d5ffd5b60203d10612fe857610a20905051610a00526105405161084051811015612fe85760051b61086001516040526105605161084051811015612fe85760051b61086001516060526109a051608052610a005160a052612250610a20611c10565b610a20516109e0525b6105605161084051811015612fe85760051b61086001516109c0516402540be4008102816402540be400820418612fe85790506109e051806402540be400036402540be4008111612fe85790508015612fe85780820490509050808203828111612fe85790509050610a005261056051610120526105405161014052610a0051610160526108405160208160051b01806101808261084060045afa505050610960516102a052610980516102c0526105e0516102e05261231a610a40611df8565b610a4051610a2052610a20516105405161084051811015612fe85760051b6108600151808203828111612fe85790509050670de0b6b3a7640000810281670de0b6b3a7640000820418612fe85790506105405161060051811015612fe85760051b61062001518015612fe85780820490509050815250565b6040366060376040515a5f600460c0527f76a9cd3e0000000000000000000000000000000000000000000000000000000060e05260c080516020820183610120018151815250508083019250505060018161012001526020810190505f8161012001526020810190508061010052610100505060206101a0610100516101208585fa905090506060523d602081183d6020100218610180526101808051608052602081015160a05250606051815250565b6106805163f446c1d0610700526020610700600461071c845afa612469573d5f5f3e3d5ffd5b60203d10612fe85761070090505160648102816064820418612fe85790506106e0525f610700525f610820525f61094052610680515a6004610a80527f9c4258c400000000000000000000000000000000000000000000000000000000610aa052610a80505f5f610a8051610aa08585fa90509050610a60526001610a8052610a60516126ae575f610a80525f6106c05160088111612fe85780156126a757905b80610aa0526107005160078111612fe8576106805163c6610657610ac052610aa051610ae0526020610ac06024610adc845afa612549573d5f5f3e3d5ffd5b60203d10612fe857610ac0518060a01c612fe857610b0052610b0090505163313ce567610b20526020610b206004610b3c845afa612589573d5f5f3e3d5ffd5b60203d10612fe857610b20518060081c612fe857610b6052610b609050518060240360248111612fe8579050604d8111612fe85780600a0a90508160051b61072001526001810161070052506108205160078111612fe85761068051634903b0d1610ac052610aa051610ae0526020610ac06024610adc845afa61260f573d5f5f3e3d5ffd5b60203d10612fe857610ac09050518160051b61084001526001810161082052506109405160078111612fe857610aa05161070051811015612fe85760051b6107200151610aa05161082051811015612fe85760051b6108400151808202811583838304141715612fe85790509050670de0b6b3a7640000810490508160051b610960015260018101610940525060010181811861250a575b505061271a565b610680516040526106c0516060526126c7610aa06117c4565b610aa0805160208160051b0180610700828560045afa5050506101208101805160208160051b0180610820828560045afa505050506102408101805160208160051b0180610940828560045afa50505050505b6109405160208160051b018060408261094060045afa5050506106e051610160526106c0516101805261274e610ac0611994565b610ac051610aa0526106a0516318160ddd610ae0526020610ae06004610afc845afa61277c573d5f5f3e3d5ffd5b60203d10612fe857610ae0905051610ac0526108205160208160051b0180610ae08261082060045afa5050505f6106c05160088111612fe857801561285057905b80610c0052610c005161054051811015612fe85760051b6105600151610c20526106605161281757610c0051610ae051811015612fe85760051b610b00018051610c2051808203828111612fe85790509050815250612845565b610c0051610ae051811015612fe85760051b610b00018051610c2051808201828110612fe857905090508152505b6001018181186127bd575b50505f6106c05160088111612fe85780156128dd57905b80610c0052610c005161070051811015612fe85760051b6107200151610c0051610ae051811015612fe85760051b610b000151808202811583838304141715612fe85790509050670de0b6b3a764000081049050610c005161094051811015612fe85760051b6109600152600101818118612867575b50506109405160208160051b018060408261094060045afa5050506106e051610160526106c05161018052612913610c20611994565b610c2051610c0052610c0051610c2052604036610c4037610ac05115612d03576106805163ddca3f43610ca0526020610ca06004610cbc845afa612959573d5f5f3e3d5ffd5b60203d10612fe857610ca09050516106c051808202811583838304141715612fe857905090506106c05160018103818111612fe85790508060021b818160021c18612fe85790508015612fe85780820490509050610c8052610a8051156129f35761068051638edfdd5f610ca0526020610ca06004610cbc845afa6129e0573d5f5f3e3d5ffd5b60203d10612fe857610ca0905051610c40525b5f610ca052610aa051610c0051808201828110612fe857905090506106c0518015612fe85780820490509050610cc0525f6106c05160088111612fe8578015612c3357905b80610ce052610c0051610ce05161082051811015612fe85760051b6108400151808202811583838304141715612fe85790509050610aa0518015612fe85780820490509050610d00525f610d2052610ce051610ae051811015612fe85760051b610b000151610d4052610d4051610d005111612acd57610d4051610d0051808203828111612fe85790509050610d2052612ae8565b610d0051610d4051808203828111612fe85790509050610d20525b610ce05161070051811015612fe85760051b6107200151610ce05161082051811015612fe85760051b6108400151610d4051808201828110612fe85790509050808202811583838304141715612fe85790509050670de0b6b3a764000081049050610ca052610a8051612ba957610ce051610ae051811015612fe85760051b610b00018051610c8051610d2051808202811583838304141715612fe857905090506402540be40081049050808203828111612fe85790509050815250612c28565b610ca051604052610cc051606052610c8051608052610c405160a052612bd0610d60611c10565b610d6051610c6052610ce051610ae051811015612fe85760051b610b00018051610c6051610d2051808202811583838304141715612fe857905090506402540be40081049050808203828111612fe857905090508152505b600101818118612a38575b50505f6106c05160088111612fe8578015612cc057905b80610ce052610ce05161070051811015612fe85760051b6107200151610ce051610ae051811015612fe85760051b610b000151808202811583838304141715612fe85790509050670de0b6b3a764000081049050610ce05161094051811015612fe85760051b6109600152600101818118612c4a575b50506109405160208160051b018060408261094060045afa5050506106e051610160526106c05161018052612cf6610ce0611994565b610ce051610c2052612d0f565b610c0051815250612d87565b5f610c805261066051612d3b57610aa051610c2051808203828111612fe85790509050610c8052612d56565b610c2051610aa051808203828111612fe85790509050610c80525b610c8051610ac051808202811583838304141715612fe85790509050610aa0518015612fe857808204905090508152505b565b61010036610ee0376008610ec052610e0051610e2051610ec051811015612fe85760051b610ee00152610ec05160208160051b018061054082610ec060045afa505050610ea05161066052610e605161068052610e80516106a052610e40516106c052612df7610fe0612443565b610fe051815250565b6102a05180607f1c612fe8576102c0525f6101405112612fe8576102c051610140511215612fe8576060366102e0376102805161034052610120516102a051808202811583838304141715612fe85790509050610360525f6008905b80610380526102a0516103805118612e7357612f1a565b610140515f8112612fe8576103805114612f0f576103805161016051811015612fe85760051b610180015161030052612eab56612f0f565b6102e05161030051808201828110612fe857905090506102e0526103405161028051808202811583838304141715612fe85790509050610300516102a051808202811583838304141715612fe857905090508015612fe85780820490509050610340525b600101818118612e5c575b50506103405161028051808202811583838304141715612fe8579050905060648102816064820418612fe8579050610360516102a051808202811583838304141715612fe857905090508015612fe85780820490509050610340526102e0516102805160648102816064820418612fe8579050610360518015612fe85780820490509050808201828110612fe8579050905061038052610280516103a0526103805160405261034051606052610280516080526103a05160a052612fdf6103c0611cfd565b6103c051815250565b5f80fd17c00c300f66083b009a11f60018

Verified Source Code Partial Match

Compiler: v0.3.10+commit.91361694
CurveStableSwapNGViews.vy 704 lines
# pragma version 0.3.10
# pragma evm-version shanghai
"""
@title CurveStableSwapNGViews
@author Curve.Fi
@license Copyright (c) Curve.Fi, 2020-2023 - all rights reserved
@notice Auxiliary contract for Stableswap-NG containing utility methods for
        integrators
"""

from vyper.interfaces import ERC20Detailed

interface StableSwapNG:
    def N_COINS() -> uint256: view
    def BASE_POOL() -> address: view
    def BASE_N_COINS() -> uint256: view
    def stored_rates() -> DynArray[uint256, MAX_COINS]: view
    def balances(i: uint256) -> uint256: view
    def get_balances() -> DynArray[uint256, MAX_COINS]: view
    def fee() -> uint256: view
    def get_dy(i: int128, j: int128, dx: uint256) -> uint256: view
    def A() -> uint256: view
    def calc_withdraw_one_coin(_token_amount: uint256, i: int128) -> uint256: view
    def totalSupply() -> uint256: view
    def offpeg_fee_multiplier() -> uint256: view
    def coins(i: uint256) -> address: view

A_PRECISION: constant(uint256) = 100
MAX_COINS: constant(uint256) = 8
PRECISION: constant(uint256) = 10 ** 18
FEE_DENOMINATOR: constant(uint256) = 10 ** 10


VERSION: public(constant(String[8])) = "1.2.0"
# first version was: 0xe0B15824862f3222fdFeD99FeBD0f7e0EC26E1FA (ethereum mainnet)
# second version was: 0x13526206545e2DC7CcfBaF28dC88F440ce7AD3e0 (ethereum mainnet)


# ------------------------------ Public Getters ------------------------------


@view
@external
def get_dx(i: int128, j: int128, dy: uint256, pool: address) -> uint256:
    """
    @notice Calculate the current input dx given output dy
    @dev Index values can be found via the `coins` public getter method
    @param i Index value for the coin to send
    @param j Index valie of the coin to recieve
    @param dy Amount of `j` being received after exchange
    @return Amount of `i` predicted
    """
    N_COINS: uint256 = StableSwapNG(pool).N_COINS()
    return self._get_dx(i, j, dy, pool, False, N_COINS)


@view
@external
def get_dy(i: int128, j: int128, dx: uint256, pool: address) -> uint256:
    """
    @notice Calculate the current output dy given input dx
    @dev Index values can be found via the `coins` public getter method
    @param i Index value for the coin to send
    @param j Index valie of the coin to recieve
    @param dx Amount of `i` being exchanged
    @return Amount of `j` predicted
    """
    N_COINS: uint256 = StableSwapNG(pool).N_COINS()

    rates: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    balances: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    xp: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    rates, balances, xp = self._get_rates_balances_xp(pool, N_COINS)

    amp: uint256 = StableSwapNG(pool).A() * A_PRECISION
    D: uint256 = self.get_D(xp, amp, N_COINS)

    x: uint256 = xp[i] + (dx * rates[i] / PRECISION)
    y: uint256 = self.get_y(i, j, x, xp, amp, D, N_COINS)
    dy: uint256 = xp[j] - y - 1

    base_fee: uint256 = StableSwapNG(pool).fee()
    fee_multiplier: uint256 = StableSwapNG(pool).offpeg_fee_multiplier()
    fee: uint256 = self._dynamic_fee((xp[i] + x) / 2, (xp[j] + y) / 2, base_fee, fee_multiplier) * dy / FEE_DENOMINATOR

    return (dy - fee) * PRECISION / rates[j]


@view
@external
def get_dx_underlying(
    i: int128,
    j: int128,
    dy: uint256,
    pool: address,
) -> uint256:

    BASE_POOL: address = StableSwapNG(pool).BASE_POOL()
    BASE_N_COINS: uint256 = StableSwapNG(pool).BASE_N_COINS()
    N_COINS: uint256 = StableSwapNG(pool).N_COINS()
    base_pool_has_static_fee: bool = self._has_static_fee(BASE_POOL)
    base_pool_lp_token: address = StableSwapNG(pool).coins(1)

    # CASE 1: Swap does not involve Metapool at all. In this case, we kindly ask the user
    # to use the right pool for their swaps.
    if min(i, j) > 0:
        raise "Not a Metapool Swap. Use Base pool."

    # CASE 2:
    #    1. meta token_0 of (unknown amount) > base pool lp_token
    #    2. base pool lp_token > calc_withdraw_one_coin gives dy amount of (j-1)th base coin
    # So, need to do the following calculations:
    #    1. calc_token_amounts on base pool for depositing liquidity on (j-1)th token > lp_tokens.
    #    2. get_dx on metapool for i = 0, and j = 1 (base lp token) with amt calculated in (1).
    if i == 0:
        # Calculate LP tokens that are burnt to receive dy amount of base_j tokens.
        lp_amount_burnt: uint256 = self._base_calc_token_amount(
            dy, j - 1, BASE_N_COINS, BASE_POOL, base_pool_lp_token, False,
        )
        return self._get_dx(0, 1, lp_amount_burnt, pool, False, N_COINS)

    # CASE 3: Swap in token i-1 from base pool and swap out dy amount of token 0 (j) from metapool.
    #    1. deposit i-1 token from base pool > receive base pool lp_token
    #    2. swap base pool lp token > 0th token of the metapool
    # So, need to do the following calculations:
    #    1. get_dx on metapool with i = 0, j = 1 > gives how many base lp tokens are required for receiving
    #       dy amounts of i-1 tokens from the metapool
    #    2. We have number of lp tokens: how many i-1 base pool coins are needed to mint that many tokens?
    #       We don't have a method where user inputs lp tokens and it gives number of coins of (i-1)th token
    #       is needed to mint that many base_lp_tokens. Instead, we will use calc_withdraw_one_coin. That's
    #       close enough.
    lp_amount_required: uint256 = self._get_dx(1, 0, dy, pool, False, N_COINS)
    return StableSwapNG(BASE_POOL).calc_withdraw_one_coin(lp_amount_required, i-1)


@view
@external
def get_dy_underlying(
    i: int128,
    j: int128,
    dx: uint256,
    pool: address,
) -> uint256:
    """
    @notice Calculate the current output dy given input dx on underlying
    @dev Index values can be found via the `coins` public getter method
    @param i Index value for the coin to send
    @param j Index valie of the coin to recieve
    @param dx Amount of `i` being exchanged
    @return Amount of `j` predicted
    """

    N_COINS: uint256 = StableSwapNG(pool).N_COINS()
    MAX_COIN: int128 = convert(N_COINS, int128) - 1
    BASE_POOL: address = StableSwapNG(pool).BASE_POOL()
    base_lp_token: address = StableSwapNG(pool).coins(1)

    rates: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    balances: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    xp: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    rates, balances, xp = self._get_rates_balances_xp(pool, N_COINS)

    x: uint256 = 0
    base_i: int128 = 0
    base_j: int128 = 0
    meta_i: int128 = 0
    meta_j: int128 = 0

    if i != 0:
        base_i = i - MAX_COIN
        meta_i = 1
    if j != 0:
        base_j = j - MAX_COIN
        meta_j = 1

    if i == 0:

        x = xp[i] + dx * rates[0] / 10**18

    else:

        if j == 0:

            # i is from BasePool
            base_n_coins: uint256 = StableSwapNG(pool).BASE_N_COINS()
            x = self._base_calc_token_amount(
                dx,
                base_i,
                base_n_coins,
                BASE_POOL,
                base_lp_token,
                True,
            ) * rates[1] / PRECISION

            # Adding number of pool tokens
            x += xp[1]

        else:
            # If both are from the base pool
            return StableSwapNG(BASE_POOL).get_dy(base_i, base_j, dx)

    # This pool is involved only when in-pool assets are used
    amp: uint256 = StableSwapNG(pool).A() * A_PRECISION
    D: uint256 = self.get_D(xp, amp, N_COINS)
    y: uint256 = self.get_y(meta_i, meta_j, x, xp, amp, D, N_COINS)
    dy: uint256 = xp[meta_j] - y - 1

    # calculate output after subtracting dynamic fee
    base_fee: uint256 = StableSwapNG(pool).fee()
    fee_multiplier: uint256 = StableSwapNG(pool).offpeg_fee_multiplier()

    dynamic_fee: uint256 = self._dynamic_fee((xp[meta_i] + x) / 2, (xp[meta_j] + y) / 2, base_fee, fee_multiplier)
    dy = (dy - dynamic_fee * dy / FEE_DENOMINATOR)

    # If output is going via the metapool
    if j == 0:
        dy = dy * 10**18 / rates[0]
    else:
        # j is from BasePool
        # The fee is already accounted for
        dy = StableSwapNG(BASE_POOL).calc_withdraw_one_coin(dy * PRECISION / rates[1], base_j)

    return dy


@view
@external
def calc_token_amount(
    _amounts: DynArray[uint256, MAX_COINS],
    _is_deposit: bool,
    pool: address
) -> uint256:
    """
    @notice Calculate addition or reduction in token supply from a deposit or withdrawal
    @dev Only works for StableswapNG pools and not legacy versions
    @param _amounts Amount of each coin being deposited
    @param _is_deposit set True for deposits, False for withdrawals
    @return Expected amount of LP tokens received
    """

    return self._calc_token_amount(
        _amounts,
        _is_deposit,
        pool,
        pool,
        StableSwapNG(pool).N_COINS()
    )


@view
@external
def calc_withdraw_one_coin(_burn_amount: uint256, i: int128, pool: address) -> uint256:
    # First, need to calculate
    # * Get current D
    # * Solve Eqn against y_i for D - _token_amount

    amp: uint256 = StableSwapNG(pool).A() * A_PRECISION
    N_COINS: uint256 = StableSwapNG(pool).N_COINS()

    rates: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    balances: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    xp: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    rates, balances, xp = self._get_rates_balances_xp(pool, N_COINS)

    D0: uint256 = self.get_D(xp, amp, N_COINS)

    total_supply: uint256 = StableSwapNG(pool).totalSupply()
    D1: uint256 = D0 - _burn_amount * D0 / total_supply
    new_y: uint256 = self.get_y_D(amp, i, xp, D1, N_COINS)
    ys: uint256 = (D0 + D1) / (2 * N_COINS)

    base_fee: uint256 = StableSwapNG(pool).fee() * N_COINS / (4 * (N_COINS - 1))
    fee_multiplier: uint256 = StableSwapNG(pool).offpeg_fee_multiplier()
    xp_reduced: DynArray[uint256, MAX_COINS] = xp
    xp_j: uint256 = 0
    xavg: uint256 = 0
    dynamic_fee: uint256 = 0

    for j in range(MAX_COINS):

        if j == N_COINS:
            break

        dx_expected: uint256 = 0
        xp_j = xp[j]
        if convert(j, int128) == i:
            dx_expected = xp_j * D1 / D0 - new_y
            xavg = (xp[j] + new_y) / 2
        else:
            dx_expected = xp_j - xp_j * D1 / D0
            xavg = xp[j]

        dynamic_fee = self._dynamic_fee(xavg, ys, base_fee, fee_multiplier)
        xp_reduced[j] = xp_j - dynamic_fee * dx_expected / FEE_DENOMINATOR

    dy: uint256 = xp_reduced[i] - self.get_y_D(amp, i, xp_reduced, D1, N_COINS)
    dy = (dy - 1) * PRECISION / rates[i]  # Withdraw less to account for rounding errors

    return dy


@view
@external
def dynamic_fee(i: int128, j: int128, pool:address) -> uint256:
    """
    @notice Return the fee for swapping between `i` and `j`
    @param i Index value for the coin to send
    @param j Index value of the coin to recieve
    @return Swap fee expressed as an integer with 1e10 precision
    """
    N_COINS: uint256 = StableSwapNG(pool).N_COINS()
    fee: uint256 = StableSwapNG(pool).fee()
    fee_multiplier: uint256 = StableSwapNG(pool).offpeg_fee_multiplier()

    rates: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    balances: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    xp: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    rates, balances, xp = self._get_rates_balances_xp(pool, N_COINS)

    return self._dynamic_fee(xp[i], xp[j], fee, fee_multiplier)


# ----------------------------- Utility Methods ------------------------------


@view
@internal
def _has_static_fee(pool: address) -> bool:

    success: bool = False
    response: Bytes[32] = b""
    success, response = raw_call(
        pool,
        concat(
            method_id("dynamic_fee(int128,int128)"),
            convert(1, bytes32),
            convert(0, bytes32)
        ),
        max_outsize=32,
        revert_on_failure=False,
        is_static_call=True
    )

    return success


@view
@internal
def _get_dx(
    i: int128,
    j: int128,
    dy: uint256,
    pool: address,
    static_fee: bool,
    N_COINS: uint256
) -> uint256:

    rates: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    balances: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    xp: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    rates, balances, xp = self._get_rates_balances_xp(pool, N_COINS)

    amp: uint256 = StableSwapNG(pool).A() * A_PRECISION
    D: uint256 = self.get_D(xp, amp, N_COINS)

    base_fee: uint256 = StableSwapNG(pool).fee()
    dy_with_fee: uint256 = dy * rates[j] / PRECISION + 1

    fee: uint256 = base_fee
    if not static_fee:
        fee_multiplier: uint256 = StableSwapNG(pool).offpeg_fee_multiplier()
        fee = self._dynamic_fee(xp[i], xp[j], base_fee, fee_multiplier)

    y: uint256 = xp[j] - dy_with_fee * FEE_DENOMINATOR / (FEE_DENOMINATOR - fee)
    x: uint256 = self.get_y(j, i, y, xp, amp, D, N_COINS)
    return (x - xp[i]) * PRECISION / rates[i]


@view
@internal
def _dynamic_fee(xpi: uint256, xpj: uint256, _fee: uint256, _fee_multiplier: uint256) -> uint256:

    if _fee_multiplier <= FEE_DENOMINATOR:
        return _fee

    xps2: uint256 = (xpi + xpj) ** 2
    return (
        (_fee_multiplier * _fee) /
        ((_fee_multiplier - FEE_DENOMINATOR) * 4 * xpi * xpj / xps2 + FEE_DENOMINATOR)
    )


@internal
@view
def _calc_token_amount(
    _amounts: DynArray[uint256, MAX_COINS],
    _is_deposit: bool,
    pool: address,
    pool_lp_token: address,
    n_coins: uint256,
) -> uint256:

    amp: uint256 = StableSwapNG(pool).A() * A_PRECISION

    rates: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    old_balances: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    xp: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])

    pool_is_ng: bool = raw_call(
        pool,
        method_id("D_ma_time()"),
        revert_on_failure=False,
        is_static_call=True
    )
    use_dynamic_fees: bool = True
    if pool_is_ng:
        rates, old_balances, xp = self._get_rates_balances_xp(pool, n_coins)
    else:
        use_dynamic_fees = False
        for i in range(n_coins, bound=MAX_COINS):
            rates.append(
                10 ** (36 - convert(ERC20Detailed(StableSwapNG(pool).coins(i)).decimals(), uint256))
            )
            old_balances.append(StableSwapNG(pool).balances(i))
            xp.append(rates[i] * old_balances[i] / PRECISION)

    # Initial invariant
    D0: uint256 = self.get_D(xp, amp, n_coins)

    total_supply: uint256 = StableSwapNG(pool_lp_token).totalSupply()
    new_balances: DynArray[uint256, MAX_COINS] = old_balances
    for i in range(n_coins, bound=MAX_COINS):
        amount: uint256 = _amounts[i]
        if _is_deposit:
            new_balances[i] += amount
        else:
            new_balances[i] -= amount

    # Invariant after change
    for idx in range(n_coins, bound=MAX_COINS):
        xp[idx] = rates[idx] * new_balances[idx] / PRECISION
    D1: uint256 = self.get_D(xp, amp, n_coins)

    # We need to recalculate the invariant accounting for fees
    # to calculate fair user's share
    D2: uint256 = D1
    fee_multiplier: uint256 = 0
    _dynamic_fee_i: uint256 = 0
    if total_supply > 0:

        # Only account for fees if we are not the first to deposit
        base_fee: uint256 = StableSwapNG(pool).fee() * n_coins / (4 * (n_coins - 1))
        if use_dynamic_fees:
            fee_multiplier = StableSwapNG(pool).offpeg_fee_multiplier()

        xs: uint256 = 0
        ys: uint256 = (D0 + D1) / n_coins

        for i in range(n_coins, bound=MAX_COINS):

            ideal_balance: uint256 = D1 * old_balances[i] / D0
            difference: uint256 = 0
            new_balance: uint256 = new_balances[i]
            if ideal_balance > new_balance:
                difference = ideal_balance - new_balance
            else:
                difference = new_balance - ideal_balance

            xs = rates[i] * (old_balances[i] + new_balance) / PRECISION

            # use dynamic fees only if pool is NG
            if use_dynamic_fees:
                _dynamic_fee_i = self._dynamic_fee(xs, ys, base_fee, fee_multiplier)
                new_balances[i] -= _dynamic_fee_i * difference / FEE_DENOMINATOR
            else:
                new_balances[i] -= base_fee * difference / FEE_DENOMINATOR

        for idx in range(n_coins, bound=MAX_COINS):
            xp[idx] = rates[idx] * new_balances[idx] / PRECISION

        D2 = self.get_D(xp, amp, n_coins)
    else:
        return D1  # Take the dust if there was any

    diff: uint256 = 0
    if _is_deposit:
        diff = D2 - D0
    else:
        diff = D0 - D2
    return diff * total_supply / D0


@internal
@view
def _base_calc_token_amount(
    dx: uint256,
    base_i: int128,
    base_n_coins: uint256,
    base_pool: address,
    base_pool_lp_token: address,
    is_deposit: bool,
) -> uint256:

    base_inputs: DynArray[uint256, MAX_COINS] = [0, 0, 0, 0, 0, 0, 0, 0]
    base_inputs[base_i] = dx

    return self._calc_token_amount(
        base_inputs,
        is_deposit,
        base_pool,
        base_pool_lp_token,
        base_n_coins
    )


@internal
@pure
def newton_y(b: uint256, c: uint256, D: uint256, _y: uint256) -> uint256:

    y_prev: uint256 = 0
    y: uint256 = _y

    for _i in range(255):
        y_prev = y
        y = (y*y + c) / (2 * y + b - D)
        # Equality with the precision of 1
        if y > y_prev:
            if y - y_prev <= 1:
                return y
        else:
            if y_prev - y <= 1:
                return y
    raise


@view
@internal
def get_y(
    i: int128,
    j: int128,
    x: uint256,
    xp: DynArray[uint256, MAX_COINS],
    _amp: uint256,
    _D: uint256,
    N_COINS: uint256
) -> uint256:
    """
    Calculate x[j] if one makes x[i] = x

    Done by solving quadratic equation iteratively.
    x_1**2 + x_1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)
    x_1**2 + b*x_1 = c

    x_1 = (x_1**2 + c) / (2*x_1 + b)
    """
    # x in the input is converted to the same price/precision

    assert i != j       # dev: same coin
    assert j >= 0       # dev: j below zero
    assert j < convert(N_COINS, int128)  # dev: j above N_COINS

    # should be unreachable, but good for safety
    assert i >= 0
    assert i < convert(N_COINS, int128)

    amp: uint256 = _amp
    D: uint256 = _D
    S_: uint256 = 0
    _x: uint256 = 0
    c: uint256 = D
    Ann: uint256 = amp * N_COINS

    for _i in range(MAX_COINS):

        if _i == N_COINS:
            break

        if  convert(_i, int128) == i:
            _x = x
        elif convert(_i, int128) != j:
            _x = xp[_i]
        else:
            continue
        S_ += _x
        c = c * D / (_x * N_COINS)

    c = c * D * A_PRECISION / (Ann * N_COINS)
    b: uint256 = S_ + D * A_PRECISION / Ann  # - D
    y: uint256 = D

    return self.newton_y(b, c, D, y)


@pure
@internal
def get_D(_xp: DynArray[uint256, MAX_COINS], _amp: uint256, N_COINS: uint256) -> uint256:
    """
    D invariant calculation in non-overflowing integer operations
    iteratively

    A * sum(x_i) * n**n + D = A * D * n**n + D**(n+1) / (n**n * prod(x_i))

    Converging solution:
    D[j+1] = (A * n**n * sum(x_i) - D[j]**(n+1) / (n**n prod(x_i))) / (A * n**n - 1)
    """
    S: uint256 = 0
    for i in range(MAX_COINS):
        if i == N_COINS:
            break
        S += _xp[i]

    if S == 0:
        return 0

    D: uint256 = S
    Ann: uint256 = _amp * N_COINS

    for i in range(255):

        D_P: uint256 = D
        for x in _xp:
            D_P = D_P * D / x
        D_P /= pow_mod256(N_COINS, N_COINS)
        Dprev: uint256 = D

        D = (Ann * S / A_PRECISION + D_P * N_COINS) * D / ((Ann - A_PRECISION) * D / A_PRECISION + (N_COINS + 1) * D_P)
        # Equality with the precision of 1
        if D > Dprev:
            if D - Dprev <= 1:
                return D
        else:
            if Dprev - D <= 1:
                return D
    # convergence typically occurs in 4 rounds or less, this should be unreachable!
    # if it does happen the pool is borked and LPs can withdraw via `remove_liquidity`
    raise


@pure
@internal
def get_y_D(
    A: uint256,
    i: int128,
    xp: DynArray[uint256, MAX_COINS],
    D: uint256,
    N_COINS: uint256
) -> uint256:
    """
    Calculate x[i] if one reduces D from being calculated for xp to D

    Done by solving quadratic equation iteratively.
    x_1**2 + x_1 * (sum' - (A*n**n - 1) * D / (A * n**n)) = D ** (n + 1) / (n ** (2 * n) * prod' * A)
    x_1**2 + b*x_1 = c

    x_1 = (x_1**2 + c) / (2*x_1 + b)
    """
    # x in the input is converted to the same price/precision

    N_COINS_128: int128 = convert(N_COINS, int128)
    assert i >= 0  # dev: i below zero
    assert i < N_COINS_128  # dev: i above N_COINS

    S_: uint256 = 0
    _x: uint256 = 0
    y_prev: uint256 = 0
    c: uint256 = D
    Ann: uint256 = A * N_COINS

    for _i in range(MAX_COINS):

        if _i == N_COINS:
            break

        if _i != convert(i, uint256):
            _x = xp[_i]
        else:
            continue
        S_ += _x
        c = c * D / (_x * N_COINS)

    c = c * D * A_PRECISION / (Ann * N_COINS)
    b: uint256 = S_ + D * A_PRECISION / Ann
    y: uint256 = D

    return self.newton_y(b, c, D, y)


@view
@internal
def _get_rates_balances_xp(pool: address, N_COINS: uint256) -> (
    DynArray[uint256, MAX_COINS],
    DynArray[uint256, MAX_COINS],
    DynArray[uint256, MAX_COINS],
):

    rates: DynArray[uint256, MAX_COINS] = StableSwapNG(pool).stored_rates()
    balances: DynArray[uint256, MAX_COINS] = StableSwapNG(pool).get_balances()
    xp: DynArray[uint256, MAX_COINS] = empty(DynArray[uint256, MAX_COINS])
    for idx in range(MAX_COINS):
        if idx == N_COINS:
            break
        xp.append(rates[idx] * balances[idx] / PRECISION)

    return rates, balances, xp

Read Contract

VERSION 0xffa1ad74 → string
calc_token_amount 0xfb79eb27 → uint256
calc_withdraw_one_coin 0xb54e9f05 → uint256
dynamic_fee 0xa63530bd → uint256
get_dx 0x83aa796a → uint256
get_dx_underlying 0xd6fc10ab → uint256
get_dy 0x0c601c2c → uint256
get_dy_underlying 0xc02c60a6 → uint256

Recent Transactions

This address has 1 on-chain transactions, but only 0.8% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →