@intentsolutionsio/flash-loan-simulator 1.0.0 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -12
- package/agents/flashloan-agent.md +17 -0
- package/package.json +1 -1
- package/skills/simulating-flash-loans/ARD.md +21 -7
- package/skills/simulating-flash-loans/PRD.md +9 -3
- package/skills/simulating-flash-loans/SKILL.md +29 -8
- package/skills/simulating-flash-loans/references/errors.md +47 -2
- package/skills/simulating-flash-loans/references/examples.md +12 -0
- package/skills/simulating-flash-loans/references/implementation.md +6 -0
- package/skills/simulating-flash-loans/scripts/flash_simulator.py +29 -85
- package/skills/simulating-flash-loans/scripts/formatters.py +19 -51
- package/skills/simulating-flash-loans/scripts/profit_calculator.py +16 -16
- package/skills/simulating-flash-loans/scripts/protocol_adapters.py +2 -8
- package/skills/simulating-flash-loans/scripts/risk_assessor.py +6 -17
- package/skills/simulating-flash-loans/scripts/strategy_engine.py +6 -14
|
@@ -9,13 +9,12 @@ Handles all output formatting:
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import json
|
|
12
|
-
from dataclasses import asdict
|
|
13
12
|
from decimal import Decimal
|
|
14
|
-
from typing import
|
|
13
|
+
from typing import List, Optional
|
|
15
14
|
|
|
16
|
-
from strategy_engine import StrategyResult,
|
|
17
|
-
from profit_calculator import ProfitBreakdown
|
|
18
|
-
from risk_assessor import RiskAssessment,
|
|
15
|
+
from strategy_engine import StrategyResult, StrategyType
|
|
16
|
+
from profit_calculator import ProfitBreakdown
|
|
17
|
+
from risk_assessor import RiskAssessment, RiskLevel
|
|
19
18
|
from protocol_adapters import ProviderInfo
|
|
20
19
|
|
|
21
20
|
|
|
@@ -79,8 +78,7 @@ class ConsoleFormatter:
|
|
|
79
78
|
border_left = (inner_width - len(title_part)) // 2
|
|
80
79
|
border_right = inner_width - len(title_part) - border_left
|
|
81
80
|
result.append(
|
|
82
|
-
f"{self.BOX_TL}{self.BOX_H * border_left}{title_part}"
|
|
83
|
-
f"{self.BOX_H * border_right}{self.BOX_TR}"
|
|
81
|
+
f"{self.BOX_TL}{self.BOX_H * border_left}{title_part}{self.BOX_H * border_right}{self.BOX_TR}"
|
|
84
82
|
)
|
|
85
83
|
else:
|
|
86
84
|
result.append(f"{self.BOX_TL}{self.BOX_H * (inner_width + 2)}{self.BOX_TR}")
|
|
@@ -126,14 +124,9 @@ class ConsoleFormatter:
|
|
|
126
124
|
lines.append(self._subheader("PROFIT BREAKDOWN"))
|
|
127
125
|
lines.append(f" Gross Profit: {result.gross_profit:+.6f} {result.loan_asset}")
|
|
128
126
|
lines.append(f" Flash Loan Fee: -{result.loan_fee:.6f} {result.loan_asset}")
|
|
129
|
-
lines.append(
|
|
130
|
-
f" Gas Cost: -{result.gas_cost_eth:.6f} ETH (${result.gas_cost_usd:.2f})"
|
|
131
|
-
)
|
|
127
|
+
lines.append(f" Gas Cost: -{result.gas_cost_eth:.6f} ETH (${result.gas_cost_usd:.2f})")
|
|
132
128
|
lines.append(f" {'-' * 40}")
|
|
133
|
-
lines.append(
|
|
134
|
-
f" Net Profit: {result.net_profit:+.6f} {result.loan_asset} "
|
|
135
|
-
f"(${result.net_profit_usd:+.2f})"
|
|
136
|
-
)
|
|
129
|
+
lines.append(f" Net Profit: {result.net_profit:+.6f} {result.loan_asset} (${result.net_profit_usd:+.2f})")
|
|
137
130
|
lines.append(f" ROI: {result.roi_percent:.4f}%")
|
|
138
131
|
|
|
139
132
|
return "\n".join(lines)
|
|
@@ -150,20 +143,14 @@ class ConsoleFormatter:
|
|
|
150
143
|
# Costs
|
|
151
144
|
lines.append("\n Costs:")
|
|
152
145
|
lines.append(f" Flash Loan Fee: -{breakdown.flash_loan_fee:.6f} ETH")
|
|
153
|
-
lines.append(
|
|
154
|
-
f" Gas Cost: -{breakdown.gas_cost_eth:.6f} ETH "
|
|
155
|
-
f"(${breakdown.gas_cost_usd:.2f})"
|
|
156
|
-
)
|
|
146
|
+
lines.append(f" Gas Cost: -{breakdown.gas_cost_eth:.6f} ETH (${breakdown.gas_cost_usd:.2f})")
|
|
157
147
|
lines.append(f" Est. Slippage: -{breakdown.slippage_cost:.6f} ETH")
|
|
158
148
|
lines.append(f" DEX Fees: ~{breakdown.dex_fees:.6f} ETH (in price)")
|
|
159
149
|
lines.append(f" {'-' * 45}")
|
|
160
150
|
lines.append(f" Total Costs: -{breakdown.total_costs:.6f} ETH")
|
|
161
151
|
|
|
162
152
|
# Net
|
|
163
|
-
lines.append(
|
|
164
|
-
f"\n Net Profit: {breakdown.net_profit:+.6f} ETH "
|
|
165
|
-
f"(${breakdown.net_profit_usd:+.2f})"
|
|
166
|
-
)
|
|
153
|
+
lines.append(f"\n Net Profit: {breakdown.net_profit:+.6f} ETH (${breakdown.net_profit_usd:+.2f})")
|
|
167
154
|
lines.append(f" ROI: {breakdown.roi_percent:.4f}%")
|
|
168
155
|
lines.append(f" Breakeven Gas: {breakdown.breakeven_gas_price:.1f} gwei")
|
|
169
156
|
|
|
@@ -182,9 +169,7 @@ class ConsoleFormatter:
|
|
|
182
169
|
lines.append(self._header("RISK ASSESSMENT"))
|
|
183
170
|
|
|
184
171
|
# Overall rating
|
|
185
|
-
indicator, label = self.RISK_INDICATORS.get(
|
|
186
|
-
assessment.overall_level, ("⚪", "UNKNOWN")
|
|
187
|
-
)
|
|
172
|
+
indicator, label = self.RISK_INDICATORS.get(assessment.overall_level, ("⚪", "UNKNOWN"))
|
|
188
173
|
lines.append(f"\n Overall Risk: {indicator} {label}")
|
|
189
174
|
lines.append(f" Risk Score: {assessment.overall_score:.0f}/100")
|
|
190
175
|
lines.append(f" Viability: {assessment.viability}")
|
|
@@ -211,9 +196,7 @@ class ConsoleFormatter:
|
|
|
211
196
|
|
|
212
197
|
return "\n".join(lines)
|
|
213
198
|
|
|
214
|
-
def format_provider_comparison(
|
|
215
|
-
self, providers: List[ProviderInfo], asset: str, amount: Decimal
|
|
216
|
-
) -> str:
|
|
199
|
+
def format_provider_comparison(self, providers: List[ProviderInfo], asset: str, amount: Decimal) -> str:
|
|
217
200
|
"""Format provider comparison table."""
|
|
218
201
|
lines = []
|
|
219
202
|
|
|
@@ -221,10 +204,7 @@ class ConsoleFormatter:
|
|
|
221
204
|
lines.append(f"\n Comparing {amount} {asset} flash loan:\n")
|
|
222
205
|
|
|
223
206
|
# Table header
|
|
224
|
-
lines.append(
|
|
225
|
-
f" {'Provider':<14} {'Fee %':<8} {'Fee Amount':<14} "
|
|
226
|
-
f"{'Gas OH':<10} {'Chains':<20}"
|
|
227
|
-
)
|
|
207
|
+
lines.append(f" {'Provider':<14} {'Fee %':<8} {'Fee Amount':<14} {'Gas OH':<10} {'Chains':<20}")
|
|
228
208
|
lines.append(f" {'-' * 66}")
|
|
229
209
|
|
|
230
210
|
# Table rows
|
|
@@ -236,10 +216,7 @@ class ConsoleFormatter:
|
|
|
236
216
|
if len(info.supported_chains) > 2:
|
|
237
217
|
chains += "..."
|
|
238
218
|
|
|
239
|
-
lines.append(
|
|
240
|
-
f" {info.name:<14} {fee_pct:<8} {fee_amt:<14} "
|
|
241
|
-
f"{gas_oh:<10} {chains:<20}"
|
|
242
|
-
)
|
|
219
|
+
lines.append(f" {info.name:<14} {fee_pct:<8} {fee_amt:<14} {gas_oh:<10} {chains:<20}")
|
|
243
220
|
|
|
244
221
|
# Recommendation
|
|
245
222
|
if providers:
|
|
@@ -252,17 +229,14 @@ class ConsoleFormatter:
|
|
|
252
229
|
|
|
253
230
|
return "\n".join(lines)
|
|
254
231
|
|
|
255
|
-
def format_quick_summary(
|
|
256
|
-
self, result: StrategyResult, assessment: Optional[RiskAssessment] = None
|
|
257
|
-
) -> str:
|
|
232
|
+
def format_quick_summary(self, result: StrategyResult, assessment: Optional[RiskAssessment] = None) -> str:
|
|
258
233
|
"""Format a quick one-box summary."""
|
|
259
234
|
lines = []
|
|
260
235
|
|
|
261
236
|
# Profit line
|
|
262
237
|
profit_emoji = "✓" if result.is_profitable else "✗"
|
|
263
238
|
lines.append(
|
|
264
|
-
f"Net Profit: {result.net_profit:+.6f} {result.loan_asset} "
|
|
265
|
-
f"(${result.net_profit_usd:+.2f}) {profit_emoji}"
|
|
239
|
+
f"Net Profit: {result.net_profit:+.6f} {result.loan_asset} (${result.net_profit_usd:+.2f}) {profit_emoji}"
|
|
266
240
|
)
|
|
267
241
|
|
|
268
242
|
# Provider
|
|
@@ -270,15 +244,11 @@ class ConsoleFormatter:
|
|
|
270
244
|
|
|
271
245
|
# Risk if available
|
|
272
246
|
if assessment:
|
|
273
|
-
ind, lbl = self.RISK_INDICATORS.get(
|
|
274
|
-
assessment.overall_level, ("⚪", "?")
|
|
275
|
-
)
|
|
247
|
+
ind, lbl = self.RISK_INDICATORS.get(assessment.overall_level, ("⚪", "?"))
|
|
276
248
|
lines.append(f"Risk: {ind} {lbl} | Viability: {assessment.viability}")
|
|
277
249
|
|
|
278
250
|
# Verdict
|
|
279
|
-
if result.is_profitable and (
|
|
280
|
-
assessment is None or assessment.viability != "NO-GO"
|
|
281
|
-
):
|
|
251
|
+
if result.is_profitable and (assessment is None or assessment.viability != "NO-GO"):
|
|
282
252
|
lines.append("Verdict: PROCEED WITH CAUTION")
|
|
283
253
|
elif result.is_profitable:
|
|
284
254
|
lines.append("Verdict: HIGH RISK - RECONSIDER")
|
|
@@ -400,9 +370,7 @@ class MarkdownFormatter:
|
|
|
400
370
|
lines.append(f"- **Strategy**: {result.strategy_type.value}")
|
|
401
371
|
lines.append(f"- **Loan**: {result.loan_amount} {result.loan_asset}")
|
|
402
372
|
lines.append(f"- **Provider**: {result.provider}")
|
|
403
|
-
lines.append(
|
|
404
|
-
f"- **Profitable**: {'Yes ✓' if result.is_profitable else 'No ✗'}"
|
|
405
|
-
)
|
|
373
|
+
lines.append(f"- **Profitable**: {'Yes ✓' if result.is_profitable else 'No ✗'}")
|
|
406
374
|
lines.append("")
|
|
407
375
|
|
|
408
376
|
# Profit
|
|
@@ -461,7 +429,7 @@ class MarkdownFormatter:
|
|
|
461
429
|
|
|
462
430
|
def demo():
|
|
463
431
|
"""Demonstrate formatters."""
|
|
464
|
-
from strategy_engine import StrategyFactory,
|
|
432
|
+
from strategy_engine import StrategyFactory, ArbitrageParams
|
|
465
433
|
from profit_calculator import ProfitCalculator
|
|
466
434
|
from risk_assessor import RiskAssessor
|
|
467
435
|
from protocol_adapters import ProviderManager
|
|
@@ -11,7 +11,7 @@ Calculates net profit after all costs including:
|
|
|
11
11
|
|
|
12
12
|
from dataclasses import dataclass
|
|
13
13
|
from decimal import Decimal
|
|
14
|
-
from typing import List
|
|
14
|
+
from typing import List
|
|
15
15
|
|
|
16
16
|
from strategy_engine import StrategyResult, TransactionStep
|
|
17
17
|
|
|
@@ -120,9 +120,7 @@ class ProfitCalculator:
|
|
|
120
120
|
if total_gas_units > 0 and profit_before_gas > 0:
|
|
121
121
|
# profit_before_gas = gas_units * gas_price * eth_price
|
|
122
122
|
# gas_price = profit_before_gas / (gas_units * eth_price)
|
|
123
|
-
breakeven_gas = float(
|
|
124
|
-
profit_before_gas * Decimal("1e9") / (total_gas_units * self.eth_price_usd)
|
|
125
|
-
)
|
|
123
|
+
breakeven_gas = float(profit_before_gas * Decimal("1e9") / (total_gas_units * self.eth_price_usd))
|
|
126
124
|
else:
|
|
127
125
|
breakeven_gas = 0.0
|
|
128
126
|
|
|
@@ -223,15 +221,17 @@ class ProfitCalculator:
|
|
|
223
221
|
|
|
224
222
|
total_cost = fee + gas_cost
|
|
225
223
|
|
|
226
|
-
results.append(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
224
|
+
results.append(
|
|
225
|
+
{
|
|
226
|
+
"provider": name,
|
|
227
|
+
"fee_rate": float(fee_rate) * 100,
|
|
228
|
+
"fee_amount": float(fee),
|
|
229
|
+
"gas_overhead": overhead,
|
|
230
|
+
"gas_cost_eth": float(gas_cost),
|
|
231
|
+
"total_cost_eth": float(total_cost),
|
|
232
|
+
"total_cost_usd": float(total_cost * self.eth_price_usd),
|
|
233
|
+
}
|
|
234
|
+
)
|
|
235
235
|
|
|
236
236
|
# Sort by total cost
|
|
237
237
|
results.sort(key=lambda x: x["total_cost_eth"])
|
|
@@ -267,11 +267,11 @@ def demo():
|
|
|
267
267
|
print("=" * 60)
|
|
268
268
|
|
|
269
269
|
print(f"\nGross Revenue: {breakdown.gross_revenue:.6f} ETH")
|
|
270
|
-
print(
|
|
270
|
+
print("\nCosts:")
|
|
271
271
|
print(f" Flash Loan Fee: -{breakdown.flash_loan_fee:.6f} ETH")
|
|
272
272
|
print(f" Gas Cost: -{breakdown.gas_cost_eth:.6f} ETH (${breakdown.gas_cost_usd:.2f})")
|
|
273
273
|
print(f" Est. Slippage: -{breakdown.slippage_cost:.6f} ETH")
|
|
274
|
-
print(
|
|
274
|
+
print(" ────────────────────────────────")
|
|
275
275
|
print(f" Total Costs: -{breakdown.total_costs:.6f} ETH")
|
|
276
276
|
|
|
277
277
|
print(f"\nNet Profit: {breakdown.net_profit:.6f} ETH (${breakdown.net_profit_usd:.2f})")
|
|
@@ -297,7 +297,7 @@ def demo():
|
|
|
297
297
|
providers=providers,
|
|
298
298
|
)
|
|
299
299
|
|
|
300
|
-
print(
|
|
300
|
+
print("\nFor 100 ETH flash loan:")
|
|
301
301
|
print(f"{'Provider':<12} {'Fee %':<8} {'Fee ETH':<12} {'Gas ETH':<12} {'Total':<12}")
|
|
302
302
|
print("-" * 56)
|
|
303
303
|
|
|
@@ -11,8 +11,6 @@ from dataclasses import dataclass
|
|
|
11
11
|
from decimal import Decimal
|
|
12
12
|
from typing import Dict, List, Optional
|
|
13
13
|
|
|
14
|
-
import httpx
|
|
15
|
-
|
|
16
14
|
|
|
17
15
|
@dataclass
|
|
18
16
|
class LoanParams:
|
|
@@ -343,9 +341,7 @@ class ProviderManager:
|
|
|
343
341
|
"""List all available providers."""
|
|
344
342
|
return list(self.providers.keys())
|
|
345
343
|
|
|
346
|
-
def compare_providers(
|
|
347
|
-
self, asset: str, amount: Decimal, chain: str = "ethereum"
|
|
348
|
-
) -> List[ProviderInfo]:
|
|
344
|
+
def compare_providers(self, asset: str, amount: Decimal, chain: str = "ethereum") -> List[ProviderInfo]:
|
|
349
345
|
"""
|
|
350
346
|
Compare all providers for a specific loan.
|
|
351
347
|
|
|
@@ -368,9 +364,7 @@ class ProviderManager:
|
|
|
368
364
|
results.sort(key=lambda x: x.fee_amount)
|
|
369
365
|
return results
|
|
370
366
|
|
|
371
|
-
def find_cheapest(
|
|
372
|
-
self, asset: str, amount: Decimal, chain: str = "ethereum"
|
|
373
|
-
) -> Optional[ProviderInfo]:
|
|
367
|
+
def find_cheapest(self, asset: str, amount: Decimal, chain: str = "ethereum") -> Optional[ProviderInfo]:
|
|
374
368
|
"""Find the cheapest provider for a loan."""
|
|
375
369
|
providers = self.compare_providers(asset, amount, chain)
|
|
376
370
|
return providers[0] if providers else None
|
|
@@ -12,7 +12,7 @@ Evaluates risks for flash loan strategies:
|
|
|
12
12
|
from dataclasses import dataclass
|
|
13
13
|
from decimal import Decimal
|
|
14
14
|
from enum import Enum
|
|
15
|
-
from typing import List
|
|
15
|
+
from typing import List
|
|
16
16
|
|
|
17
17
|
from strategy_engine import StrategyResult, StrategyType
|
|
18
18
|
|
|
@@ -128,10 +128,7 @@ class RiskAssessor:
|
|
|
128
128
|
"Profit Margin": 0.15,
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
overall_score = sum(
|
|
132
|
-
f.score * weights.get(f.name, 0.2)
|
|
133
|
-
for f in factors
|
|
134
|
-
)
|
|
131
|
+
overall_score = sum(f.score * weights.get(f.name, 0.2) for f in factors)
|
|
135
132
|
|
|
136
133
|
# Determine overall level
|
|
137
134
|
if overall_score < 30:
|
|
@@ -169,10 +166,7 @@ class RiskAssessor:
|
|
|
169
166
|
# Higher score = more competition
|
|
170
167
|
pair_key = (result.loan_asset, "USDC") # Simplified
|
|
171
168
|
|
|
172
|
-
score = self.MEV_COMPETITION.get(
|
|
173
|
-
pair_key,
|
|
174
|
-
self.MEV_COMPETITION.get("default", 50)
|
|
175
|
-
)
|
|
169
|
+
score = self.MEV_COMPETITION.get(pair_key, self.MEV_COMPETITION.get("default", 50))
|
|
176
170
|
|
|
177
171
|
# Adjust for trade size (larger = more attractive to MEV)
|
|
178
172
|
if result.loan_amount > 100:
|
|
@@ -240,10 +234,7 @@ class RiskAssessor:
|
|
|
240
234
|
protocols.add(step.protocol.lower())
|
|
241
235
|
|
|
242
236
|
# Sum risk scores
|
|
243
|
-
total_risk = sum(
|
|
244
|
-
self.PROTOCOL_RISK.get(p, self.PROTOCOL_RISK["default"])
|
|
245
|
-
for p in protocols
|
|
246
|
-
)
|
|
237
|
+
total_risk = sum(self.PROTOCOL_RISK.get(p, self.PROTOCOL_RISK["default"]) for p in protocols)
|
|
247
238
|
|
|
248
239
|
# Average across protocols
|
|
249
240
|
score = total_risk / len(protocols) if protocols else 50
|
|
@@ -334,9 +325,7 @@ class RiskAssessor:
|
|
|
334
325
|
mitigation="Increase trade size or wait for better opportunity",
|
|
335
326
|
)
|
|
336
327
|
|
|
337
|
-
def _generate_recommendations(
|
|
338
|
-
self, factors: List[RiskFactor], result: StrategyResult
|
|
339
|
-
) -> List[str]:
|
|
328
|
+
def _generate_recommendations(self, factors: List[RiskFactor], result: StrategyResult) -> List[str]:
|
|
340
329
|
"""Generate actionable recommendations."""
|
|
341
330
|
recs = []
|
|
342
331
|
|
|
@@ -376,7 +365,7 @@ class RiskAssessor:
|
|
|
376
365
|
|
|
377
366
|
def demo():
|
|
378
367
|
"""Demonstrate risk assessment."""
|
|
379
|
-
from strategy_engine import StrategyFactory,
|
|
368
|
+
from strategy_engine import StrategyFactory, ArbitrageParams
|
|
380
369
|
|
|
381
370
|
# Run a simulation first
|
|
382
371
|
factory = StrategyFactory()
|
|
@@ -176,9 +176,7 @@ class SimpleArbitrageStrategy(FlashLoanStrategy):
|
|
|
176
176
|
def strategy_type(self) -> StrategyType:
|
|
177
177
|
return StrategyType.SIMPLE_ARBITRAGE
|
|
178
178
|
|
|
179
|
-
def get_dex_price(
|
|
180
|
-
self, dex: str, from_token: str, to_token: str
|
|
181
|
-
) -> Optional[Decimal]:
|
|
179
|
+
def get_dex_price(self, dex: str, from_token: str, to_token: str) -> Optional[Decimal]:
|
|
182
180
|
"""Get price from DEX (mock data)."""
|
|
183
181
|
dex_prices = self.MOCK_PRICES.get(dex.lower(), {})
|
|
184
182
|
return dex_prices.get((from_token.upper(), to_token.upper()))
|
|
@@ -219,9 +217,7 @@ class SimpleArbitrageStrategy(FlashLoanStrategy):
|
|
|
219
217
|
)
|
|
220
218
|
|
|
221
219
|
# Step 2: Sell on high-price DEX
|
|
222
|
-
sell_price = self.get_dex_price(
|
|
223
|
-
params.dex_sell, params.input_token, params.output_token
|
|
224
|
-
)
|
|
220
|
+
sell_price = self.get_dex_price(params.dex_sell, params.input_token, params.output_token)
|
|
225
221
|
if not sell_price:
|
|
226
222
|
warnings.append(f"No price data for {params.dex_sell}")
|
|
227
223
|
sell_price = Decimal("2540") # Fallback
|
|
@@ -245,9 +241,7 @@ class SimpleArbitrageStrategy(FlashLoanStrategy):
|
|
|
245
241
|
)
|
|
246
242
|
|
|
247
243
|
# Step 3: Buy on low-price DEX
|
|
248
|
-
buy_price = self.get_dex_price(
|
|
249
|
-
params.dex_buy, params.output_token, params.input_token
|
|
250
|
-
)
|
|
244
|
+
buy_price = self.get_dex_price(params.dex_buy, params.output_token, params.input_token)
|
|
251
245
|
if not buy_price:
|
|
252
246
|
warnings.append(f"No price data for {params.dex_buy}")
|
|
253
247
|
buy_price = Decimal("1") / Decimal("2538") # Fallback
|
|
@@ -389,11 +383,9 @@ class LiquidationStrategy(FlashLoanStrategy):
|
|
|
389
383
|
debt_amount = Decimal("10000") # 10K USDC debt
|
|
390
384
|
collateral_amount = Decimal("5") # 5 ETH collateral
|
|
391
385
|
collateral_price = Decimal("2500") # $2500/ETH
|
|
392
|
-
|
|
386
|
+
collateral_amount * collateral_price # $12,500
|
|
393
387
|
|
|
394
|
-
liquidation_bonus = self.LIQUIDATION_BONUSES.get(
|
|
395
|
-
params.protocol.lower(), Decimal("0.05")
|
|
396
|
-
)
|
|
388
|
+
liquidation_bonus = self.LIQUIDATION_BONUSES.get(params.protocol.lower(), Decimal("0.05"))
|
|
397
389
|
|
|
398
390
|
# Step 1: Flash borrow debt asset
|
|
399
391
|
loan_fee = provider.get_fee(params.debt_asset, debt_amount)
|
|
@@ -459,7 +451,7 @@ class LiquidationStrategy(FlashLoanStrategy):
|
|
|
459
451
|
output_amount=Decimal("0"),
|
|
460
452
|
fee=Decimal("0"),
|
|
461
453
|
gas_estimate=50000,
|
|
462
|
-
description=
|
|
454
|
+
description="Repay flash loan",
|
|
463
455
|
)
|
|
464
456
|
)
|
|
465
457
|
|