From f36525c0a31dafcf2c7e5fc7ab0237094799e735 Mon Sep 17 00:00:00 2001 From: Lee Date: Thu, 4 Jul 2024 08:57:00 -0500 Subject: [PATCH] smoother print statements/logging --- contracts/Liquidator.sol | 16 ++- .../__pycache__/liquidator.cpython-312.pyc | Bin 4140 -> 5881 bytes python/execute/liquidator.py | 58 +++++---- python/liquidation_bot.py | 10 +- .../__pycache__/monitor.cpython-312.pyc | Bin 5389 -> 6836 bytes .../__pycache__/position.cpython-312.pyc | Bin 2856 -> 3337 bytes .../__pycache__/position_list.cpython-312.pyc | Bin 6314 -> 7081 bytes .../profitability_calculator.cpython-312.pyc | Bin 3922 -> 4027 bytes .../__pycache__/vault_list.cpython-312.pyc | Bin 3813 -> 3857 bytes python/monitor/monitor.py | 58 ++++++--- python/monitor/position_list.py | 21 ++- python/monitor/profitability_calculator.py | 8 +- python/monitor/vault_list.py | 2 +- .../basic_deposit_liquidation_scenario.py | 122 +++++++++--------- 14 files changed, 163 insertions(+), 132 deletions(-) diff --git a/contracts/Liquidator.sol b/contracts/Liquidator.sol index 8c7a619..3c4671d 100644 --- a/contracts/Liquidator.sol +++ b/contracts/Liquidator.sol @@ -74,7 +74,7 @@ contract Liquidator { evc.enableController(msg.sender, params.vaultAddress); // TODO: use swapper in correct way - // TODO: correctly use sub account instead of msg.sender + // TODO: correctly use evc account instead of msg.sender multicallItems[0] = abi.encodeCall( ISwapper.swap, ISwapper.SwapParams({ @@ -86,7 +86,7 @@ contract Liquidator { vaultIn: params.vaultAddress, receiver: params.vaultAddress, amountOut: 0, - data: params.swapData + data: injectReceiver(swapperAddress, params.swapData) }) ); @@ -157,4 +157,16 @@ contract Liquidator { return true; } + + // Need to understand this more + function injectReceiver(address receiver, bytes memory _payload) internal pure returns (bytes memory payload) { + payload = _payload; + + // uint256 constant RECEIVER_OFFSET = 208; + + assembly { + mstore(0, receiver) + mcopy(add(add(payload, 32), 208), 12, 20) + } + } } diff --git a/python/execute/__pycache__/liquidator.cpython-312.pyc b/python/execute/__pycache__/liquidator.cpython-312.pyc index 246f5ef3d0f52f6f887450bff02af50283afcba5..eb66104e5b88c8ede183577e70b90b81064252ed 100644 GIT binary patch literal 5881 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 delta 1947 zcmZ8iTTB#J7(Qp`vKRIS>?$D3E;3%$3!)X;s1Ze_5Dio=K@eTWnL}MV>?~(y<2@o|ki$Z6xy-J{;PoO)t``|2 zp30^)Zz(N4X;0hJAhsGZ4asaZY?>o8rxhe^9|{;*cd1e53Dm^0HHi`?JEWjdA@VPHT#}7B%mmqW+hrL1QA~f(`+A9~)lFM#Nt%^Y~?x_L# zMj|Q<0pQ4_?`>nrUh2F(?R)FcOFC)N_la-Zx6DW3C|D_pzilF5{OawVirP*01u>=Q zhnG9q^j(Onim0pD5_rz37^|a5KCEd-H~o^TD8v9^QCXIF#9=j+(7V(QloZF!5;T@X zl8)pf#BkZpbZDbu@~EhbFKMGkS<^0^7vqUm+1TqVn<}@?897=JEhS0hL=C2tT9<1g zxK<@2U5qQ*J{P9P&16OVq1H7KS!*+NAdq9GJPWZ8J1%hen$F}Wlr4TINHKj&a7 zA?YNSW;$s{84iCrPum6ujV=CL)!rml=@L4SgyKovbRHX%P?9=C{kV+S8J{{QjDP*{ zJtjn&p9muV8#qMsl%g>trF0adN$52~A{dv8BU2Sbt9?&);v#q*08VelFJv~=XM~1F zLytp`eVKMSgFep4={!01u+v6ZmrbFp(>6@munkk@(`>H+aO$?aquN=X3sujD>a(Hx z`A}mv)Hok%&4yYtr_bk3f0XN0bNza*_k8Z`NUrNl#h)JjIE=wXz*h~xB{vWuhS`CU zT+b<^wd7!l2HS{^6Ja~ddw^#{zQVX!GBR~C8$6lm=${RqnQ4CEF3yzfnse7JP_S*z zy`6w-n{O0fkKSm`mekC-h3BQ~|61^sy#lg;UX+&ollKtC8;$Pg ztz(g6`@zrqoy`LCgk9GhW}bvOf~D14lNcFSOMir6qc;$NyN%BSds>P+Nlzsaj;!3l z`yx>e??rxwVU|Gbr^HK1A$T`vA#gS08^?iRRZc1BAU;KG=*MeeLh=lR b@ENFj27-S8=Wn2BiEV*!0KNhRRtWGP36}i# diff --git a/python/execute/liquidator.py b/python/execute/liquidator.py index 1eb27b0..a8507fa 100644 --- a/python/execute/liquidator.py +++ b/python/execute/liquidator.py @@ -4,17 +4,18 @@ import time import os import json +import threading from monitor.monitor import Monitor from monitor.position import Position class Liquidator: - def __init__(self, liquidation_contract_address: str, monitor_instance: Monitor, run_with_monitor: bool = False): + def __init__(self, liquidator_contract_address: str, monitor_instance: Monitor, run_with_monitor: bool = False): LIQUIDATOR_ABI_PATH = 'out/Liquidator.sol/Liquidator.json' with open(LIQUIDATOR_ABI_PATH, 'r') as file: - liquidation_interface = json.load(file) + liquidator_interface = json.load(file) - liquidation_abi = liquidation_interface['abi'] + liquidator_abi = liquidator_interface['abi'] load_dotenv() @@ -23,19 +24,20 @@ def __init__(self, liquidation_contract_address: str, monitor_instance: Monitor, w3 = Web3(Web3.HTTPProvider(rpc_url)) self.w3 = w3 - self.liquidation_contract_address = liquidation_contract_address - self.liquidation_abi = liquidation_abi + self.liquidator_contract_address = liquidator_contract_address + self.liquidator_abi = liquidator_abi - self.liquidator_contract = w3.eth.contract(address=liquidation_contract_address, abi=liquidation_abi) + self.liquidator_contract = w3.eth.contract(address=liquidator_contract_address, abi=liquidator_abi) self.monitor_instance = monitor_instance if(run_with_monitor): - self.start() + self.monitor_listener_thread = threading.Thread(target=self.start) + self.monitor_listener_thread.start() def start(self): while True: - print("Checking for profitable liquidation opportunities to execute...\n") + print("Liquidator: Checking for profitable liquidation opportunities to execute...\n") try: profitable_liquidation = self.monitor_instance.position_list.pop_profitable_liquidation() @@ -61,7 +63,8 @@ def start(self): liquidator_private_key) except Exception as e: - print("No profitable liquidation opportunities found.\n") + print("ERROR: Liquidator: No profitable liquidation opportunities found.\n") + print("ERROR: Liquidator: Error: ", e, "\n") time.sleep(10) continue @@ -76,22 +79,23 @@ def execute_liquidation(self, swap_data, caller_public_key, caller_private_key): - print(f"Trying to liquidate {violator_address} in vault {vault_address} with borrowed asset {borrowed_asset_address} and collateral asset {collateral_asset_address}...\n") + print(f"Liquidator Trying to liquidate {violator_address} in vault {vault_address} with borrowed asset {borrowed_asset_address} and collateral asset {collateral_asset_address}...\n") #TODO: enable collateral & controller at EVC level for liquidation try: - liquidation_tx = self.liquidator_contract.functions.liquidate({'vaultAddress': vault_address, - 'violatorAddress': violator_address, - 'borrowedAsset': borrowed_asset_address, - 'colllateralAsset': collateral_asset_address, - 'amountToRepay': amount_to_repay, - 'expectedCollateral': expected_collateral, - 'swapData': swap_data}).build_transaction({ - 'chainId': 1, + liquidation_tx = self.liquidator_contract.functions.liquidate((vault_address, + violator_address, + borrowed_asset_address, + collateral_asset_address, + amount_to_repay, + expected_collateral, + swap_data + )).build_transaction({ + 'chainId': 41337, 'gasPrice': self.w3.eth.gas_price, 'from': caller_public_key, - 'nonce': self.w3.eth.get_transaction_count(caller_public_key) + 'nonce': self.w3.eth.get_transaction_count(caller_public_key) }) signed_tx = self.w3.eth.account.sign_transaction(liquidation_tx, caller_private_key) @@ -100,26 +104,26 @@ def execute_liquidation(self, tx_receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash) - result = self.liquidator_contract.events.Liquidation().processReceipt(tx_receipt) + result = self.liquidator_contract.events.Liquidation().process_receipt(tx_receipt) - print("Liquidation successful.\n\n") - print("Liquidation details:\n") + print("Liquidator: Liquidation details:") print(result[0]['args']) + print("Liquidator: Liquidation successful.") return True except Exception as e: - print("Liquidation failed, see error:\n\n") + print("ERROR: Liquidator: Liquidation failed, see error:") - print(e) + print("ERROR: Liquidator:", e, "\n") return False def test_contract_deployment(self): - print("Testing contract deployment...\n") + print("Liquidator: Testing contract deployment...\n") - print("Trying to get swapper address from liquidator...\n") - print("Swapper address: " + self.liquidator_contract.functions.swapperAddress().call()) + print("Liquidator: Trying to get swapper address from liquidator...\n") + print("Liquidator: Swapper address: " + self.liquidator_contract.functions.swapperAddress().call()) # if __name__ == "__main__": diff --git a/python/liquidation_bot.py b/python/liquidation_bot.py index 49b0e5a..43da512 100644 --- a/python/liquidation_bot.py +++ b/python/liquidation_bot.py @@ -9,13 +9,7 @@ def __init__(self): load_dotenv() self.monitor = Monitor(0.1, 0.2, 0.2, 0.2, 1) - self.liquidator = Liquidator(os.getenv('LIQUIDATOR_ADDRESS'), self.monitor) - - def start(self): - self.monitor.start() - - #TODO: change to IO model for reading outputs from monitor to trigger liquidation + self.liquidator = Liquidator(os.getenv('LIQUIDATOR_ADDRESS'), self.monitor, True) if __name__ == "__main__": - bot = LiquidationBot() - bot.start() \ No newline at end of file + bot = LiquidationBot() \ No newline at end of file diff --git a/python/monitor/__pycache__/monitor.cpython-312.pyc b/python/monitor/__pycache__/monitor.cpython-312.pyc index 84cb90e4df842d76ea8ec7613328fcd6e133264a..cbdf40bafb2e55ddb7df797b958332901ce415e3 100644 GIT binary patch delta 2251 zcmchY?@wD*7{~8zd+87Q|yN#gp7` zPtQHi({n!G)8{OmzSpIHpwnpx)Lg3{UEVZ(qi0ES;_fgxAXD5R-f==&)dWA4vt%87 zApfyeH=9Z)GKp03(llIGG%EL~bSBDW;CG5;@_RT=eZ@38SKID%taao(n>`ynyUl~Q z6oRVpH&gu=8L`2^H#k-;cbe9kb{o9ArtVvc+sa>5+Rro}YnHTkZ8hJ@G@Y-el8H=; zV`%uR>N>@}fR+ZM>I1uzs{1ilCPVy}7nc`-Xkfwc!$(2+u@zE{yZcxB%XG1S~6>WzCl! z(dy%^zT5%eTDlkW+r&NuhpqSDr7q^11C5r+DA}T?x+!zBv1kUHGL^V8MRSSt)nm3O;jrG`f^l;U76TR^78Xg#8MvfBogKs@ z3rI?)u#zVs0SuIR;^%>10DWcjyLf9?PR3gq0r)ED7cz`&M+GoeEkXo79{42oEPHrR zV6P0;5?i(EkXF8Bafg)h`$`J+pBej;{tbw|tH_>)_YAgx1mF7<_%rcXVs54y{+|ra zGW-COuY$h?yqGcXY4fr zM5={|0NaWApV9>mxqkHX{}<;|k2wz+n|mbAXP?43m6?ij6$gCAXe%RZL_4TPc-`2M zeG|Pqe!%?_;Q%_$WrT6jK_|HkmzTGCb0$<{1i)4hE@XIlyF~ya)gnZ|@_>~Nc$@zj z1J0gYMA}M#U$3m(*P?UNnY7#O)^HN{j_TZ>sQ86ARPL2rC%WDKF*TK;H~$BEkGUfo z!|1OeDb*Il7u9=INdgG{iecFxf^$4LCxEUpj2_HVSLjTZe%s?VbP%{ZAbDUk(ZgNy8Kx{g~@!o ziVBhWdKJZD31IObSX7jcvq7Jwxkf6n?eJ~OTa80FRVnkKik(Tt=BDETZVc{PT!u>| L>B|#XrAhw+!rfWg delta 1203 zcma)*O-vI(6o7Zz-9npbDJ^!P6sZMl7n=T3T1w?WLsX<-DhUU;C{(FGt(mSQRuepE zA|{ABCdL@=a?uh@z=QGNN#(%A)e^$NgYjZaOgZVvnL@)RO$?LFmzmkOGvB^_^E$N9 zY51hq>lo4|*YBL4H7pxqEIY7rijAw#OLdHGKtI)Ab>M0?mzL7m%rIK#tmqf_ko|z> z_-7WI>qWz>)}_|9_IIu~uFtmkT~4lTLOxBCYN2LjO!HR7il|w8y=IHgNoS#io@#fT zODt?92j*A;JG2u*ksz;6WHV_g3q9q~cC@1V(H{L$+Xo%w=@gBwG>#0^r0;AJJVDCf;80@YbP|V>GB~phjEh6_Ll2~)5XM4y&4GoO437P- zVd~8Pk$p^M87(8B@0R=g2~jtv4?4zioP}-yS#?DkfS2T~;Ye55JsIS@9rRr~^GQQ>E-^1Eqvrv|J2 z!ZL^`{Gu2{We`*N1+fq;oWlaq?me)dSoX8UXHrv_(wPhPtTdB?_DY%NJRXk@?&bC4 zp*DqgeU-Pt;!O=#d;4V&P1&r${V;*@)~>pfEE_H{ Hl;xm*S6U)+xnznwOW00SNBSZ%d0|pU5|l(PH9SW3CjA7KSL!N={9#jZc`_h1q~An1T57 z1|Tt=p@t!gaq@a*IgVP!S|%WeX|f};@MH&OVJRR7q!tapl!$PkNdUPulP|K0*4HrB zFr~2tGiWmUX|fe50mX}WfW$4{vc%GylK8}wl%mw);v!Cvm_%t_N@`I~WoBM_d}48N zDnc6M6HVqKL69o`#N7PSyps5m{P?2Og2c*O!l@MnsmUd&De=kqIXQ_XsYQu7#UM{9 zC@9ny34!#8qyr7h$t*0*Oi3)s%+HGlQi)Zv0r|z5Ag&%ZX$7Fh;vgW=z;MIR^tz$@ zMML+?hMpHW^g84(Na@}X5Sh+3k?XpE#zg^*8$1Hnc@!`5C;}P%UY%aodGs&x=mR-o z*LgHA@@U@Rk-otr|ACuTK=A_uE2rY-tL&bPtVJq7(&q9;uaJfktf+R&i1jt{%IBatBQ%ZAE?TSn%|KXD7 N)nF9;!~i6~N&wd`ivj=u delta 137 zcmeB_S|P@FnwOW00SH{rx2FALoya$j(P-jYW0pz|P0o$4nAta<;529Czr|aYSejE3 zpO}(Tlv-RonT6YvQDL$l_f$sC$xpcL7}Y0h@W?S5PIl+fXZp-Bxt7OGN(X3WkqC$o g0usMCY;yBcN^?@}iVP;-<&o!=XB7R!03^Ul0N7F`NdN!< diff --git a/python/monitor/__pycache__/position_list.cpython-312.pyc b/python/monitor/__pycache__/position_list.cpython-312.pyc index 9e77d9f784c5f1648cc60c61add64199340df8ee..335e270967846aac72a0624e2b2635e808be80a6 100644 GIT binary patch delta 2375 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 diff --git a/python/monitor/__pycache__/profitability_calculator.cpython-312.pyc b/python/monitor/__pycache__/profitability_calculator.cpython-312.pyc index 3d2132cc1c8bc1243732732c582d2cf4e315da09..30c518b69626ce141e67d38d98312a3e00a2e790 100644 GIT binary patch delta 547 zcmca4w_Bd~G%qg~0}!|_YfHPgk@q|&7blR%48)%|O@79i$&$i3mwj>|mp&ucv*t3VBVme6E= zZc%2=xvZ1zxuwM=YdK3;VX9O3YB*;z0PSI(oX@SwC^&g4ce03HKv8~LW{HAxVoq{t zPGU)Zk(I*apWG_Uw}1|j<&msc#-hM5GcP$qp(wSuAV04-)k@(OXG(F2V{U$FUP+Y( z7WJ-0MfpVvDXGc%DVcfc3SPnfepU)q=2%oZ26zI^Ei6qfE>TEJ%*;uhT*K4K<^l9V zk>_M~UMI#slf8HyWUY2s?$ACEc%b4y)`ftO3!!lrLgFvPCtl!6y26q?c_FW9z4;E= z6D(JFeD4U0O{iTEeNo)-varzw9-}W@44ixy1l&(>T=$5%=n-?lJ@!Iu{Dp*!>j}9R z6LK%a=UvDvxWHFe)sYpdM= delta 455 zcmdlje@Tw_G%qg~0}z;9X-#X}$a|iXiv!4G2I9}FCO_lMWSYx1IhaeIn{zct3xTaZ&2LevB7Fb$N|j*(igaVudw({{>N)tud*Qb3XjPhVX+Cd3!*QI z8(tPRy1--fg^Pic?}C8IhKTE?o)=9$FPM0pP&yHDKK5kn3I7XxF;_TZZ}1EM_`=N~ zAoYoXiBsYZkKhFn%@v9(gf9r`Ug6QZBP{;=11nJCSFr@pIR_OroeUWc8FD%cF(0zx tbLM3}%*zU7Yfj$BCok#)a&h2LSXDbsPWy diff --git a/python/monitor/__pycache__/vault_list.cpython-312.pyc b/python/monitor/__pycache__/vault_list.cpython-312.pyc index 06c208a9c1c2144a231f8613e13d1db2ea3f52cd..4e5e84ad183d6a82c18be9d937c08d639b9ec7da 100644 GIT binary patch delta 322 zcmaDVJ5i4JG%qg~0}xzW+LktdBX18IKL?P<48)&97#SF*GfbA{7N5MIEsN1%vKD)h zSPI)**401>5MX5JabjVpVaO7itjH}q`7pZ~Bm3lE>@vJ+VTq+VB?>;7#U)k>lf^j< zm~Sz1O?KzF%(#8BG^Z7l8`I=)PF+i@9kx64FL=gYh)e&@z!1;q$n+6HePCdSV{~Ey zQcg@RAWGPk=_>;RuN%_`UN%mk?j@XS*$ja$DAJ!C&SfWL3}Tu92~DOV8Hn(5E-yyI z$)C7RvKFZUMJDg#juq7gsbB%CxW$%VT2fG20yMyYXAMy0T^@TOQ;=435Md7_Rx%VB dPS)d%0!nuBuIAPPiMxUb!^!r1i&#L`0|0&`O~L>G delta 263 zcmbOz_f(emG%qg~0}xnmZ%v!Hk++A9n;pnw2I9{_jFabZNlo6zmd$8CS&O}hZ!XJf zMvz(t21bS+$H{Bh{TbON|6!M5l$xx{VK6y@<1*vC$vT`?OcjiiGdOh>^j6fa$iHA4 zcp)hIdQi#5pppxLr5A+CuJV+B;AP_kDmurxmdyZYT#?@7MlL%cBM{RVNN6$@$v}iJ za(OWtOqSt3$$X2EYw|1ZSWzvIJPTO<7F&L4NkM4|P 1: self.other_positions[id] = self.high_risk_positions.pop(id) - if pos.health_score < 1: + if pos.health_score < 1 and id not in self.profitable_liquidations_queue: max_repay, expected_yield = pos.check_liquidation() - print(f"Possible liquidation found in vault {pos.vault.vault_address} for borrower {pos.borrower_address}...") - print(f"Max repay: {max_repay}, Expected yield: {expected_yield}") + print(f"Position List: Possible liquidation found in vault {pos.vault.vault_address} for borrower {pos.borrower_address}...\n") + print(f"Position List: Max repay: {max_repay}, Expected yield: {expected_yield}\n") #TODO: add filter to exclude small size positions profitable = check_if_liquidation_profitable(pos.vault.vault_address, pos.borrower_address, pos.vault.underlying_asset_address, self.vault_list.get_vault(pos.collateral_asset_address).underlying_asset_address, max_repay, expected_yield) if profitable: - print(f"Position in vault {pos.vault.vault_address} is profitable to liquidate.") - print(f"Borrower: {pos.borrower_address}") - print(f"Max repay: {max_repay}, Expected yield: {expected_yield}") - if id not in self.profitable_liquidations_queue: - self.profitable_liquidations_queue.append(id) + print(f"Position List: Position in vault {pos.vault.vault_address} is profitable to liquidate.") + print(f"Position List: Borrower: {pos.borrower_address}") + print(f"Position List: Max repay: {max_repay}, Expected yield: {expected_yield}\n") + self.profitable_liquidations_queue.append(id) # Update medium risk positions # These are positions with a health score <= 1.15 that have potential to move to high risk @@ -124,4 +122,5 @@ def get_position(self, position_id: int): return self.all_positions[position_id] def pop_profitable_liquidation(self): - return self.profitable_liquidations_queue.pop(0) \ No newline at end of file + id = self.profitable_liquidations_queue.pop(0) + return self.all_positions[id] \ No newline at end of file diff --git a/python/monitor/profitability_calculator.py b/python/monitor/profitability_calculator.py index 92a6767..7981d22 100644 --- a/python/monitor/profitability_calculator.py +++ b/python/monitor/profitability_calculator.py @@ -66,19 +66,19 @@ def get_1inch_quote(asset_in: str, asset_out: str, amount_in: int): "amount": amount_in } - print(f"Requesting 1inch quote for {amount_in} {asset_in} to {asset_out}") + print(f"Profit Calculator: Requesting 1inch quote for {amount_in} {asset_in} to {asset_out}\n") response = requests.get(apiUrl, headers=headers, params=params) if response.status_code == 200: try: response_json = response.json() - print("1inch response: ", response_json) + print("Profit Calculator: 1inch response: ", response_json, "\n") return int(response_json['dstAmount']) except ValueError as e: - print(f"Error decoding JSON: {e}") + print(f"Profit Calculator: Error decoding JSON: {e}\n") return None else: - print(f"API request failed with status code {response.status_code}: {response.text}") + print(f"Profit Calculator: API request failed with status code {response.status_code}: {response.text}\n") return None diff --git a/python/monitor/vault_list.py b/python/monitor/vault_list.py index da520f8..e5d57dc 100644 --- a/python/monitor/vault_list.py +++ b/python/monitor/vault_list.py @@ -40,7 +40,7 @@ def scan_for_new_vaults(self): self.vault_dict[vault_address] = new_vault - print(f"New vault found! Address: {vault_address}, underlying asset: {new_vault.underlying_asset_address}") + print(f"Vault List: New vault found! Address: {vault_address}, underlying asset: {new_vault.underlying_asset_address}\n") self.latest_block_number = self.w3.eth.block_number diff --git a/python/test_scripts/basic_deposit_liquidation_scenario.py b/python/test_scripts/basic_deposit_liquidation_scenario.py index bc87ba7..c657df5 100644 --- a/python/test_scripts/basic_deposit_liquidation_scenario.py +++ b/python/test_scripts/basic_deposit_liquidation_scenario.py @@ -37,69 +37,69 @@ def test_basic_deposit_liquidation_scenario(): w3 = Web3(Web3.HTTPProvider(rpc_url)) - # print("Setting up Vault 1 deposits...") + # print("Test Scenario: Setting up Vault 1 deposits...") # approve_and_deposit_in_vault(vault_1, token_1, 1*10**15, deployer, deployer_private_key, w3, CHAIN_ID) - # print("Setting up Vault 2 deposits...") + # print("Test Scenario: Setting up Vault 2 deposits...") # approve_and_deposit_in_vault(vault_2, token_2, 1*10**15, deployer, deployer_private_key, w3, CHAIN_ID) - print("Checking vault balance...") - print(f"Vault balance: {vault_1.instance.functions.balanceOf(deployer).call()}") + print("Test Scenario: Checking vault balance...") + print(f"Test Scenario: Vault balance: {vault_1.instance.functions.balanceOf(deployer).call()}") - print("Checking asset balance...") - print(f"Asset balance: {token_1.instance.functions.balanceOf(deployer).call()}") + print("Test Scenario: Checking asset balance...") + print(f"Test Scenario: Asset balance: {token_1.instance.functions.balanceOf(deployer).call()}") - print("Checking vault balance...") - print(f"Vault balance: {vault_2.instance.functions.balanceOf(deployer).call()}") + print("Test Scenario: Checking vault balance...") + print(f"Test Scenario: Vault balance: {vault_2.instance.functions.balanceOf(deployer).call()}") - print("Checking asset balance...") - print(f"Asset balance: {token_2.instance.functions.balanceOf(deployer).call()}") + print("Test Scenario: Checking asset balance...") + print(f"Test Scenario: Asset balance: {token_2.instance.functions.balanceOf(deployer).call()}") - # print("Setting LTV") + # print("Test Scenario: Setting LTV") # set_ltv(vault_1, vault_2, int(0.9*10**4), deployer, deployer_private_key, w3, CHAIN_ID) - print("Checking LTV set correctly") - print(f"LTV: {vault_1.instance.functions.LTVBorrow(TEST_VAULT_2_ADDRESS).call()}") + print("Test Scenario: Checking LTV set correctly") + print(f"Test Scenario: LTV: {vault_1.instance.functions.LTVBorrow(TEST_VAULT_2_ADDRESS).call()}") - # print("Enabling collateral") + # print("Test Scenario: Enabling collateral") # enable_collateral(evc, vault_2, deployer, deployer_private_key, w3, CHAIN_ID) - print("Checking collateral status") - print(f"Collateral status: {evc.instance.functions.isCollateralEnabled(deployer, vault_2.vault_address).call()}") + print("Test Scenario: Checking collateral status") + print(f"Test Scenario: Collateral status: {evc.instance.functions.isCollateralEnabled(deployer, vault_2.vault_address).call()}") - # print("Enabling controller") + # print("Test Scenario: Enabling controller") # enable_controller(evc, vault_1, deployer, deployer_private_key, w3, CHAIN_ID) - print("Checking controller status") - print(f"Controller status: {evc.instance.functions.isControllerEnabled(deployer, vault_1.vault_address).call()}") + print("Test Scenario: Checking controller status") + print(f"Test Scenario: Controller status: {evc.instance.functions.isControllerEnabled(deployer, vault_1.vault_address).call()}") - print("Checking account liquidity") - print(f"Account liquidity: {vault_1.instance.functions.accountLiquidity(deployer, False).call()}") + print("Test Scenario: Checking account liquidity") + print(f"Test Scenario: Account liquidity: {vault_1.instance.functions.accountLiquidity(deployer, False).call()}") - # print("Setting up oracle prices") - # set_asset_price(vault_1.underlying_asset_address, oracle, UNIT_OF_ACCOUNT, 1*10**18, deployer, deployer_private_key, w3, CHAIN_ID) + # print("Test Scenario: Setting up oracle prices") + set_asset_price(vault_1.underlying_asset_address, oracle, UNIT_OF_ACCOUNT, 1*10**18, deployer, deployer_private_key, w3, CHAIN_ID) # set_asset_price(vault_2.underlying_asset_address, oracle, UNIT_OF_ACCOUNT, 1*10**18, deployer, deployer_private_key, w3, CHAIN_ID) # set_asset_price(TEST_VAULT_1_ADDRESS, oracle, UNIT_OF_ACCOUNT, 1*10**18, deployer, deployer_private_key, w3, CHAIN_ID) # set_asset_price(TEST_VAULT_2_ADDRESS, oracle, UNIT_OF_ACCOUNT, 1*10**18, deployer, deployer_private_key, w3, CHAIN_ID) - # print("Asset prices set") + # print("Test Scenario: Asset prices set") - # print("Attempting borrow") + # print("Test Scenario: Attempting borrow") # borrow_amount = 1*10**10 # create_borrow(borrow_amount, vault_1, deployer, deployer_private_key, w3, CHAIN_ID) - print("Checking account liquidity") - print(f"Account liquidity: {vault_1.instance.functions.accountLiquidity(deployer, False).call()}") + print("Test Scenario: Checking account liquidity") + print(f"Test Scenario: Account liquidity: {vault_1.instance.functions.accountLiquidity(deployer, False).call()}") - print("Changing price of borrowed asset") - set_asset_price(vault_1.underlying_asset_address, oracle, UNIT_OF_ACCOUNT, 1*10**23, deployer, deployer_private_key, w3, CHAIN_ID) + print("Test Scenario: Changing price of borrowed asset") + # set_asset_price(vault_1.underlying_asset_address, oracle, UNIT_OF_ACCOUNT, 1*10**23, deployer, deployer_private_key, w3, CHAIN_ID) - print("Checking account liquidity after price change") - print(f"Account liquidity: {vault_1.instance.functions.accountLiquidity(deployer, False).call()}") + print("Test Scenario: Checking account liquidity after price change") + print(f"Test Scenario: Account liquidity: {vault_1.instance.functions.accountLiquidity(deployer, False).call()}") def approve_and_deposit_in_vault(vault: Vault, token: Token, amount, depositor_address, depositor_key, w3: Web3, chain_id): - print(f"Approving {amount} tokens for deposit of {token.token_address} into {vault.vault_address}...") + print(f"Test Scenario: Approving {amount} tokens for deposit of {token.token_address} into {vault.vault_address}...") approval_tx = token.instance.functions.approve(vault.vault_address, amount).build_transaction({ 'chainId': chain_id, @@ -111,21 +111,21 @@ def approve_and_deposit_in_vault(vault: Vault, token: Token, amount, depositor_a signed_tx = w3.eth.account.sign_transaction(approval_tx, depositor_key) tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) - print("Approval transaction sent, waiting for mining...") + print("Test Scenario: Approval transaction sent, waiting for mining...") time.sleep(15) while True: tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) try: approval_logs = token.instance.events.Approval().process_receipt(tx_receipt) - print("Approval successful") + print("Test Scenario: Approval successful") break except: - print("Approval not yet mined, retrying...") + print("Test Scenario: Approval not yet mined, retrying...") time.sleep(3) continue - print(f"Depositing {amount} of {token.token_address} into {vault.vault_address}...") + print(f"Test Scenario: Depositing {amount} of {token.token_address} into {vault.vault_address}...") deposit_tx = vault.instance.functions.deposit(amount, depositor_address).build_transaction({ 'chainId': chain_id, @@ -137,24 +137,24 @@ def approve_and_deposit_in_vault(vault: Vault, token: Token, amount, depositor_a signed_tx = w3.eth.account.sign_transaction(deposit_tx, depositor_key) tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) - print("Deposit transaction sent, waiting for mining...") + print("Test Scenario: Deposit transaction sent, waiting for mining...") time.sleep(15) while True: tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) try: deposit_logs = vault.instance.events.Deposit().process_receipt(tx_receipt) - print("Despoit successful") + print("Test Scenario: Despoit successful") break except Exception as e: deposit_logs = vault.instance.events.Deposit().process_receipt(tx_receipt) - print("Deposit not yet mined, retrying...") - print("Error: ", e) + print("Test Scenario: Deposit not yet mined, retrying...") + print("Test Scenario: Error: ", e) time.sleep(3) continue def set_ltv(borrow_vault: Vault, collateral_vault: Vault, ltv: int, depositor_address, depositor_key, w3: Web3, chain_id): - print(f"Setting {collateral_vault.vault_address} as collateral for {borrow_vault.vault_address} with LTV {ltv}...") + print(f"Test Scenario: Setting {collateral_vault.vault_address} as collateral for {borrow_vault.vault_address} with LTV {ltv}...") ltv_tx = borrow_vault.instance.functions.setLTV(collateral_vault.vault_address, ltv, ltv, 0).build_transaction({ 'chainId': chain_id, @@ -166,23 +166,23 @@ def set_ltv(borrow_vault: Vault, collateral_vault: Vault, ltv: int, depositor_ad signed_tx = w3.eth.account.sign_transaction(ltv_tx, depositor_key) tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) - print("LTV transaction sent, waiting for mining...") + print("Test Scenario: LTV transaction sent, waiting for mining...") time.sleep(15) while True: tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) try: ltv_logs = borrow_vault.instance.events.GovSetLTV().process_receipt(tx_receipt) - print("LTV set successful") + print("Test Scenario: LTV set successful") break except Exception as e: - print("LTV not yet mined, retrying...") - print("Error: ", e) + print("Test Scenario: LTV not yet mined, retrying...") + print("Test Scenario: Error: ", e) time.sleep(3) continue def enable_collateral(evc: EVC, collateral_vault: Vault, depositor_address, depositor_key, w3: Web3, chain_id): - print(f"Enabling {collateral_vault.vault_address} as collateral for account {depositor_address}...") + print(f"Test Scenario: Enabling {collateral_vault.vault_address} as collateral for account {depositor_address}...") enable_collateral_tx = evc.instance.functions.enableCollateral(depositor_address, collateral_vault.vault_address).build_transaction({ 'chainId': chain_id, @@ -194,23 +194,23 @@ def enable_collateral(evc: EVC, collateral_vault: Vault, depositor_address, dep signed_tx = w3.eth.account.sign_transaction(enable_collateral_tx, depositor_key) tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) - print("Enable collateral transaction sent, waiting for mining...") + print("Test Scenario: Enable collateral transaction sent, waiting for mining...") time.sleep(15) while True: tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) try: collateral_status_logs = evc.instance.events.CollateralStatus().process_receipt(tx_receipt) - print("Collateral enabled successful") + print("Test Scenario: Collateral enabled successful") break except Exception as e: - print("Transaction not yet mined, retrying...") - print("Error: ", e) + print("Test Scenario: Transaction not yet mined, retrying...") + print("Test Scenario: Error: ", e) time.sleep(3) continue def enable_controller(evc: EVC, controller_vault: Vault, depositor_address, depositor_key, w3: Web3, chain_id): - print(f"Enabling {controller_vault.vault_address} as controller for account {depositor_address}...") + print(f"Test Scenario: Enabling {controller_vault.vault_address} as controller for account {depositor_address}...") enable_controller_tx = evc.instance.functions.enableController(depositor_address, controller_vault.vault_address).build_transaction({ 'chainId': chain_id, @@ -223,23 +223,23 @@ def enable_controller(evc: EVC, controller_vault: Vault, depositor_address, dep signed_tx = w3.eth.account.sign_transaction(enable_controller_tx, depositor_key) tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) - print("Enable controller transaction sent, waiting for mining...") + print("Test Scenario: Enable controller transaction sent, waiting for mining...") time.sleep(15) while True: tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) try: controller_status_logs = evc.instance.events.ControllerStatus().process_receipt(tx_receipt) - print("Controller enabled successful") + print("Test Scenario: Controller enabled successful") break except Exception as e: - print("Transaction not yet mined, retrying...") - print("Error: ", e) + print("Test Scenario: Transaction not yet mined, retrying...") + print("Test Scenario: Error: ", e) time.sleep(3) continue def set_asset_price(asset_address, oracle: MockOracle, unit_of_account, price: int, depositor_address, depositor_key, w3: Web3, chain_id): - print(f"Setting price of {asset_address} in {unit_of_account} to {price}...") + print(f"Test Scenario: Setting price of {asset_address} in {unit_of_account} to {price}...") set_price_tx = oracle.instance.functions.setPrice(asset_address, unit_of_account, price).build_transaction({ 'chainId': chain_id, @@ -252,11 +252,11 @@ def set_asset_price(asset_address, oracle: MockOracle, unit_of_account, price: i tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction) tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) - print(f"Set price transaction sent for {asset_address}, waiting for mining...") + print(f"Test Scenario: Set price transaction sent for {asset_address}, waiting for mining...") time.sleep(15) def create_borrow(borrow_amount: int, borrow_vault: Vault, depositor_address, depositor_key, w3: Web3, chain_id): - print(f"Borrowing {borrow_amount} from {borrow_vault.vault_address}...") + print(f"Test Scenario: Borrowing {borrow_amount} from {borrow_vault.vault_address}...") borrow_tx = borrow_vault.instance.functions.borrow(borrow_amount, depositor_address).build_transaction({ 'chainId': chain_id, @@ -271,11 +271,11 @@ def create_borrow(borrow_amount: int, borrow_vault: Vault, depositor_address, de tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) try: borrow_logs = borrow_vault.instance.events.Borrow().process_receipt(tx_receipt) - print("Controller enabled successful") + print("Test Scenario: Controller enabled successful") break except Exception as e: - print("Transaction not yet mined, retrying...") - print("Error: ", e) + print("Test Scenario: Transaction not yet mined, retrying...") + print("Test Scenario: Error: ", e) time.sleep(3) continue