diff --git a/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/batch_request/GetCurveCryptoPoolDataBatchRequestABI.json b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/batch_request/GetCurveCryptoPoolDataBatchRequestABI.json new file mode 100644 index 000000000..3a23889ab --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/batch_request/GetCurveCryptoPoolDataBatchRequestABI.json @@ -0,0 +1,58 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "address[]", + "name": "pools", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "asset_length", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + } + ], + "name": "CurvePoolData", + "metadata": "{\"compiler\":{\"version\":\"0.8.24+commit.e11b9ed9\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"pools\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"asset_length\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/1_Storage.sol\":\"CurvePoolData\"},\"evmVersion\":\"shanghai\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/1_Storage.sol\":{\"keccak256\":\"0x6f320df6ec319760eb59f32d8efccd1f048ebf92e820a3b93534362563ce9dce\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f9be1df587bbde192ccc73d24b6936da920356bcf374c3c7444cf91397d4cbac\",\"dweb:/ipfs/QmQaGtHXbzYhXkBAMPJ32WGzQx9wBVwVM2yu6FsdfCyfrW\"]}},\"version\":1}", + "bytecode": { + "linkReferences": {}, + "object": "608060405234801561000f575f80fd5b50604051610dab380380610dab83398181016040528101906100319190610894565b5f825167ffffffffffffffff81111561004d5761004c61060b565b5b60405190808252806020026020018201604052801561008657816020015b6100736105b3565b81526020019060019003908161006b5790505b5090505f5b8351811015610585575f5b8382815181106100a9576100a861090a565b5b6020026020010151811015610379578482815181106100cb576100ca61090a565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663c6610657826040518263ffffffff1660e01b815260040161010b9190610946565b602060405180830381865afa158015610126573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061014a919061095f565b83838151811061015d5761015c61090a565b5b60200260200101515f0151828151811061017a5761017961090a565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508282815181106101c7576101c661090a565b5b60200260200101515f015181815181106101e4576101e361090a565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610234573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061025891906109c0565b83838151811061026b5761026a61090a565b5b60200260200101516020015182815181106102895761028861090a565b5b602002602001019060ff16908160ff16815250508482815181106102b0576102af61090a565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16634903b0d1826040518263ffffffff1660e01b81526004016102f09190610946565b602060405180830381865afa15801561030b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032f91906109eb565b8383815181106103425761034161090a565b5b60200260200101516060015182815181106103605761035f61090a565b5b6020026020010181815250508080600101915050610096565b5083818151811061038d5761038c61090a565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103dd573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061040191906109eb565b8282815181106104145761041361090a565b5b602002602001015160400181815250508381815181106104375761043661090a565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663f446c1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610487573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ab91906109eb565b8282815181106104be576104bd61090a565b5b602002602001015160800181815250508381815181106104e1576104e061090a565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663b13739296040518163ffffffff1660e01b8152600401602060405180830381865afa158015610531573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061055591906109eb565b8282815181106105685761056761090a565b5b602002602001015160a0018181525050808060010191505061008b565b505f816040516020016105989190610d8a565b60405160208183030381529060405290506020810180590381f35b6040518060c0016040528060608152602001606081526020015f8152602001606081526020015f81526020015f81525090565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b610641826105fb565b810181811067ffffffffffffffff821117156106605761065f61060b565b5b80604052505050565b5f6106726105e6565b905061067e8282610638565b919050565b5f67ffffffffffffffff82111561069d5761069c61060b565b5b602082029050602081019050919050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6106db826106b2565b9050919050565b6106eb816106d1565b81146106f5575f80fd5b50565b5f81519050610706816106e2565b92915050565b5f61071e61071984610683565b610669565b90508083825260208201905060208402830185811115610741576107406106ae565b5b835b8181101561076a578061075688826106f8565b845260208401935050602081019050610743565b5050509392505050565b5f82601f830112610788576107876105f7565b5b815161079884826020860161070c565b91505092915050565b5f67ffffffffffffffff8211156107bb576107ba61060b565b5b602082029050602081019050919050565b5f819050919050565b6107de816107cc565b81146107e8575f80fd5b50565b5f815190506107f9816107d5565b92915050565b5f61081161080c846107a1565b610669565b90508083825260208201905060208402830185811115610834576108336106ae565b5b835b8181101561085d578061084988826107eb565b845260208401935050602081019050610836565b5050509392505050565b5f82601f83011261087b5761087a6105f7565b5b815161088b8482602086016107ff565b91505092915050565b5f80604083850312156108aa576108a96105ef565b5b5f83015167ffffffffffffffff8111156108c7576108c66105f3565b5b6108d385828601610774565b925050602083015167ffffffffffffffff8111156108f4576108f36105f3565b5b61090085828601610867565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b610940816107cc565b82525050565b5f6020820190506109595f830184610937565b92915050565b5f60208284031215610974576109736105ef565b5b5f610981848285016106f8565b91505092915050565b5f60ff82169050919050565b61099f8161098a565b81146109a9575f80fd5b50565b5f815190506109ba81610996565b92915050565b5f602082840312156109d5576109d46105ef565b5b5f6109e2848285016109ac565b91505092915050565b5f60208284031215610a00576109ff6105ef565b5b5f610a0d848285016107eb565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610a71816106d1565b82525050565b5f610a828383610a68565b60208301905092915050565b5f602082019050919050565b5f610aa482610a3f565b610aae8185610a49565b9350610ab983610a59565b805f5b83811015610ae9578151610ad08882610a77565b9750610adb83610a8e565b925050600181019050610abc565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610b288161098a565b82525050565b5f610b398383610b1f565b60208301905092915050565b5f602082019050919050565b5f610b5b82610af6565b610b658185610b00565b9350610b7083610b10565b805f5b83811015610ba0578151610b878882610b2e565b9750610b9283610b45565b925050600181019050610b73565b5085935050505092915050565b610bb6816107cc565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f610bf08383610bad565b60208301905092915050565b5f602082019050919050565b5f610c1282610bbc565b610c1c8185610bc6565b9350610c2783610bd6565b805f5b83811015610c57578151610c3e8882610be5565b9750610c4983610bfc565b925050600181019050610c2a565b5085935050505092915050565b5f60c083015f8301518482035f860152610c7e8282610a9a565b91505060208301518482036020860152610c988282610b51565b9150506040830151610cad6040860182610bad565b5060608301518482036060860152610cc58282610c08565b9150506080830151610cda6080860182610bad565b5060a0830151610ced60a0860182610bad565b508091505092915050565b5f610d038383610c64565b905092915050565b5f602082019050919050565b5f610d2182610a16565b610d2b8185610a20565b935083602082028501610d3d85610a30565b805f5b85811015610d785784840389528151610d598582610cf8565b9450610d6483610d0b565b925060208a01995050600181019050610d40565b50829750879550505050505092915050565b5f6020820190508181035f830152610da28184610d17565b90509291505056fe", + "sourceMap": "513:1088:0:-:0;;;729:870;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;806:26;850:5;:12;835:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;806:57;;878:6;873:502;891:5;:12;888:1;:15;873:502;;;929:9;924:284;944:12;957:1;944:15;;;;;;;;:::i;:::-;;;;;;;;942:1;:17;924:284;;;1015:5;1021:1;1015:8;;;;;;;;:::i;:::-;;;;;;;;1009:21;;;1031:1;1009:24;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;985:8;994:1;985:11;;;;;;;;:::i;:::-;;;;;;;;:18;;;1004:1;985:21;;;;;;;;:::i;:::-;;;;;;;:48;;;;;;;;;;;1089:8;1098:1;1089:11;;;;;;;;:::i;:::-;;;;;;;;:18;;;1108:1;1089:21;;;;;;;;:::i;:::-;;;;;;;;1082:38;;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1051:8;1060:1;1051:11;;;;;;;;:::i;:::-;;;;;;;;:25;;;1077:1;1051:28;;;;;;;;:::i;:::-;;;;;;;:71;;;;;;;;;;;1172:5;1178:1;1172:8;;;;;;;;:::i;:::-;;;;;;;;1166:24;;;1191:1;1166:27;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1140:8;1149:1;1140:11;;;;;;;;:::i;:::-;;;;;;;;:20;;;1161:1;1140:23;;;;;;;;:::i;:::-;;;;;;;:53;;;;;961:3;;;;;;;924:284;;;;1241:5;1247:1;1241:8;;;;;;;;:::i;:::-;;;;;;;;1235:19;;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1217:8;1226:1;1217:11;;;;;;;;:::i;:::-;;;;;;;;:15;;:39;;;;;1293:5;1299:1;1293:8;;;;;;;;:::i;:::-;;;;;;;;1287:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1266:8;1275:1;1266:11;;;;;;;;:::i;:::-;;;;;;;;:18;;:40;;;;;1347:5;1353:1;1347:8;;;;;;;;:::i;:::-;;;;;;;;1341:21;;;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1316:8;1325:1;1316:11;;;;;;;;:::i;:::-;;;;;;;;:22;;:48;;;;;905:3;;;;;;;873:502;;;;1402:27;1443:8;1432:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;1402:50;;1523:4;1507:14;1503:25;1572:9;1563:7;1559:23;1548:9;1541:42;513:1088;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:311::-;1250:4;1340:18;1332:6;1329:30;1326:56;;;1362:18;;:::i;:::-;1326:56;1412:4;1404:6;1400:17;1392:25;;1472:4;1466;1462:15;1454:23;;1173:311;;;:::o;1490:117::-;1599:1;1596;1589:12;1613:126;1650:7;1690:42;1683:5;1679:54;1668:65;;1613:126;;;:::o;1745:96::-;1782:7;1811:24;1829:5;1811:24;:::i;:::-;1800:35;;1745:96;;;:::o;1847:122::-;1920:24;1938:5;1920:24;:::i;:::-;1913:5;1910:35;1900:63;;1959:1;1956;1949:12;1900:63;1847:122;:::o;1975:143::-;2032:5;2063:6;2057:13;2048:22;;2079:33;2106:5;2079:33;:::i;:::-;1975:143;;;;:::o;2141:732::-;2248:5;2273:81;2289:64;2346:6;2289:64;:::i;:::-;2273:81;:::i;:::-;2264:90;;2374:5;2403:6;2396:5;2389:21;2437:4;2430:5;2426:16;2419:23;;2490:4;2482:6;2478:17;2470:6;2466:30;2519:3;2511:6;2508:15;2505:122;;;2538:79;;:::i;:::-;2505:122;2653:6;2636:231;2670:6;2665:3;2662:15;2636:231;;;2745:3;2774:48;2818:3;2806:10;2774:48;:::i;:::-;2769:3;2762:61;2852:4;2847:3;2843:14;2836:21;;2712:155;2696:4;2691:3;2687:14;2680:21;;2636:231;;;2640:21;2254:619;;2141:732;;;;;:::o;2896:385::-;2978:5;3027:3;3020:4;3012:6;3008:17;3004:27;2994:122;;3035:79;;:::i;:::-;2994:122;3145:6;3139:13;3170:105;3271:3;3263:6;3256:4;3248:6;3244:17;3170:105;:::i;:::-;3161:114;;2984:297;2896:385;;;;:::o;3287:311::-;3364:4;3454:18;3446:6;3443:30;3440:56;;;3476:18;;:::i;:::-;3440:56;3526:4;3518:6;3514:17;3506:25;;3586:4;3580;3576:15;3568:23;;3287:311;;;:::o;3604:77::-;3641:7;3670:5;3659:16;;3604:77;;;:::o;3687:122::-;3760:24;3778:5;3760:24;:::i;:::-;3753:5;3750:35;3740:63;;3799:1;3796;3789:12;3740:63;3687:122;:::o;3815:143::-;3872:5;3903:6;3897:13;3888:22;;3919:33;3946:5;3919:33;:::i;:::-;3815:143;;;;:::o;3981:732::-;4088:5;4113:81;4129:64;4186:6;4129:64;:::i;:::-;4113:81;:::i;:::-;4104:90;;4214:5;4243:6;4236:5;4229:21;4277:4;4270:5;4266:16;4259:23;;4330:4;4322:6;4318:17;4310:6;4306:30;4359:3;4351:6;4348:15;4345:122;;;4378:79;;:::i;:::-;4345:122;4493:6;4476:231;4510:6;4505:3;4502:15;4476:231;;;4585:3;4614:48;4658:3;4646:10;4614:48;:::i;:::-;4609:3;4602:61;4692:4;4687:3;4683:14;4676:21;;4552:155;4536:4;4531:3;4527:14;4520:21;;4476:231;;;4480:21;4094:619;;3981:732;;;;;:::o;4736:385::-;4818:5;4867:3;4860:4;4852:6;4848:17;4844:27;4834:122;;4875:79;;:::i;:::-;4834:122;4985:6;4979:13;5010:105;5111:3;5103:6;5096:4;5088:6;5084:17;5010:105;:::i;:::-;5001:114;;4824:297;4736:385;;;;:::o;5127:913::-;5256:6;5264;5313:2;5301:9;5292:7;5288:23;5284:32;5281:119;;;5319:79;;:::i;:::-;5281:119;5460:1;5449:9;5445:17;5439:24;5490:18;5482:6;5479:30;5476:117;;;5512:79;;:::i;:::-;5476:117;5617:89;5698:7;5689:6;5678:9;5674:22;5617:89;:::i;:::-;5607:99;;5410:306;5776:2;5765:9;5761:18;5755:25;5807:18;5799:6;5796:30;5793:117;;;5829:79;;:::i;:::-;5793:117;5934:89;6015:7;6006:6;5995:9;5991:22;5934:89;:::i;:::-;5924:99;;5726:307;5127:913;;;;;:::o;6046:180::-;6094:77;6091:1;6084:88;6191:4;6188:1;6181:15;6215:4;6212:1;6205:15;6232:118;6319:24;6337:5;6319:24;:::i;:::-;6314:3;6307:37;6232:118;;:::o;6356:222::-;6449:4;6487:2;6476:9;6472:18;6464:26;;6500:71;6568:1;6557:9;6553:17;6544:6;6500:71;:::i;:::-;6356:222;;;;:::o;6584:351::-;6654:6;6703:2;6691:9;6682:7;6678:23;6674:32;6671:119;;;6709:79;;:::i;:::-;6671:119;6829:1;6854:64;6910:7;6901:6;6890:9;6886:22;6854:64;:::i;:::-;6844:74;;6800:128;6584:351;;;;:::o;6941:86::-;6976:7;7016:4;7009:5;7005:16;6994:27;;6941:86;;;:::o;7033:118::-;7104:22;7120:5;7104:22;:::i;:::-;7097:5;7094:33;7084:61;;7141:1;7138;7131:12;7084:61;7033:118;:::o;7157:139::-;7212:5;7243:6;7237:13;7228:22;;7259:31;7284:5;7259:31;:::i;:::-;7157:139;;;;:::o;7302:347::-;7370:6;7419:2;7407:9;7398:7;7394:23;7390:32;7387:119;;;7425:79;;:::i;:::-;7387:119;7545:1;7570:62;7624:7;7615:6;7604:9;7600:22;7570:62;:::i;:::-;7560:72;;7516:126;7302:347;;;;:::o;7655:351::-;7725:6;7774:2;7762:9;7753:7;7749:23;7745:32;7742:119;;;7780:79;;:::i;:::-;7742:119;7900:1;7925:64;7981:7;7972:6;7961:9;7957:22;7925:64;:::i;:::-;7915:74;;7871:128;7655:351;;;;:::o;8012:138::-;8103:6;8137:5;8131:12;8121:22;;8012:138;;;:::o;8156:208::-;8279:11;8313:6;8308:3;8301:19;8353:4;8348:3;8344:14;8329:29;;8156:208;;;;:::o;8370:156::-;8461:4;8484:3;8476:11;;8514:4;8509:3;8505:14;8497:22;;8370:156;;;:::o;8532:114::-;8599:6;8633:5;8627:12;8617:22;;8532:114;;;:::o;8652:174::-;8741:11;8775:6;8770:3;8763:19;8815:4;8810:3;8806:14;8791:29;;8652:174;;;;:::o;8832:132::-;8899:4;8922:3;8914:11;;8952:4;8947:3;8943:14;8935:22;;8832:132;;;:::o;8970:108::-;9047:24;9065:5;9047:24;:::i;:::-;9042:3;9035:37;8970:108;;:::o;9084:179::-;9153:10;9174:46;9216:3;9208:6;9174:46;:::i;:::-;9252:4;9247:3;9243:14;9229:28;;9084:179;;;;:::o;9269:113::-;9339:4;9371;9366:3;9362:14;9354:22;;9269:113;;;:::o;9418:712::-;9527:3;9556:54;9604:5;9556:54;:::i;:::-;9626:76;9695:6;9690:3;9626:76;:::i;:::-;9619:83;;9726:56;9776:5;9726:56;:::i;:::-;9805:7;9836:1;9821:284;9846:6;9843:1;9840:13;9821:284;;;9922:6;9916:13;9949:63;10008:3;9993:13;9949:63;:::i;:::-;9942:70;;10035:60;10088:6;10035:60;:::i;:::-;10025:70;;9881:224;9868:1;9865;9861:9;9856:14;;9821:284;;;9825:14;10121:3;10114:10;;9532:598;;;9418:712;;;;:::o;10136:112::-;10201:6;10235:5;10229:12;10219:22;;10136:112;;;:::o;10254:172::-;10341:11;10375:6;10370:3;10363:19;10415:4;10410:3;10406:14;10391:29;;10254:172;;;;:::o;10432:130::-;10497:4;10520:3;10512:11;;10550:4;10545:3;10541:14;10533:22;;10432:130;;;:::o;10568:102::-;10641:22;10657:5;10641:22;:::i;:::-;10636:3;10629:35;10568:102;;:::o;10676:171::-;10741:10;10762:42;10800:3;10792:6;10762:42;:::i;:::-;10836:4;10831:3;10827:14;10813:28;;10676:171;;;;:::o;10853:111::-;10921:4;10953;10948:3;10944:14;10936:22;;10853:111;;;:::o;10996:696::-;11101:3;11130:52;11176:5;11130:52;:::i;:::-;11198:74;11265:6;11260:3;11198:74;:::i;:::-;11191:81;;11296:54;11344:5;11296:54;:::i;:::-;11373:7;11404:1;11389:278;11414:6;11411:1;11408:13;11389:278;;;11490:6;11484:13;11517:59;11572:3;11557:13;11517:59;:::i;:::-;11510:66;;11599:58;11650:6;11599:58;:::i;:::-;11589:68;;11449:218;11436:1;11433;11429:9;11424:14;;11389:278;;;11393:14;11683:3;11676:10;;11106:586;;;10996:696;;;;:::o;11698:108::-;11775:24;11793:5;11775:24;:::i;:::-;11770:3;11763:37;11698:108;;:::o;11812:114::-;11879:6;11913:5;11907:12;11897:22;;11812:114;;;:::o;11932:174::-;12021:11;12055:6;12050:3;12043:19;12095:4;12090:3;12086:14;12071:29;;11932:174;;;;:::o;12112:132::-;12179:4;12202:3;12194:11;;12232:4;12227:3;12223:14;12215:22;;12112:132;;;:::o;12250:179::-;12319:10;12340:46;12382:3;12374:6;12340:46;:::i;:::-;12418:4;12413:3;12409:14;12395:28;;12250:179;;;;:::o;12435:113::-;12505:4;12537;12532:3;12528:14;12520:22;;12435:113;;;:::o;12584:712::-;12693:3;12722:54;12770:5;12722:54;:::i;:::-;12792:76;12861:6;12856:3;12792:76;:::i;:::-;12785:83;;12892:56;12942:5;12892:56;:::i;:::-;12971:7;13002:1;12987:284;13012:6;13009:1;13006:13;12987:284;;;13088:6;13082:13;13115:63;13174:3;13159:13;13115:63;:::i;:::-;13108:70;;13201:60;13254:6;13201:60;:::i;:::-;13191:70;;13047:224;13034:1;13031;13027:9;13022:14;;12987:284;;;12991:14;13287:3;13280:10;;12698:598;;;12584:712;;;;:::o;13372:1540::-;13479:3;13515:4;13510:3;13506:14;13604:4;13597:5;13593:16;13587:23;13657:3;13651:4;13647:14;13640:4;13635:3;13631:14;13624:38;13683:103;13781:4;13767:12;13683:103;:::i;:::-;13675:111;;13530:267;13888:4;13881:5;13877:16;13871:23;13941:3;13935:4;13931:14;13924:4;13919:3;13915:14;13908:38;13967:99;14061:4;14047:12;13967:99;:::i;:::-;13959:107;;13807:270;14158:4;14151:5;14147:16;14141:23;14177:63;14234:4;14229:3;14225:14;14211:12;14177:63;:::i;:::-;14087:163;14336:4;14329:5;14325:16;14319:23;14389:3;14383:4;14379:14;14372:4;14367:3;14363:14;14356:38;14415:103;14513:4;14499:12;14415:103;:::i;:::-;14407:111;;14260:269;14613:4;14606:5;14602:16;14596:23;14632:63;14689:4;14684:3;14680:14;14666:12;14632:63;:::i;:::-;14539:166;14793:4;14786:5;14782:16;14776:23;14812:63;14869:4;14864:3;14860:14;14846:12;14812:63;:::i;:::-;14715:170;14902:4;14895:11;;13484:1428;13372:1540;;;;:::o;14918:252::-;15035:10;15070:94;15160:3;15152:6;15070:94;:::i;:::-;15056:108;;14918:252;;;;:::o;15176:137::-;15270:4;15302;15297:3;15293:14;15285:22;;15176:137;;;:::o;15393:1103::-;15560:3;15589:78;15661:5;15589:78;:::i;:::-;15683:110;15786:6;15781:3;15683:110;:::i;:::-;15676:117;;15819:3;15864:4;15856:6;15852:17;15847:3;15843:27;15894:80;15968:5;15894:80;:::i;:::-;15997:7;16028:1;16013:438;16038:6;16035:1;16032:13;16013:438;;;16109:9;16103:4;16099:20;16094:3;16087:33;16160:6;16154:13;16188:112;16295:4;16280:13;16188:112;:::i;:::-;16180:120;;16323:84;16400:6;16323:84;:::i;:::-;16313:94;;16436:4;16431:3;16427:14;16420:21;;16073:378;16060:1;16057;16053:9;16048:14;;16013:438;;;16017:14;16467:4;16460:11;;16487:3;16480:10;;15565:931;;;;;15393:1103;;;;:::o;16502:469::-;16693:4;16731:2;16720:9;16716:18;16708:26;;16780:9;16774:4;16770:20;16766:1;16755:9;16751:17;16744:47;16808:156;16959:4;16950:6;16808:156;:::i;:::-;16800:164;;16502:469;;;;:::o" + }, + "storageLayout": { + "storage": [], + "types": null + }, + "functionHashes": {}, + "gasEstimates": { + "Creation": { + "codeDepositCost": "12400", + "executionCost": "infinite", + "totalCost": "infinite" + } + }, + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "Runtime Bytecode": { + "functionDebugData": {}, + "generatedSources": [], + "immutableReferences": {}, + "linkReferences": {}, + "object": "60806040525f80fdfea26469706673582212204e0f7686321089cffa942019d30b319ad1e19962130c666411e3998466df852b64736f6c63430008180033", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH0 DUP1 REVERT INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0x4E 0xF PUSH23 0x86321089CFFA942019D30B319AD1E19962130C666411E3 SWAP10 DUP5 PUSH7 0xDF852B64736F6C PUSH4 0x43000818 STOP CALLER ", + "sourceMap": "513:1088:0:-:0;;;;;" + } +} diff --git a/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/batch_request/mod.rs b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/batch_request/mod.rs new file mode 100644 index 000000000..91457cd2e --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/batch_request/mod.rs @@ -0,0 +1,120 @@ +use std::{ + str::from_utf8, + sync::Arc, +}; + +use alloy_sol_macro::sol; +use alloy_sol_types::SolCall; +use alloy_primitives::{hex, Bytes, FixedBytes, U256}; +use brontes_types::traits::TracingProvider; +use futures::TryFutureExt; +use reth_primitives::{Address, Bytecode, StorageValue}; +use reth_rpc_types::{request::TransactionInput, TransactionRequest}; + +use super::CurvePool; +use crate::errors::AmmError; + +sol!( + IGetCurveCryptoDataBatchRequest, + "./src/protocols/curve/curve_crypto_pool/batch_request/GetCurveCryptoPoolDataBatchRequestABI.json" +); + +sol!( + struct PoolData { + address[] tokens; + uint8[] tokenDecimals; + uint256 fee; + uint256[] reserves; + uint256 aValue; + uint256 gammaValue; + } + + function data_constructor( + address[] memory pools, + uint256[] memory asset_length) returns(PoolData[]); +); + +// Positions of crypto pool immutables in the bytecode +const PRICE_SCALE_PACKED_RANGE: std::ops::Range = "4542..4542 + 40"; +const FUTURE_A_GAMMA_TIME_RANGE: std::ops::Range = "9128..9128 + 40"; + +pub fn extract_curve_crypto_pool_immutables(bytecode: Bytes) -> (U256, U256) { + // Slices + let price_scale_packed_slice = &bytecode[PRICE_SCALE_PACKED_RANGE]; + let future_a_gamma_time_slice = &bytecode[FUTURE_A_GAMMA_TIME_RANGE]; + + let price_scale_packed = from_utf8(price_scale_packed_slice).unwrap(); + let future_a_gamma_time = from_utf8(future_a_gamma_time_slice).unwrap(); + + let price_scale_packed = U256::from_str_radix(price_scale_packed, 16).unwrap(); + let future_a_gamma_time = U256::from_str_radix(future_a_gamma_time, 16).unwrap(); + + (price_scale_packed, future_a_gamma_time) +} + +fn populate_pool_data(mut pool: CurvePool, pool_data: PoolData) -> CurvePool { + pool.tokens = pool_data.tokens; + pool.token_decimals = pool_data.tokenDecimals; + pool.fee = pool_data.fee; + pool.a_value = pool_data.aValue; + pool.gamma_value = pool_data.gammaValue; + pool.reserves = pool_data.reserves; + + pool +} + +pub async fn get_curve_crypto_pool_data_batch_request( + pool: &mut CurvePool, + block_number: Option, + middleware: Arc, +) -> Result<(), AmmError> { + + // Pool Storage Slots + let d_value_slot: FixedBytes<32> = FixedBytes::new(["0u8; 32"]); + + // Fetch from db + let d_value: Option = middleware + .get_storage(block_number, pool.address, d_value_slot) + .await?; + + // Fetch bytecode + let pool_bytecode: Option = + middleware.get_bytecode(block_number, pool.address).await?; + + // Decode liquidity + if let Some(d_value) = d_value { + let d_value = hex::encode::<[u8; 32]>(d_value.to_be_bytes()); + let d_value = u128::from_str_radix(&d_value[d_value.len() - 16..], 16).unwrap(); + pool.d_value = U256::from(d_value); + } + + // Extract price_scale_packed, future_a_gamma_time from bytecode + if let Some(pool_bytecode) = pool_bytecode { + let pool_bytecode = Bytes::from(hex::encode_prefixed(pool_bytecode.bytecode.as_ref())); + let (price_scale_packed, future_a_gamma_time) = extract_curve_crypto_pool_immutables(pool_bytecode); + pool.price_scale_packed = price_scale_packed; + pool.future_a_gamma_time = future_a_gamma_time; + } + + let mut bytecode = IGetCurveCryptoDataBatchRequest::BYTECODE.to_vec(); + data_constructorCall::new(( + vec![pool.address], + vec![U256::from(pool.tokens.len())], + )) + .abi_encode_raw(&mut bytecode); + + let req = TransactionRequest { + to: None, + input: TransactionInput::new(bytecode.into()), + ..Default::default() + }; + + let res = middleware + .eth_call(req, block_number.map(|i| i.into()), None, None) + .map_err(|e| eyre::eyre!("curve crypto call failed, err={}", e)) + .await?; + + let mut return_data = data_constructorCall::abi_decode_returns(&res, false)?; + *pool = populate_pool_data(pool.to_owned(), return_data._0.remove(0)); + Ok(()) +} \ No newline at end of file diff --git a/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/curve_crypto_pool_math/crypto_swap_invariant.rs b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/curve_crypto_pool_math/crypto_swap_invariant.rs new file mode 100644 index 000000000..3ee2ac307 --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/curve_crypto_pool_math/crypto_swap_invariant.rs @@ -0,0 +1,256 @@ +use alloy_primitives::U256; + +const PRECISION: U256 = U256::from_limbs([1_000_000_000_000_000_000, 0, 0, 0]); +const A_MULTIPLIER: U256 = U256::from_limbs([10000, 0, 0, 0]); +const U256_ONE: U256 = U256::from_limbs([1, 0, 0, 0]); +const MIN_GAMMA: U256 = U256::from_limbs([1_000_000_000_0, 0, 0, 0]); +const MAX_GAMMA: U256 = U256::from_limbs([5_000_000_000_000_000_0, 0, 0, 0]); + +pub fn calculate_exchange_rate_crypto( + reserves: Vec, + n_assets: U256, + coin_decimals: Vec, + sold_id: usize, + bought_id: usize, + price_scale_packed: U256, + future_a_gamma_time: Option, + d_value: U256, + a_0: U256, + a_1: U256, +) -> U256 { + let mut xp = reserves; + let price_size = U256::from(256) / (n_assets - U256::from(1)); + let price_mask = U256::from(2).pow(price_size) - U256::from(1); + let mut price_scale = Vec::new(); + let mut packed_prices = price_scale_packed; + let n_coins: usize = n_assets.to(); + let mut d_var = d_value; + for _ in 0..n_coins - 1 { + let price = packed_prices & price_mask; // Extract price using bitwise AND + price_scale.push(price); // Store the extracted price + packed_prices = packed_prices >> price_size; // Right shift for next price + } + let mut precisions = Vec::new(); + for i in 0..n_coins { + let precision = U256::from(10).pow(U256::from(18 - coin_decimals[i])); + precisions.push(precision); + } + xp[0] *= precisions[0]; + + for k in 1..n_coins { + xp[k] = (xp[k] * price_scale[k - 1] * precisions[k]) / PRECISION; + } + let prec_i = precisions[sold_id]; + if let Some(_future_a_gamma_time) = future_a_gamma_time { + let mut x0 = xp[sold_id]; + x0 *= prec_i; + if sold_id > 0 { + x0 = (x0 * price_scale[sold_id - 1]) / PRECISION; + } + let x1 = xp[sold_id]; + xp[sold_id] = x0; + d_var = newton_d( a_0, a_1, &xp, n_assets); + xp[sold_id] = x1; + } + + let prec_j = precisions[bought_id]; + let mut dy: U256 = + xp[bought_id] - + newton_y(a_0, a_1, xp, d_var, bought_id, n_assets); + dy -= U256::from(1); + if bought_id > 0 { + dy = (dy * PRECISION) / price_scale[bought_id - 1]; + } + dy / prec_j +} + +fn newton_d(ann: U256, gamma: U256, x_unsorted: &Vec, n_assets: U256) -> U256 { + let n_coins = n_assets.clone(); + let min_a = (n_coins.pow(n_coins) * A_MULTIPLIER) / U256::from(100); + let max_a = n_coins.pow(n_coins) * A_MULTIPLIER * U256::from(1000); + assert!(ann > min_a - U256_ONE && ann < max_a + U256_ONE, "unsafe values A"); + assert!(gamma > MIN_GAMMA - U256_ONE && gamma < MAX_GAMMA + U256_ONE, "unsafe values gamma"); + + let x = sort(& x_unsorted); + assert!( + x[0] > U256::from(1_000_000_000 - 1) && + x[0] < U256::from(1_000_000_000_000_000) * PRECISION + U256_ONE, + "unsafe values x[0]" + ); + + for i in 1..n_coins.to() { + let frac = (x[i] * PRECISION) / x[0]; + assert!(frac > U256::from(100_000_000_000 - 1), "unsafe values x[i]"); + } + + let mut d = n_coins * geometric_mean(x.clone(), false); + let mut s = U256::ZERO; + for x_i in &x { + s += *x_i; + } + + for _ in 0..255 { + let d_prev = d; + let mut k0 = PRECISION; + for x_i in &x { + k0 = (k0 * *x_i * n_coins) / d; + } + + let mut g1k0 = gamma + PRECISION; + g1k0 = if g1k0 > k0 { g1k0 - k0 + U256_ONE } else { k0 - g1k0 + U256_ONE }; + + let mul1 = (((((PRECISION * d) / gamma) * g1k0) / gamma) * g1k0 * A_MULTIPLIER) / ann; + let mul2 = (U256::from(2) * PRECISION * n_coins * k0) / g1k0; + let neg_fprime = + s + (s * mul2) / PRECISION + (mul1 * n_coins) / k0 - (mul2 * d) / PRECISION; + + let d_plus = (d * (neg_fprime + s)) / neg_fprime; + let mut d_minus = (d * d) / neg_fprime; + if PRECISION > k0 { + d_minus += + (((d * (mul1 / neg_fprime)) / PRECISION) * (PRECISION - k0)) / k0; + } else { + d_minus -= + (((d * (mul1 / neg_fprime)) / PRECISION) * (k0 - PRECISION)) / k0; + } + + d = if d_plus > d_minus { d_plus - d_minus } else { (d_minus - d_plus) / U256::from(2) }; + + let diff = if d > d_prev { d - d_prev } else { d_prev - d }; + if diff * (PRECISION / U256::from(10000)) < U256::max(PRECISION / U256::from(100), d) { + for x_i in &x { + let frac = (*x_i * PRECISION) / d; + assert!( + frac > (PRECISION / U256::from(100)) - U256_ONE && frac < (PRECISION * U256::from(100)) + U256_ONE, + "unsafe values x[i]" + ); + } + return d; + } + } + + panic!("Did not converge"); +} + +fn newton_y(ann: U256, gamma: U256, mut x: Vec, d: U256, i: usize, n_assets: U256) -> U256 { + let n_coins = n_assets.clone(); + let min_a = (n_coins.pow(n_coins) * A_MULTIPLIER) / U256::from(100); + let max_a = n_coins.pow(n_coins) * A_MULTIPLIER * U256::from(1000); + assert!(ann > min_a - U256_ONE && ann < max_a + U256_ONE, "unsafe values A"); + assert!( + gamma > MIN_GAMMA - U256_ONE && gamma < MAX_GAMMA + U256_ONE, + "unsafe values gamma" + ); + assert!( + d > U256::from(10).pow(U256::from(17)) - U256_ONE && + d < U256::from(10).pow(U256::from(15)) * PRECISION + U256_ONE, + "unsafe values D" + ); + + for &x_k in &x { + if x_k != x[i] { + let frac = (x_k * PRECISION) / d; + assert!( + frac > (PRECISION / U256::from(100)) - U256_ONE && frac < (PRECISION * U256::from(100)) + U256_ONE, + "unsafe values x[k]" + ); + } + } + + let mut y = d / n_coins; + let mut k0_i = PRECISION; + let mut s_i = U256::ZERO; + + x[i] = U256::ZERO; // Temporarily set x[i] to 0 for calculations + let x_sorted = sort(&x); + let asset_count: usize = n_coins.to(); + for j in 2..=asset_count { + let _x = x_sorted[asset_count - j]; + y = (y * d) / (_x * n_coins); + s_i += _x; + } + for x_j in &x_sorted[0..asset_count - 1] { + k0_i = (k0_i * *x_j * n_coins) / d; + } + + let convergence_limit = U256::max( + U256::max(x_sorted[0] / (PRECISION / U256::from(10000)), d / (PRECISION / U256::from(10000))), + U256::from(100) + ); + for _ in 0..255 { + let y_prev = y; + let k0 = (k0_i * y * n_coins) / d; + let s = s_i + y; + + let mut g1k0 = gamma + PRECISION; + g1k0 = if g1k0 > k0 { g1k0 - k0 + U256_ONE } else { k0 - g1k0 + U256_ONE }; + + let mul1 = (((((PRECISION * d) / gamma) * g1k0) / gamma) * g1k0 * A_MULTIPLIER) / ann; + let mul2 = PRECISION + (U256::from(2) * PRECISION * k0) / g1k0; + + let yfprime = PRECISION * y + s * mul2 + mul1; + let dyfprime = d * mul2; + let mut y_minus: U256; + let y_plus: U256; + + if yfprime < dyfprime { + y = y_prev / U256::from(2); + continue; + } else { + let fprime = yfprime - dyfprime; + y_minus = mul1 / fprime; + y_plus = (yfprime + PRECISION * d) / fprime + (y_minus * PRECISION) / k0; + y_minus += (PRECISION * s) / fprime; + } + + y = if y_plus > y_minus { y_plus - y_minus } else { y_prev / U256::from(2) }; // Adjust based on condition + + let diff = if y > y_prev { y - y_prev } else { y_prev - y }; + if diff < U256::max(convergence_limit, y / (PRECISION / U256::from(10000))) { + let frac = (y * PRECISION) / d; + assert!( + frac > (PRECISION / U256::from(100)) - U256_ONE && frac < (PRECISION * U256::from(100)) + U256_ONE, + "unsafe value for y" + ); + return y; + } + } + + panic!("Did not converge"); +} + +fn sort(values: &Vec) -> Vec{ + let mut values_sorted = values.clone(); + values_sorted.sort_by(|a, b| a.cmp(b)); + values_sorted +} + +fn geometric_mean(unsorted_x: Vec, sort: bool) -> U256 { + let x = if sort { + let mut sorted_x = unsorted_x.clone(); + sorted_x.sort(); // Sorts in ascending order by default + sorted_x + } else { + unsorted_x + }; + + let n_coins = U256::from(x.len() as u64); + let mut d = x[0]; + let mut diff :U256; + + for _ in 0..255 { + let d_prev = d; + let mut tmp = PRECISION; + for &_x in &x { + tmp = tmp.saturating_mul(_x) / d; // Adjusted for U256, using saturating_mul for overflow safety + } + d = d.saturating_mul(n_coins.saturating_sub(U256_ONE) * PRECISION + tmp) / (n_coins * PRECISION); + diff = if d > d_prev { d.saturating_sub(d_prev) } else { d_prev.saturating_sub(d) }; + + if diff <= U256_ONE || diff.saturating_mul(PRECISION) < d { + return d; + } + } + panic!("Did not converge"); +} + diff --git a/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/curve_crypto_pool_math/mod.rs b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/curve_crypto_pool_math/mod.rs new file mode 100644 index 000000000..d627b15e1 --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/curve_crypto_pool_math/mod.rs @@ -0,0 +1 @@ +pub mod crypto_swap_invariant; \ No newline at end of file diff --git a/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/mod.rs b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/mod.rs new file mode 100644 index 000000000..33284d46d --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_crypto_pool/mod.rs @@ -0,0 +1,236 @@ +use std::sync::Arc; + +use alloy_primitives::{Address, FixedBytes, Log, B256, U256}; +use alloy_rlp::{RlpDecodable, RlpEncodable}; +use alloy_sol_macro::sol; +use alloy_sol_types::{SolCall, SolEvent}; +use async_trait::async_trait; +use brontes_types::{ + db::{address_to_protocol_info::ProtocolInfo, traits::LibmdbxReader}, + normalized_actions::Actions, + traits::TracingProvider, + ToScaledRational, +}; +use malachite::Rational; +use serde::{Deserialize, Serialize}; + +pub mod batch_request; +pub mod curve_crypto_pool_math; +use crate::{ + errors::{AmmError, ArithmeticError, EventLogError}, + UpdatableProtocol, +}; + +use self::{batch_request::get_curve_crypto_pool_data_batch_request, curve_crypto_pool_math::crypto_swap_invariant::calculate_exchange_rate_crypto}; +sol!( + interface ICurveCryptoPool { + function A() external view returns (uint256); + function gamma() external view returns (uint256); + event TokenExchange( + address indexed buyer, + uint256 sold_id, + uint256 tokens_sold, + uint256 bought_id, + uint256 tokens_bought + ); + event AddLiquidity( + address indexed provider, + uint256[] token_amounts, + uint256 fee, + uint256 token_supply + ); + event RemoveLiquidity( + address indexed provider, + uint256[] token_amounts, + uint256 token_supply + ); + } +); + +//update event signature if required +// Swap event signature +pub const SWAP_EVENT_SIGNATURE: B256 = FixedBytes([ + 139, 62, 150, 242, 184, 137, 250, 119, 28, 83, 201, 129, 180, 13, 175, 0, 95, 99, 246, 55, 241, + 134, 159, 112, 112, 82, 209, 90, 61, 217, 113, 64, +]); + +// Burn event signature +pub const BURN_EVENT_SIGNATURE: B256 = FixedBytes([ + 158, 150, 221, 59, 153, 122, 42, 37, 126, 236, 77, 249, 187, 110, 175, 98, 110, 32, 109, 245, + 245, 67, 189, 150, 54, 130, 209, 67, 48, 11, 227, 16, +]); + +// Mint event signature +pub const MINT_EVENT_SIGNATURE: B256 = FixedBytes([ + 38, 245, 90, 133, 8, 29, 36, 151, 78, 133, 198, 192, 0, 69, 208, 240, 69, 57, 145, 233, 88, + 115, 245, 43, 255, 13, 33, 175, 64, 121, 167, 104, +]); + +#[derive( + Debug, Clone, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, Hash, PartialEq, Eq, +)] +pub struct CurvePool { + pub address: Address, + pub tokens: Vec
, + pub token_decimals: Vec, + pub fee: U256, + pub reserves: Vec, + //update this on executions if needed + pub a_value: U256, + //update this on executions if needed + pub gamma_value: U256, + // contract immutable variables + pub price_scale_packed: U256, + pub future_a_gamma_time: U256, + //update this on executions + pub d_value: U256, +} + +#[async_trait] +impl UpdatableProtocol for CurvePool { + fn address(&self) -> Address { + self.address + } + + fn sync_from_action(&mut self, _action: Actions) -> Result<(), AmmError> { + todo!("syncing from actions is currently not supported for curve crypto pools.") + } + + fn sync_from_log(&mut self, log: Log) -> Result<(), AmmError> { + let event_signature = log.topics()[0]; + + (match event_signature { + BURN_EVENT_SIGNATURE => self.sync_from_burn_log(log), + MINT_EVENT_SIGNATURE => self.sync_from_mint_log(log), + SWAP_EVENT_SIGNATURE => self.sync_from_swap_log(log), + _ => Err(EventLogError::InvalidEventSignature.into()), + })?; + + Ok(()) + } + + fn calculate_price( + &self, + base_token: Address, + quote_token: Option
, + ) -> Result { + let base_token_index = self.tokens.iter().position(|x| x == &base_token); + let quote_token_index = self.tokens.iter().position(|x| x == "e_token.unwrap()); + let price = calculate_exchange_rate_crypto( + self.reserves.clone(), + U256::from(self.tokens.len()), + self.token_decimals.clone(), + base_token_index.unwrap(), + quote_token_index.unwrap(), + self.price_scale_packed, + Some(self.future_a_gamma_time.to()), + self.d_value, + self.a_value, + self.gamma_value, + ); + let price_as_rational = + price.to_scaled_rational(self.token_decimals[base_token_index.unwrap()]); + + Ok(price_as_rational) + } + + fn tokens(&self) -> Vec
{ + self.tokens.clone() + } +} + +impl CurvePool { + async fn populate_data( + &mut self, + block: Option, + middleware: Arc, + ) -> Result<(), AmmError> { + get_curve_crypto_pool_data_batch_request(self, block, middleware).await + } + + // Creates a new instance of the pool from the pair address + pub async fn new_from_address( + pair_address: Address, + block_number: u64, + middleware: Arc, + db: &DB, + ) -> Result { + let pool_details = db.get_protocol_details(pair_address)?; + let tokens = collect_addresses(&pool_details); + let mut pool = CurvePool { + address: pair_address, + tokens, + token_decimals: Vec::new(), + fee: U256::ZERO, + a_value: U256::ZERO, + gamma_value: U256::ZERO, + price_scale_packed: U256::ZERO, + future_a_gamma_time: U256::ZERO, + d_value: U256::ZERO, + ..Default::default() + }; + + pool.populate_data(Some(block_number), middleware).await?; + + if !pool.data_is_populated() { + return Err(AmmError::NoStateError(pair_address)) + } + + Ok(pool) + } + + pub fn data_is_populated(&self) -> bool { + !(self.reserves.is_empty() || self.tokens.is_empty()) + } + + fn sync_from_burn_log(&mut self, log: Log) -> Result<(), AmmError> { + let remove_liquidity_event = ICurveCryptoPool::RemoveLiquidity::decode_log_data(&log, false)?; + for (i, amount) in remove_liquidity_event.token_amounts.iter().enumerate() { + self.reserves[i] -= amount; + } + + Ok(()) + } + + fn sync_from_mint_log(&mut self, log: Log) -> Result<(), AmmError> { + let add_liquidity_event = ICurveCryptoPool::AddLiquidity::decode_log_data(&log, false)?; + + for (i, amount) in add_liquidity_event.token_amounts.iter().enumerate() { + self.reserves[i] += amount; + } + + Ok(()) + } + + pub fn sync_from_swap_log(&mut self, log: Log) -> Result<(), AmmError> { + let token_exchange_event = ICurveCryptoPool::TokenExchange::decode_log_data(&log, false)?; + let to_token_index: usize = token_exchange_event.bought_id.to(); + let from_token_index: usize = token_exchange_event.sold_id.to(); + self.reserves[from_token_index - 1] += token_exchange_event.tokens_sold; + self.reserves[to_token_index - 1] -= token_exchange_event.tokens_bought; + Ok(()) + } + +} + +fn collect_addresses(protocol_info: &ProtocolInfo) -> Vec
{ + let mut addresses = Vec::new(); + + addresses.push(protocol_info.token0); + addresses.push(protocol_info.token1); + + if let Some(token2) = &protocol_info.token2 { + addresses.push(*token2); + } + if let Some(token3) = &protocol_info.token3 { + addresses.push(*token3); + } + if let Some(token4) = &protocol_info.token4 { + addresses.push(*token4); + } + if let Some(curve_lp_token) = &protocol_info.curve_lp_token { + addresses.push(*curve_lp_token); + } + + addresses +} \ No newline at end of file diff --git a/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/batch_request/GetCurveStablePoolDataBatchRequestABI.json b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/batch_request/GetCurveStablePoolDataBatchRequestABI.json new file mode 100644 index 000000000..82a5d99e6 --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/batch_request/GetCurveStablePoolDataBatchRequestABI.json @@ -0,0 +1,61 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "address[]", + "name": "pools", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "asset_length", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "base_pools", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + } + ], + "bytecode": { + "object": "608060405234801561000f575f80fd5b50604051610e9c380380610e9c83398181016040528101906100319190610944565b5f835167ffffffffffffffff81111561004d5761004c6106bb565b5b60405190808252806020026020018201604052801561008657816020015b61007361065d565b81526020019060019003908161006b5790505b5090505f5b845181101561062f575f5b8482815181106100a9576100a86109e8565b5b6020026020010151811015610379578582815181106100cb576100ca6109e8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663c6610657826040518263ffffffff1660e01b815260040161010b9190610a24565b602060405180830381865afa158015610126573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061014a9190610a3d565b83838151811061015d5761015c6109e8565b5b60200260200101515f0151828151811061017a576101796109e8565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508282815181106101c7576101c66109e8565b5b60200260200101515f015181815181106101e4576101e36109e8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610234573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102589190610a9e565b83838151811061026b5761026a6109e8565b5b6020026020010151602001518281518110610289576102886109e8565b5b602002602001019060ff16908160ff16815250508582815181106102b0576102af6109e8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff16634903b0d1826040518263ffffffff1660e01b81526004016102f09190610a24565b602060405180830381865afa15801561030b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032f9190610ac9565b838381518110610342576103416109e8565b5b602002602001015160c0015182815181106103605761035f6109e8565b5b6020026020010181815250508080600101915050610096565b5084818151811061038d5761038c6109e8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663ddca3f436040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103dd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104019190610ac9565b828281518110610414576104136109e8565b5b60200260200101516040018181525050848181518110610437576104366109e8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663fee3f7f96040518163ffffffff1660e01b8152600401602060405180830381865afa158015610487573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104ab9190610ac9565b8282815181106104be576104bd6109e8565b5b602002602001015160600181815250508481815181106104e1576104e06109e8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663f446c1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610531573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105559190610ac9565b828281518110610568576105676109e8565b5b6020026020010151608001818152505082818151811061058b5761058a6109e8565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1663bb7b8b806040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105ff9190610ac9565b828281518110610612576106116109e8565b5b602002602001015160a0018181525050808060010191505061008b565b505f816040516020016106429190610e7b565b60405160208183030381529060405290506020810180590381f35b6040518060e0016040528060608152602001606081526020015f81526020015f81526020015f81526020015f8152602001606081525090565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6106f1826106ab565b810181811067ffffffffffffffff821117156107105761070f6106bb565b5b80604052505050565b5f610722610696565b905061072e82826106e8565b919050565b5f67ffffffffffffffff82111561074d5761074c6106bb565b5b602082029050602081019050919050565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61078b82610762565b9050919050565b61079b81610781565b81146107a5575f80fd5b50565b5f815190506107b681610792565b92915050565b5f6107ce6107c984610733565b610719565b905080838252602082019050602084028301858111156107f1576107f061075e565b5b835b8181101561081a578061080688826107a8565b8452602084019350506020810190506107f3565b5050509392505050565b5f82601f830112610838576108376106a7565b5b81516108488482602086016107bc565b91505092915050565b5f67ffffffffffffffff82111561086b5761086a6106bb565b5b602082029050602081019050919050565b5f819050919050565b61088e8161087c565b8114610898575f80fd5b50565b5f815190506108a981610885565b92915050565b5f6108c16108bc84610851565b610719565b905080838252602082019050602084028301858111156108e4576108e361075e565b5b835b8181101561090d57806108f9888261089b565b8452602084019350506020810190506108e6565b5050509392505050565b5f82601f83011261092b5761092a6106a7565b5b815161093b8482602086016108af565b91505092915050565b5f805f6060848603121561095b5761095a61069f565b5b5f84015167ffffffffffffffff811115610978576109776106a3565b5b61098486828701610824565b935050602084015167ffffffffffffffff8111156109a5576109a46106a3565b5b6109b186828701610917565b925050604084015167ffffffffffffffff8111156109d2576109d16106a3565b5b6109de86828701610824565b9150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b610a1e8161087c565b82525050565b5f602082019050610a375f830184610a15565b92915050565b5f60208284031215610a5257610a5161069f565b5b5f610a5f848285016107a8565b91505092915050565b5f60ff82169050919050565b610a7d81610a68565b8114610a87575f80fd5b50565b5f81519050610a9881610a74565b92915050565b5f60208284031215610ab357610ab261069f565b5b5f610ac084828501610a8a565b91505092915050565b5f60208284031215610ade57610add61069f565b5b5f610aeb8482850161089b565b91505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610b4f81610781565b82525050565b5f610b608383610b46565b60208301905092915050565b5f602082019050919050565b5f610b8282610b1d565b610b8c8185610b27565b9350610b9783610b37565b805f5b83811015610bc7578151610bae8882610b55565b9750610bb983610b6c565b925050600181019050610b9a565b5085935050505092915050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610c0681610a68565b82525050565b5f610c178383610bfd565b60208301905092915050565b5f602082019050919050565b5f610c3982610bd4565b610c438185610bde565b9350610c4e83610bee565b805f5b83811015610c7e578151610c658882610c0c565b9750610c7083610c23565b925050600181019050610c51565b5085935050505092915050565b610c948161087c565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f610cce8383610c8b565b60208301905092915050565b5f602082019050919050565b5f610cf082610c9a565b610cfa8185610ca4565b9350610d0583610cb4565b805f5b83811015610d35578151610d1c8882610cc3565b9750610d2783610cda565b925050600181019050610d08565b5085935050505092915050565b5f60e083015f8301518482035f860152610d5c8282610b78565b91505060208301518482036020860152610d768282610c2f565b9150506040830151610d8b6040860182610c8b565b506060830151610d9e6060860182610c8b565b506080830151610db16080860182610c8b565b5060a0830151610dc460a0860182610c8b565b5060c083015184820360c0860152610ddc8282610ce6565b9150508091505092915050565b5f610df48383610d42565b905092915050565b5f602082019050919050565b5f610e1282610af4565b610e1c8185610afe565b935083602082028501610e2e85610b0e565b805f5b85811015610e695784840389528151610e4a8582610de9565b9450610e5583610dfc565b925060208a01995050600181019050610e31565b50829750879550505050505092915050565b5f6020820190508181035f830152610e938184610e08565b90509291505056fe", + "sourceMap": "583:1232:0:-:0;;;831:982;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;937:26;981:5;:12;966:28;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;937:57;;1009:6;1004:585;1022:5;:12;1019:1;:15;1004:585;;;1060:9;1055:284;1075:12;1088:1;1075:15;;;;;;;;:::i;:::-;;;;;;;;1073:1;:17;1055:284;;;1146:5;1152:1;1146:8;;;;;;;;:::i;:::-;;;;;;;;1140:21;;;1162:1;1140:24;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1116:8;1125:1;1116:11;;;;;;;;:::i;:::-;;;;;;;;:18;;;1135:1;1116:21;;;;;;;;:::i;:::-;;;;;;;:48;;;;;;;;;;;1220:8;1229:1;1220:11;;;;;;;;:::i;:::-;;;;;;;;:18;;;1239:1;1220:21;;;;;;;;:::i;:::-;;;;;;;;1213:38;;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1182:8;1191:1;1182:11;;;;;;;;:::i;:::-;;;;;;;;:25;;;1208:1;1182:28;;;;;;;;:::i;:::-;;;;;;;:71;;;;;;;;;;;1303:5;1309:1;1303:8;;;;;;;;:::i;:::-;;;;;;;;1297:24;;;1322:1;1297:27;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1271:8;1280:1;1271:11;;;;;;;;:::i;:::-;;;;;;;;:20;;;1292:1;1271:23;;;;;;;;:::i;:::-;;;;;;;:53;;;;;1092:3;;;;;;;1055:284;;;;1372:5;1378:1;1372:8;;;;;;;;:::i;:::-;;;;;;;;1366:19;;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1348:8;1357:1;1348:11;;;;;;;;:::i;:::-;;;;;;;;:15;;:39;;;;;1426:5;1432:1;1426:8;;;;;;;;:::i;:::-;;;;;;;;1420:25;;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1397:8;1406:1;1397:11;;;;;;;;:::i;:::-;;;;;;;;:20;;:50;;;;;1484:5;1490:1;1484:8;;;;;;;;:::i;:::-;;;;;;;;1478:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1457:8;1466:1;1457:11;;;;;;;;:::i;:::-;;;;;;;;:18;;:40;;;;;1544:10;1555:1;1544:13;;;;;;;;:::i;:::-;;;;;;;;1538:38;;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1507:8;1516:1;1507:11;;;;;;;;:::i;:::-;;;;;;;;:28;;:71;;;;;1036:3;;;;;;;1004:585;;;;1616:27;1657:8;1646:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;1616:50;;1737:4;1721:14;1717:25;1786:9;1777:7;1773:23;1762:9;1755:42;583:1232;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;7:75:1:-;40:6;73:2;67:9;57:19;;7:75;:::o;88:117::-;197:1;194;187:12;211:117;320:1;317;310:12;334:117;443:1;440;433:12;457:102;498:6;549:2;545:7;540:2;533:5;529:14;525:28;515:38;;457:102;;;:::o;565:180::-;613:77;610:1;603:88;710:4;707:1;700:15;734:4;731:1;724:15;751:281;834:27;856:4;834:27;:::i;:::-;826:6;822:40;964:6;952:10;949:22;928:18;916:10;913:34;910:62;907:88;;;975:18;;:::i;:::-;907:88;1015:10;1011:2;1004:22;794:238;751:281;;:::o;1038:129::-;1072:6;1099:20;;:::i;:::-;1089:30;;1128:33;1156:4;1148:6;1128:33;:::i;:::-;1038:129;;;:::o;1173:311::-;1250:4;1340:18;1332:6;1329:30;1326:56;;;1362:18;;:::i;:::-;1326:56;1412:4;1404:6;1400:17;1392:25;;1472:4;1466;1462:15;1454:23;;1173:311;;;:::o;1490:117::-;1599:1;1596;1589:12;1613:126;1650:7;1690:42;1683:5;1679:54;1668:65;;1613:126;;;:::o;1745:96::-;1782:7;1811:24;1829:5;1811:24;:::i;:::-;1800:35;;1745:96;;;:::o;1847:122::-;1920:24;1938:5;1920:24;:::i;:::-;1913:5;1910:35;1900:63;;1959:1;1956;1949:12;1900:63;1847:122;:::o;1975:143::-;2032:5;2063:6;2057:13;2048:22;;2079:33;2106:5;2079:33;:::i;:::-;1975:143;;;;:::o;2141:732::-;2248:5;2273:81;2289:64;2346:6;2289:64;:::i;:::-;2273:81;:::i;:::-;2264:90;;2374:5;2403:6;2396:5;2389:21;2437:4;2430:5;2426:16;2419:23;;2490:4;2482:6;2478:17;2470:6;2466:30;2519:3;2511:6;2508:15;2505:122;;;2538:79;;:::i;:::-;2505:122;2653:6;2636:231;2670:6;2665:3;2662:15;2636:231;;;2745:3;2774:48;2818:3;2806:10;2774:48;:::i;:::-;2769:3;2762:61;2852:4;2847:3;2843:14;2836:21;;2712:155;2696:4;2691:3;2687:14;2680:21;;2636:231;;;2640:21;2254:619;;2141:732;;;;;:::o;2896:385::-;2978:5;3027:3;3020:4;3012:6;3008:17;3004:27;2994:122;;3035:79;;:::i;:::-;2994:122;3145:6;3139:13;3170:105;3271:3;3263:6;3256:4;3248:6;3244:17;3170:105;:::i;:::-;3161:114;;2984:297;2896:385;;;;:::o;3287:311::-;3364:4;3454:18;3446:6;3443:30;3440:56;;;3476:18;;:::i;:::-;3440:56;3526:4;3518:6;3514:17;3506:25;;3586:4;3580;3576:15;3568:23;;3287:311;;;:::o;3604:77::-;3641:7;3670:5;3659:16;;3604:77;;;:::o;3687:122::-;3760:24;3778:5;3760:24;:::i;:::-;3753:5;3750:35;3740:63;;3799:1;3796;3789:12;3740:63;3687:122;:::o;3815:143::-;3872:5;3903:6;3897:13;3888:22;;3919:33;3946:5;3919:33;:::i;:::-;3815:143;;;;:::o;3981:732::-;4088:5;4113:81;4129:64;4186:6;4129:64;:::i;:::-;4113:81;:::i;:::-;4104:90;;4214:5;4243:6;4236:5;4229:21;4277:4;4270:5;4266:16;4259:23;;4330:4;4322:6;4318:17;4310:6;4306:30;4359:3;4351:6;4348:15;4345:122;;;4378:79;;:::i;:::-;4345:122;4493:6;4476:231;4510:6;4505:3;4502:15;4476:231;;;4585:3;4614:48;4658:3;4646:10;4614:48;:::i;:::-;4609:3;4602:61;4692:4;4687:3;4683:14;4676:21;;4552:155;4536:4;4531:3;4527:14;4520:21;;4476:231;;;4480:21;4094:619;;3981:732;;;;;:::o;4736:385::-;4818:5;4867:3;4860:4;4852:6;4848:17;4844:27;4834:122;;4875:79;;:::i;:::-;4834:122;4985:6;4979:13;5010:105;5111:3;5103:6;5096:4;5088:6;5084:17;5010:105;:::i;:::-;5001:114;;4824:297;4736:385;;;;:::o;5127:1272::-;5290:6;5298;5306;5355:2;5343:9;5334:7;5330:23;5326:32;5323:119;;;5361:79;;:::i;:::-;5323:119;5502:1;5491:9;5487:17;5481:24;5532:18;5524:6;5521:30;5518:117;;;5554:79;;:::i;:::-;5518:117;5659:89;5740:7;5731:6;5720:9;5716:22;5659:89;:::i;:::-;5649:99;;5452:306;5818:2;5807:9;5803:18;5797:25;5849:18;5841:6;5838:30;5835:117;;;5871:79;;:::i;:::-;5835:117;5976:89;6057:7;6048:6;6037:9;6033:22;5976:89;:::i;:::-;5966:99;;5768:307;6135:2;6124:9;6120:18;6114:25;6166:18;6158:6;6155:30;6152:117;;;6188:79;;:::i;:::-;6152:117;6293:89;6374:7;6365:6;6354:9;6350:22;6293:89;:::i;:::-;6283:99;;6085:307;5127:1272;;;;;:::o;6405:180::-;6453:77;6450:1;6443:88;6550:4;6547:1;6540:15;6574:4;6571:1;6564:15;6591:118;6678:24;6696:5;6678:24;:::i;:::-;6673:3;6666:37;6591:118;;:::o;6715:222::-;6808:4;6846:2;6835:9;6831:18;6823:26;;6859:71;6927:1;6916:9;6912:17;6903:6;6859:71;:::i;:::-;6715:222;;;;:::o;6943:351::-;7013:6;7062:2;7050:9;7041:7;7037:23;7033:32;7030:119;;;7068:79;;:::i;:::-;7030:119;7188:1;7213:64;7269:7;7260:6;7249:9;7245:22;7213:64;:::i;:::-;7203:74;;7159:128;6943:351;;;;:::o;7300:86::-;7335:7;7375:4;7368:5;7364:16;7353:27;;7300:86;;;:::o;7392:118::-;7463:22;7479:5;7463:22;:::i;:::-;7456:5;7453:33;7443:61;;7500:1;7497;7490:12;7443:61;7392:118;:::o;7516:139::-;7571:5;7602:6;7596:13;7587:22;;7618:31;7643:5;7618:31;:::i;:::-;7516:139;;;;:::o;7661:347::-;7729:6;7778:2;7766:9;7757:7;7753:23;7749:32;7746:119;;;7784:79;;:::i;:::-;7746:119;7904:1;7929:62;7983:7;7974:6;7963:9;7959:22;7929:62;:::i;:::-;7919:72;;7875:126;7661:347;;;;:::o;8014:351::-;8084:6;8133:2;8121:9;8112:7;8108:23;8104:32;8101:119;;;8139:79;;:::i;:::-;8101:119;8259:1;8284:64;8340:7;8331:6;8320:9;8316:22;8284:64;:::i;:::-;8274:74;;8230:128;8014:351;;;;:::o;8371:138::-;8462:6;8496:5;8490:12;8480:22;;8371:138;;;:::o;8515:208::-;8638:11;8672:6;8667:3;8660:19;8712:4;8707:3;8703:14;8688:29;;8515:208;;;;:::o;8729:156::-;8820:4;8843:3;8835:11;;8873:4;8868:3;8864:14;8856:22;;8729:156;;;:::o;8891:114::-;8958:6;8992:5;8986:12;8976:22;;8891:114;;;:::o;9011:174::-;9100:11;9134:6;9129:3;9122:19;9174:4;9169:3;9165:14;9150:29;;9011:174;;;;:::o;9191:132::-;9258:4;9281:3;9273:11;;9311:4;9306:3;9302:14;9294:22;;9191:132;;;:::o;9329:108::-;9406:24;9424:5;9406:24;:::i;:::-;9401:3;9394:37;9329:108;;:::o;9443:179::-;9512:10;9533:46;9575:3;9567:6;9533:46;:::i;:::-;9611:4;9606:3;9602:14;9588:28;;9443:179;;;;:::o;9628:113::-;9698:4;9730;9725:3;9721:14;9713:22;;9628:113;;;:::o;9777:712::-;9886:3;9915:54;9963:5;9915:54;:::i;:::-;9985:76;10054:6;10049:3;9985:76;:::i;:::-;9978:83;;10085:56;10135:5;10085:56;:::i;:::-;10164:7;10195:1;10180:284;10205:6;10202:1;10199:13;10180:284;;;10281:6;10275:13;10308:63;10367:3;10352:13;10308:63;:::i;:::-;10301:70;;10394:60;10447:6;10394:60;:::i;:::-;10384:70;;10240:224;10227:1;10224;10220:9;10215:14;;10180:284;;;10184:14;10480:3;10473:10;;9891:598;;;9777:712;;;;:::o;10495:112::-;10560:6;10594:5;10588:12;10578:22;;10495:112;;;:::o;10613:172::-;10700:11;10734:6;10729:3;10722:19;10774:4;10769:3;10765:14;10750:29;;10613:172;;;;:::o;10791:130::-;10856:4;10879:3;10871:11;;10909:4;10904:3;10900:14;10892:22;;10791:130;;;:::o;10927:102::-;11000:22;11016:5;11000:22;:::i;:::-;10995:3;10988:35;10927:102;;:::o;11035:171::-;11100:10;11121:42;11159:3;11151:6;11121:42;:::i;:::-;11195:4;11190:3;11186:14;11172:28;;11035:171;;;;:::o;11212:111::-;11280:4;11312;11307:3;11303:14;11295:22;;11212:111;;;:::o;11355:696::-;11460:3;11489:52;11535:5;11489:52;:::i;:::-;11557:74;11624:6;11619:3;11557:74;:::i;:::-;11550:81;;11655:54;11703:5;11655:54;:::i;:::-;11732:7;11763:1;11748:278;11773:6;11770:1;11767:13;11748:278;;;11849:6;11843:13;11876:59;11931:3;11916:13;11876:59;:::i;:::-;11869:66;;11958:58;12009:6;11958:58;:::i;:::-;11948:68;;11808:218;11795:1;11792;11788:9;11783:14;;11748:278;;;11752:14;12042:3;12035:10;;11465:586;;;11355:696;;;;:::o;12057:108::-;12134:24;12152:5;12134:24;:::i;:::-;12129:3;12122:37;12057:108;;:::o;12171:114::-;12238:6;12272:5;12266:12;12256:22;;12171:114;;;:::o;12291:174::-;12380:11;12414:6;12409:3;12402:19;12454:4;12449:3;12445:14;12430:29;;12291:174;;;;:::o;12471:132::-;12538:4;12561:3;12553:11;;12591:4;12586:3;12582:14;12574:22;;12471:132;;;:::o;12609:179::-;12678:10;12699:46;12741:3;12733:6;12699:46;:::i;:::-;12777:4;12772:3;12768:14;12754:28;;12609:179;;;;:::o;12794:113::-;12864:4;12896;12891:3;12887:14;12879:22;;12794:113;;;:::o;12943:712::-;13052:3;13081:54;13129:5;13081:54;:::i;:::-;13151:76;13220:6;13215:3;13151:76;:::i;:::-;13144:83;;13251:56;13301:5;13251:56;:::i;:::-;13330:7;13361:1;13346:284;13371:6;13368:1;13365:13;13346:284;;;13447:6;13441:13;13474:63;13533:3;13518:13;13474:63;:::i;:::-;13467:70;;13560:60;13613:6;13560:60;:::i;:::-;13550:70;;13406:224;13393:1;13390;13386:9;13381:14;;13346:284;;;13350:14;13646:3;13639:10;;13057:598;;;12943:712;;;;:::o;13731:1724::-;13838:3;13874:4;13869:3;13865:14;13963:4;13956:5;13952:16;13946:23;14016:3;14010:4;14006:14;13999:4;13994:3;13990:14;13983:38;14042:103;14140:4;14126:12;14042:103;:::i;:::-;14034:111;;13889:267;14247:4;14240:5;14236:16;14230:23;14300:3;14294:4;14290:14;14283:4;14278:3;14274:14;14267:38;14326:99;14420:4;14406:12;14326:99;:::i;:::-;14318:107;;14166:270;14517:4;14510:5;14506:16;14500:23;14536:63;14593:4;14588:3;14584:14;14570:12;14536:63;:::i;:::-;14446:163;14695:4;14688:5;14684:16;14678:23;14714:63;14771:4;14766:3;14762:14;14748:12;14714:63;:::i;:::-;14619:168;14871:4;14864:5;14860:16;14854:23;14890:63;14947:4;14942:3;14938:14;14924:12;14890:63;:::i;:::-;14797:166;15057:4;15050:5;15046:16;15040:23;15076:63;15133:4;15128:3;15124:14;15110:12;15076:63;:::i;:::-;14973:176;15235:4;15228:5;15224:16;15218:23;15288:3;15282:4;15278:14;15271:4;15266:3;15262:14;15255:38;15314:103;15412:4;15398:12;15314:103;:::i;:::-;15306:111;;15159:269;15445:4;15438:11;;13843:1612;13731:1724;;;;:::o;15461:252::-;15578:10;15613:94;15703:3;15695:6;15613:94;:::i;:::-;15599:108;;15461:252;;;;:::o;15719:137::-;15813:4;15845;15840:3;15836:14;15828:22;;15719:137;;;:::o;15936:1103::-;16103:3;16132:78;16204:5;16132:78;:::i;:::-;16226:110;16329:6;16324:3;16226:110;:::i;:::-;16219:117;;16362:3;16407:4;16399:6;16395:17;16390:3;16386:27;16437:80;16511:5;16437:80;:::i;:::-;16540:7;16571:1;16556:438;16581:6;16578:1;16575:13;16556:438;;;16652:9;16646:4;16642:20;16637:3;16630:33;16703:6;16697:13;16731:112;16838:4;16823:13;16731:112;:::i;:::-;16723:120;;16866:84;16943:6;16866:84;:::i;:::-;16856:94;;16979:4;16974:3;16970:14;16963:21;;16616:378;16603:1;16600;16596:9;16591:14;;16556:438;;;16560:14;17010:4;17003:11;;17030:3;17023:10;;16108:931;;;;;15936:1103;;;;:::o;17045:469::-;17236:4;17274:2;17263:9;17259:18;17251:26;;17323:9;17317:4;17313:20;17309:1;17298:9;17294:17;17287:47;17351:156;17502:4;17493:6;17351:156;:::i;:::-;17343:164;;17045:469;;;;:::o", + "linkReferences": {} + }, + "storageLayout": { + "storage": [], + "types": null + }, + "functionHashes": {}, + "gasEstimates": { + "Creation": { + "codeDepositCost": "12400", + "executionCost": "infinite", + "totalCost": "infinite" + } + }, + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "Runtime Bytecode": { + "functionDebugData": {}, + "generatedSources": [], + "immutableReferences": {}, + "linkReferences": {}, + "object": "60806040525f80fdfea264697066735822122038afca66643df2eba82651295163ed64f73d996615d0ddf6b65630db65333e4a64736f6c63430008180033", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH0 DUP1 REVERT INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 CODESIZE 0xAF 0xCA PUSH7 0x643DF2EBA82651 0x29 MLOAD PUSH4 0xED64F73D SWAP10 PUSH7 0x15D0DDF6B65630 0xDB PUSH6 0x333E4A64736F PUSH13 0x63430008180033000000000000 ", + "sourceMap": "583:1232:0:-:0;;;;;" + } +} diff --git a/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/batch_request/mod.rs b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/batch_request/mod.rs new file mode 100644 index 000000000..b7f9614b1 --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/batch_request/mod.rs @@ -0,0 +1,108 @@ +use std::{ + str::{from_utf8, FromStr}, + sync::Arc, +}; + +use alloy_primitives::{hex, Bytes, FixedBytes, U256}; +use alloy_sol_macro::sol; +use alloy_sol_types::SolCall; +use brontes_types::traits::TracingProvider; +use futures::TryFutureExt; +use reth_primitives::{Address, Bytecode, StorageValue}; +use reth_rpc_types::{request::TransactionInput, TransactionRequest}; + +use super::CurvePool; +use crate::errors::AmmError; + +sol!( + IGetCurveV2MetapoolDataBatchRequest, + "./src/protocols/curve/curve_stable_pool/batch_request/GetCurveStablePoolDataBatchRequestABI.\ + json" +); + +sol!( + struct PoolData { + address[] tokens; + uint8[] tokenDecimals; + uint256 fee; + uint256 adminFee; + uint256 aValue; + uint256 baseVirtualPrice; + uint256[] reserves; + } + + function data_constructor( + address[] memory pools, + uint256[] memory asset_length, + address[] memory base_pools) returns(PoolData[]); +); + +// Positions of stable pool immutables in the bytecode +const BASE_POOL_RANGE: std::ops::Range = "4542..4542 + 40"; +const ORIGINAL_RATES_RANGE: std::ops::Range = "9128..9128 + 40"; + +pub fn extract_curve_stable_pool_immutables(bytecode: Bytes) -> (Address, Vec) { + // Slices + let base_pool_slice = &bytecode[BASE_POOL_RANGE]; + let original_rates_slice = &bytecode[ORIGINAL_RATES_RANGE]; + + let base_pool = from_utf8(base_pool_slice).unwrap(); + let original_rates = from_utf8(original_rates_slice).unwrap(); + + let base_pool = Address::from_str(base_pool).unwrap(); + let original_pool_rates = U256::from_str_radix(future_a_gamma_time, 16).unwrap(); + + (base_pool, original_pool_rates) +} + +fn populate_pool_data(mut pool: CurvePool, pool_data: PoolData) -> CurvePool { + pool.tokens = pool_data.tokens; + pool.token_decimals = pool_data.tokenDecimals; + pool.fee = pool_data.fee; + pool.a_value = pool_data.aValue; + pool.base_virtual_price = pool_data.baseVirtualPrice; + pool.reserves = pool_data.reserves; + + pool +} + +pub async fn get_curve_pool_data_batch_request( + pool: &mut CurvePool, + block: Option, + middleware: Arc, +) -> Result<(), AmmError> { + + // Fetch pool bytecode + let pool_bytecode: Option = + middleware.get_bytecode(block, pool.address).await?; + + // Extract base_pool, original_pool_rates from bytecode + if let Some(pool_bytecode) = pool_bytecode { + let pool_bytecode = Bytes::from(hex::encode_prefixed(pool_bytecode.bytecode.as_ref())); + let (base_pool, original_pool_rates) = extract_curve_stable_pool_immutables(pool_bytecode); + pool.base_pool = base_pool; + pool.rates = original_pool_rates; + } + let mut bytecode = IGetCurveV2MetapoolDataBatchRequest::BYTECODE.to_vec(); + data_constructorCall::new(( + vec![pool.address], + vec![U256::from(pool.tokens.len())], + vec![pool.base_pool], + )) + .abi_encode_raw(&mut bytecode); + + let req = TransactionRequest { + to: None, + input: TransactionInput::new(bytecode.into()), + ..Default::default() + }; + + let res = middleware + .eth_call(req, block.map(|i| i.into()), None, None) + .map_err(|e| eyre::eyre!("curve stable call failed, err={}", e)) + .await?; + + let mut return_data = data_constructorCall::abi_decode_returns(&res, false)?; + *pool = populate_pool_data(pool.to_owned(), return_data._0.remove(0)); + Ok(()) +} diff --git a/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/fee_math.rs b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/fee_math.rs new file mode 100644 index 000000000..1a1f90360 --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/fee_math.rs @@ -0,0 +1,17 @@ +use alloy_primitives::U256; + +const PRECISION: U256 = U256::from_limbs([1_000_000_000_000_000_000, 0, 0, 0]); + +const FEE_DENOMINATOR: U256 = U256::from_limbs([10_000_000_000, 0, 0, 0]); + +pub fn calculate_bought_amount_admin_fee( + rates: Vec, + admin_fee: U256, + fee: U256, + bought_amount: U256, + bought_id: usize, +) -> U256 { + let dy_original = bought_amount * rates[bought_id - 1] / PRECISION; + let dy_fee = dy_original * fee / FEE_DENOMINATOR; + dy_fee * admin_fee / FEE_DENOMINATOR +} diff --git a/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/mod.rs b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/mod.rs new file mode 100644 index 000000000..2488eaffa --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/mod.rs @@ -0,0 +1,2 @@ +pub mod fee_math; +pub mod stable_swap_invariant; diff --git a/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/stable_swap_invariant.rs b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/stable_swap_invariant.rs new file mode 100644 index 000000000..0bb915602 --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/curve_stable_pool_math/stable_swap_invariant.rs @@ -0,0 +1,103 @@ +use alloy_primitives::U256; + +const PRECISION: U256 = U256::from_limbs([1_000_000_000_000_000_000, 0, 0, 0]); + +const IN_TOKEN_AMOUNT: U256 = U256::from_limbs([1, 0, 0, 0]); + +pub fn calculate_exchange_rate_stable( + vp_rate: U256, + balances: Vec, + rates: Vec, + n_assets: U256, + sold_id: usize, + bought_id: usize, + amp: U256, +) -> U256 { + let rates_clone = rates.clone(); + let xp = xp_mem(vp_rate, balances, rates, n_assets); + let x = xp[sold_id] + IN_TOKEN_AMOUNT * (rates_clone[sold_id] / PRECISION); + let y = get_y(sold_id, bought_id, x, xp.clone(), amp, n_assets); + xp[bought_id] - y - U256::from(1) +} + +pub fn get_d(xp: Vec, amp: U256, n_assets: U256) -> U256 { + let s: U256 = xp.iter().sum(); + if s == U256::ZERO { + return U256::ZERO; + } + + let mut d = s; + let ann = amp * U256::from(xp.len()); + let a_precision = U256::from(100); + + for _ in 0..255 { + let d_p: U256 = xp.iter().fold(d, |acc, &x| (acc * d) / (x * n_assets)); + let d_prev = d; + d = (((ann * s) / a_precision + d_p * n_assets) * d) + / (((ann - a_precision) * d) / a_precision + (n_assets + U256::from(1)) * d_p); + + if (d > d_prev && d - d_prev <= U256::from(1)) + || (d <= d_prev && d_prev - d <= U256::from(1)) + { + break; + } + } + d +} + +pub fn get_y(i: usize, j: usize, x: U256, xp_: Vec, amp: U256, n_assets: U256) -> U256 { + let n_coins = n_assets; + assert!(i != j, "same coin"); + assert!(U256::from(j) < n_coins, "j above N_COINS"); + assert!(U256::from(i) < n_coins, "i above N_COINS"); + + let d: U256 = get_d(xp_.clone(), amp, n_coins); + let a_precision = U256::from(100); + let mut s_: U256 = U256::ZERO; + let mut c: U256 = d; + let ann: U256 = amp * U256::from(n_coins); + + for (_i, _x) in xp_.iter().enumerate() { + let x_val = if _i == i { + x + } else if _i != j { + *_x + } else { + continue; + }; + s_ += x_val; + c = (c * d) / (x_val * U256::from(n_coins)); + } + + c = (c * d * a_precision) / (ann * U256::from(n_coins)); + let b: U256 = s_ + (d * a_precision) / ann; + let mut y: U256 = d; + + for _ in 0..255 { + let y_prev = y; + y = (y * y + c) / (U256::from(2) * y + b - d); + if (y > y_prev && y - y_prev <= U256::from(1)) + || (y <= y_prev && y_prev - y <= U256::from(1)) + { + break; + } + } + y +} + +pub fn xp_mem(vp_rate: U256, balance: Vec, rates: Vec, n_assets: U256) -> Vec { + let n_assets_usize = n_assets.to(); + assert!(n_assets_usize <= rates.len(), "n_assets exceeds rates length"); + assert!(n_assets_usize <= balance.len(), "n_assets exceeds balance length"); + assert!(n_assets_usize > 0, "n_assets must be greater than zero"); + + let mut result = rates; + + result[n_assets_usize - 1] = vp_rate; + + for i in 0..n_assets_usize { + result[i] = result[i] * balance[i] / PRECISION; + } + + result +} diff --git a/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/mod.rs b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/mod.rs new file mode 100644 index 000000000..9e173ae3e --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/curve_stable_pool/mod.rs @@ -0,0 +1,276 @@ +use std::sync::Arc; + +use alloy_primitives::{Address, FixedBytes, Log, B256, U256}; +use alloy_rlp::{RlpDecodable, RlpEncodable}; +use alloy_sol_macro::sol; +use alloy_sol_types::SolEvent; +use async_trait::async_trait; +use brontes_types::{ + db::{address_to_protocol_info::ProtocolInfo, traits::LibmdbxReader}, + normalized_actions::Actions, + traits::TracingProvider, + ToScaledRational, +}; +use malachite::Rational; +use serde::{Deserialize, Serialize}; + +pub mod batch_request; +pub mod curve_stable_pool_math; +use self::{ + batch_request::get_curve_pool_data_batch_request, + curve_stable_pool_math::{ + fee_math::calculate_bought_amount_admin_fee, + stable_swap_invariant::calculate_exchange_rate_stable, + }, +}; +use crate::{ + errors::{AmmError, ArithmeticError, EventLogError}, + UpdatableProtocol, +}; +sol!( + #[derive(Debug)] + interface ICurvePool { + event TokenExchange( + address buyer, + int128 sold_id, + uint256 tokens_sold, + int128 bought_id, + uint256 tokens_bought + ); + event TokenExchangeUnderlying( + address buyer, + int128 sold_id, + uint256 tokens_sold, + int128 bought_id, + uint256 tokens_bought + ); + event AddLiquidity( + address provider, + uint256[] token_amounts, + uint256[] fees, + uint256 invariant, + uint256 token_supply + ); + event RemoveLiquidity( + address provider, + uint256[] token_amounts, + uint256[] fees, uint256 token_supply + ); + } +); + +// Swap event signature +pub const SWAP_EVENT_SIGNATURE: B256 = FixedBytes([ + 139, 62, 150, 242, 184, 137, 250, 119, 28, 83, 201, 129, 180, 13, 175, 0, 95, 99, 246, 55, 241, + 134, 159, 112, 112, 82, 209, 90, 61, 217, 113, 64, +]); + +// SwapUnderlying event signature +pub const SWAP_UNDERLYING_EVENT_SIGNATURE: B256 = FixedBytes([ + 208, 19, 202, 35, 231, 122, 101, 0, 60, 44, 101, 156, 84, 66, 192, 12, 128, 83, 113, 183, 252, + 30, 189, 76, 32, 108, 65, 209, 83, 107, 217, 11, +]); + +// Burn event signature +pub const BURN_EVENT_SIGNATURE: B256 = FixedBytes([ + 158, 150, 221, 59, 153, 122, 42, 37, 126, 236, 77, 249, 187, 110, 175, 98, 110, 32, 109, 245, + 245, 67, 189, 150, 54, 130, 209, 67, 48, 11, 227, 16, +]); + +// Mint event signature +pub const MINT_EVENT_SIGNATURE: B256 = FixedBytes([ + 38, 245, 90, 133, 8, 29, 36, 151, 78, 133, 198, 192, 0, 69, 208, 240, 69, 57, 145, 233, 88, + 115, 245, 43, 255, 13, 33, 175, 64, 121, 167, 104, +]); + +#[derive( + Debug, Clone, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, Hash, PartialEq, Eq, +)] +pub struct CurvePool { + pub address: Address, + pub tokens: Vec
, + pub token_decimals: Vec, + pub fee: U256, + pub admin_fee: U256, + pub a_value: U256, + pub base_pool: Address, + pub base_virtual_price: U256, + pub reserves: Vec, + pub rates: Vec, +} + +#[async_trait] +impl UpdatableProtocol for CurvePool { + fn address(&self) -> Address { + self.address + } + + fn sync_from_action(&mut self, _action: Actions) -> Result<(), AmmError> { + todo!("syncing from actions is currently not supported for curve stable pools.") + } + + fn sync_from_log(&mut self, log: Log) -> Result<(), AmmError> { + let event_signature = log.topics()[0]; + + (match event_signature { + BURN_EVENT_SIGNATURE => self.sync_from_burn_log(log), + MINT_EVENT_SIGNATURE => self.sync_from_mint_log(log), + SWAP_EVENT_SIGNATURE | SWAP_UNDERLYING_EVENT_SIGNATURE => self.sync_from_swap_log(log), + _ => Err(EventLogError::InvalidEventSignature.into()), + })?; + + Ok(()) + } + + fn calculate_price( + &self, + base_token: Address, + quote_token: Option
, + ) -> Result { + let base_token_index = self.tokens.iter().position(|x| x == &base_token); + let quote_token_index = self.tokens.iter().position(|x| x == "e_token.unwrap()); + let price = calculate_exchange_rate_stable( + self.rates[self.tokens.len() - 1], + self.reserves.clone(), + self.rates.clone(), + U256::from(self.tokens.len()), + quote_token_index.unwrap(), + base_token_index.unwrap(), + self.a_value, + ); + let price_as_rational = + price.to_scaled_rational(self.token_decimals[base_token_index.unwrap()]); + + Ok(price_as_rational) + } + + fn tokens(&self) -> Vec
{ + self.tokens.clone() + } +} + +impl CurvePool { + async fn populate_data( + &mut self, + block: Option, + middleware: Arc, + ) -> Result<(), AmmError> { + get_curve_pool_data_batch_request(self, block, middleware).await + } + + // Creates a new instance of the pool from the pair address + pub async fn new_from_address( + pair_address: Address, + block_number: u64, + middleware: Arc, + db: &DB, + ) -> Result { + let pool_details = db.get_protocol_details(pair_address)?; + let tokens = collect_addresses(&pool_details); + let mut pool = CurvePool { + address: pair_address, + tokens, + token_decimals: Vec::new(), + fee: U256::ZERO, + admin_fee: U256::ZERO, + a_value: U256::ZERO, + rates: Vec::new(), + ..Default::default() + }; + + pool.populate_data(Some(block_number), middleware).await?; + + if !pool.data_is_populated() { + return Err(AmmError::NoStateError(pair_address)) + } + + Ok(pool) + } + + pub fn data_is_populated(&self) -> bool { + !(self.reserves.is_empty() || self.tokens.is_empty()) + } + + fn sync_from_burn_log(&mut self, log: Log) -> Result<(), AmmError> { + let burn_event = ICurvePool::RemoveLiquidity::decode_log_data(&log, false)?; + for (i, amount) in burn_event.token_amounts.iter().enumerate() { + self.reserves[i] -= amount; + } + + Ok(()) + } + + fn sync_from_mint_log(&mut self, log: Log) -> Result<(), AmmError> { + let mint_event = ICurvePool::AddLiquidity::decode_log_data(&log, false)?; + let fee_denominator = U256::from(10).pow(U256::from(10)); + + for (i, amount) in mint_event.token_amounts.iter().enumerate() { + self.reserves[i] += amount; + + let fee_amount = mint_event.fees[i] * (self.admin_fee / fee_denominator); + self.reserves[i] -= fee_amount; + } + + Ok(()) + } + + fn sync_from_swap_log(&mut self, log: Log) -> Result<(), AmmError> { + let event_signature = log.topics()[0]; + let token_exchange_event = ICurvePool::TokenExchange::decode_log_data(&log, false)?; + let token_exchange_underlying_event = + ICurvePool::TokenExchangeUnderlying::decode_log_data(&log, false)?; + + let (tokens_sold, tokens_bought, sold_id, bought_id) = match event_signature { + SWAP_EVENT_SIGNATURE => ( + token_exchange_event.tokens_sold, + token_exchange_event.tokens_bought, + token_exchange_event.sold_id, + token_exchange_event.bought_id, + ), + SWAP_UNDERLYING_EVENT_SIGNATURE => ( + token_exchange_underlying_event.tokens_sold, + token_exchange_underlying_event.tokens_bought, + token_exchange_underlying_event.sold_id, + token_exchange_underlying_event.bought_id, + ), + _ => { + return Err(AmmError::EventLogError(EventLogError::InvalidEventSignature)); + } + }; + self.rates[bought_id as usize - 1] = self.base_virtual_price; + let bought_amount_admin_fee = calculate_bought_amount_admin_fee( + self.rates.clone(), + self.admin_fee, + self.fee, + tokens_bought, + bought_id as usize, + ); + + self.reserves[sold_id as usize - 1] += tokens_sold; + self.reserves[bought_id as usize - 1] -= tokens_bought + bought_amount_admin_fee; + + Ok(()) + } +} + +fn collect_addresses(protocol_info: &ProtocolInfo) -> Vec
{ + let mut addresses = Vec::new(); + + addresses.push(protocol_info.token0); + addresses.push(protocol_info.token1); + + if let Some(token2) = &protocol_info.token2 { + addresses.push(*token2); + } + if let Some(token3) = &protocol_info.token3 { + addresses.push(*token3); + } + if let Some(token4) = &protocol_info.token4 { + addresses.push(*token4); + } + if let Some(curve_lp_token) = &protocol_info.curve_lp_token { + addresses.push(*curve_lp_token); + } + + addresses +} diff --git a/crates/brontes-pricing/src/protocols/curve/mod.rs b/crates/brontes-pricing/src/protocols/curve/mod.rs new file mode 100644 index 000000000..0863affa4 --- /dev/null +++ b/crates/brontes-pricing/src/protocols/curve/mod.rs @@ -0,0 +1,2 @@ +pub mod curve_stable_pool; +pub mod curve_crypto_pool; diff --git a/crates/brontes-pricing/src/protocols/mod.rs b/crates/brontes-pricing/src/protocols/mod.rs index fe2b206f5..e3edb0400 100644 --- a/crates/brontes-pricing/src/protocols/mod.rs +++ b/crates/brontes-pricing/src/protocols/mod.rs @@ -1,5 +1,6 @@ pub mod errors; pub mod lazy; +pub mod curve; pub mod uniswap_v2; pub mod uniswap_v3;