Naciśnij ESC, aby zamknąć

Pożyczki Krypto: Zysk czy Ryzyko Likwidacji? Analiza LTV

TL;DR: W artykule rozkładamy na czynniki pierwsze mechanizm pożyczek kryptowalutowych i likwidacji w protokołach Web3 (Aave v3, Morpho Blue). Analizujemy kluczowe metryki (Health Factor, LTV, Liquidation Threshold), scenariusze poślizgu cenowego (slippage) przy opóźnieniach wyroczni Chainlink oraz przedstawiamy skrypt w Pythonie do automatycznego wyłapywania i likwidacji zagrożonych pozycji.

Jak działają pożyczki w DeFi i skąd bierze się ryzyko likwidacji

Pożyczka w crypto to nie tradycyjny bank, gdzie pani w okienku analizuje Twoje zarobki i daje hipotekę pod zastaw mieszkania babci. W Web3 nikt nie pyta o Twoje nazwisko, historię w BIK-u czy życiowe plany. Liczy się tylko chłodna matematyka smart kontraktów: dajesz zastaw (collateral), bierzesz pożyczkę z nadwyżką zabezpieczenia (overcollateralized loan) i jeśli prześpisz spadek Health Factor — boty likwidacyjne zjedzą Twoje depozyty ze smakiem w ułamku milisekundy.

Weźmy klasyczny układ na Aave v3 albo Morpho Blue. Wrzucasz $10,000 w WBTC, żeby wyciągnąć $6,000 w USDC. Po co? Żeby nie sprzedawać bitcoina, nie wywoływać zdarzenia podatkowego i jednocześnie mieć gotówkę na wpakowanie się w kolejnego shitcoina albo zakup nowego sprzętu. Wygląda jak Święty Graal. Na papierze.

A potem wjeżdża standardowy zjazd rynku o 18% w 15 minut. Płynność z arkusza zleceń wyparowuje. Wyrocznia Chainlink aktualizuje cenę z opóźnieniem kilku bloków przez zapchany network, a Twoja pozycja leci prosto do likwidacyjnego piekła.

Anatomia likwidacji: dlaczego Twój zastaw znika w mgnieniu oka

Główna metryka, którą musisz monitorować 24/7, to Health Factor (HF). Wzór jest banalny:

HF = ∑ (Collaterali × LTVi) / Total Borrowed

Jeśli HF > 1, jesteś bezpieczny. Jeśli HF ≤ 1, Twoja pozycja staje się darmowym łupem dla każdego w sieci, kto ma odpalony odpowiedni skrypt.

ParametrWyjaśnienieRealny przykład (pula ETH)
Max LTVMaksymalny procent pożyczki w stosunku do wartości zastawu80% ($800 pożyczki na $1000 w ETH)
Liquidation Threshold (LT)Próg, po przekroczeniu którego pozycja kwalifikuje się do likwidacji82.5%
Liquidation BonusDyskonto na zastaw, które zgarnia likwidator5%
Reserve FactorDola protokołu z przychodów odsetkowych15%

Chociaż czekaj, sprostowanie. Na papierze próg 82.5% brzmi bezpiecznie, ale w praktyce musisz wziąć pod uwagę ukryty slippage i koszty gazu na mainnecie. Gdy wyrocznia typu push pcha odświeżoną cenę do kontraktu, boty MEV już ustawiają się w kolejce w paczce Flashbots. Przejmują Twoją pozycję z 5% dyskontem, błyskawicznie spłacają dług przez flash loan na Uniswap v3 i zgarniają czysty zysk na czysto.

Efekt? Zostajesz z USDC, które zapewne zdążyłeś już gdzieś przepalić, ale po Twoim WBTC nie ma ani śladu. Protokół pobrał karę, bot zgarnął spread. Jesteś na minusie.

Skrypt likwidatora: jak boty wyczuwają słabość Twojej pozycji

Pół roku temu sam widziałem, jak na Arbitrum jedna zbugowana wyrocznia posłała w kosmos depozyty warte 200k zielonych dosłownie w trzy bloki. Prosty skrypt do likwidacji można naskrobać na kolanie, ale o sukcesie decydują milisekundy i bezpośredni dostęp do przekaźników MEV.

Oto działający prototyp w Pythonie z użyciem web3.py, który śledzi pożyczkobiorcę w LendingPool i błyskawicznie przygotowuje transakcję, gdy HF spadnie poniżej jedynki.

import os
import time
from web3 import Web3
from web3.exceptions import ContractLogicError, TransactionNotFound

# ------------------------------------------------------------------------------
# 1. Konfiguracja i połączenie
# ------------------------------------------------------------------------------
RPC_URL = os.getenv("RPC_URL", "https://arb-mainnet.g.alchemy.com/v2/YOUR_API_KEY")
PRIVATE_KEY = os.getenv("PRIVATE_KEY", "0x_YOUR_PRIVATE_KEY")

w3 = Web3(Web3.HTTPProvider(RPC_URL))
if not w3.is_connected():
    raise RuntimeError("Brak połączenia z RPC. Sprawdź swój RPC_URL.")

ACCOUNT = w3.eth.account.from_key(PRIVATE_KEY)

# Kontrakty Aave v3 na Arbitrum
POOL_ADDRESS = Web3.to_checksum_address("0x794a61358D6845594F94dc1DB02A252b5b4814aD")
DATA_PROVIDER_ADDRESS = Web3.to_checksum_address("0x69FA0fee221AD11012B2f52097e8F6B7EAcF57E7")

TARGET_USER = Web3.to_checksum_address("0x0000000000000000000000000000000000000000")

COLLATERAL_ASSET = Web3.to_checksum_address("0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f")  # WBTC
DEBT_ASSET = Web3.to_checksum_address("0xaf88d065e77c8cC2239327C5EDb3A432268e5831")        # USDC

# ------------------------------------------------------------------------------
# 2. ABI
# ------------------------------------------------------------------------------
POOL_ABI = [
    {
        "inputs": [{"internalType": "address", "name": "user", "type": "address"}],
        "name": "getUserAccountData",
        "outputs": [
            {"internalType": "uint256", "name": "totalCollateralBase", "type": "uint256"},
            {"internalType": "uint256", "name": "totalDebtBase", "type": "uint256"},
            {"internalType": "uint256", "name": "availableBorrowsBase", "type": "uint256"},
            {"internalType": "uint256", "name": "currentLiquidationThreshold", "type": "uint256"},
            {"internalType": "uint256", "name": "ltv", "type": "uint256"},
            {"internalType": "uint256", "name": "healthFactor", "type": "uint256"}
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {"internalType": "address", "name": "collateralAsset", "type": "address"},
            {"internalType": "address", "name": "debtAsset", "type": "address"},
            {"internalType": "address", "name": "user", "type": "address"},
            {"internalType": "uint256", "name": "debtToCover", "type": "uint256"},
            {"internalType": "bool", "name": "receiveAToken", "type": "bool"}
        ],
        "name": "liquidationCall",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
]

DATA_PROVIDER_ABI = [
    {
        "inputs": [
            {"internalType": "address", "name": "asset", "type": "address"},
            {"internalType": "address", "name": "user", "type": "address"}
        ],
        "name": "getUserReserveData",
        "outputs": [
            {"internalType": "uint256", "name": "currentATokenBalance", "type": "uint256"},
            {"internalType": "uint256", "name": "currentStableDebt", "type": "uint256"},
            {"internalType": "uint256", "name": "currentVariableDebt", "type": "uint256"},
            {"internalType": "uint256", "name": "principalStableDebt", "type": "uint256"},
            {"internalType": "uint256", "name": "scaledVariableDebt", "type": "uint256"},
            {"internalType": "uint256", "name": "stableBorrowRate", "type": "uint256"},
            {"internalType": "uint256", "name": "liquidityRate", "type": "uint256"},
            {"internalType": "uint40", "name": "stableRateLastUpdated", "type": "uint40"},
            {"internalType": "bool", "name": "usageAsCollateralEnabled", "type": "bool"}
        ],
        "stateMutability": "view",
        "type": "function"
    }
]

ERC20_ABI = [
    {
        "inputs": [
            {"internalType": "address", "name": "owner", "type": "address"},
            {"internalType": "address", "name": "spender", "type": "address"}
        ],
        "name": "allowance",
        "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {"internalType": "address", "name": "spender", "type": "address"},
            {"internalType": "uint256", "name": "amount", "type": "uint256"}
        ],
        "name": "approve",
        "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], # FIX: Poprawiony typ zwrotny na bool
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [{"internalType": "address", "name": "account", "type": "address"}],
        "name": "balanceOf",
        "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
        "stateMutability": "view",
        "type": "function"
    }
]

pool = w3.eth.contract(address=POOL_ADDRESS, abi=POOL_ABI)
data_provider = w3.eth.contract(address=DATA_PROVIDER_ADDRESS, abi=DATA_PROVIDER_ABI)
debt_token = w3.eth.contract(address=DEBT_ASSET, abi=ERC20_ABI)

tx_in_flight = False

# ------------------------------------------------------------------------------
# 3. Bezpieczne helpery dla gazu i nonce
# ------------------------------------------------------------------------------
def get_fee_parameters():
    """Pobiera parametry opłat EIP-1559 z fallbackiem dla sieci bez baseFeePerGas."""
    latest_block = w3.eth.get_block('latest')
    base_fee = latest_block.get('baseFeePerGas')
    
    if base_fee is not None:
        max_priority_fee = w3.to_wei(0.1, 'gwei')
        max_fee = base_fee * 2 + max_priority_fee
        return {
            'maxFeePerGas': max_fee,
            'maxPriorityFeePerGas': max_priority_fee
        }
    else:
        # Fallback dla sieci typu Legacy / niestandardowych L2
        return {'gasPrice': w3.eth.gas_price}

def ensure_allowance(required_amount: int) -> bool:
    """Sprawdza i ustawia approve z obowiązkową weryfikacją statusu receipta."""
    current_allowance = debt_token.functions.allowance(ACCOUNT.address, POOL_ADDRESS).call()
    if current_allowance >= required_amount:
        return True

    print("[*] Za mały allowance. Leci transakcja approve...")
    nonce = w3.eth.get_transaction_count(ACCOUNT.address, 'pending')
    
    tx_params = {
        'chainId': w3.eth.chain_id,
        'from': ACCOUNT.address,
        'nonce': nonce,
        **get_fee_parameters()
    }
    
    tx = debt_token.functions.approve(POOL_ADDRESS, 2**256 - 1).build_transaction(tx_params)
    signed_tx = w3.eth.account.sign_transaction(tx, PRIVATE_KEY)
    tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
    
    receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=30)
    if receipt['status'] == 1:
        print(f"[+] Approve pomyślnie wbity w bloku {receipt['blockNumber']}")
        return True
    else:
        print(f"[!] BŁĄD: Transakcja approve poleciała z revertem!")
        return False

# ------------------------------------------------------------------------------
# 4. Główna logika egzekucji likwidacji
# ------------------------------------------------------------------------------
def execute_liquidation(user_address: str):
    global tx_in_flight
    if tx_in_flight:
        print("[!] Wątek zablokowany (transakcja jest już w locie).")
        return

    # FIX #9: Szybki sanity check HF przed odpaleniem kosztownego setupu
    account_data = pool.functions.getUserAccountData(user_address).call()
    health_factor = account_data[5] / 10**18
    if health_factor >= 1.0:
        print(f"[-] Anulowano: HF pozycji podskoczył do {health_factor:.6f} (>= 1.0)")
        return

    # FIX #11: Wyliczenie dokładnego długu w jednostkach tokena USDC
    reserve_data = data_provider.functions.getUserReserveData(DEBT_ASSET, user_address).call()
    actual_debt_tokens = reserve_data[1] + reserve_data[2]  # stable + variable
    
    if actual_debt_tokens == 0:
        print("[!] Brak aktywnego długu dla wybranego tokena.")
        return

    debt_to_cover = actual_debt_tokens // 2

    # Sprawdzenie lokalnego salda USDC w portfelu
    our_balance = debt_token.functions.balanceOf(ACCOUNT.address).call()
    if our_balance < debt_to_cover:
        print(f"[!] Za mało USDC na portfelu. Wymagane: {debt_to_cover}, Dostępne: {our_balance}")
        debt_to_cover = our_balance
        if debt_to_cover == 0:
            return

    # FIX #8: Weryfikacja, czy approve przeszedł pomyślnie
    if not ensure_allowance(debt_to_cover):
        return

    # Używamy nonce 'pending', aby uniknąć kolizji wewnątrz konta
    nonce = w3.eth.get_transaction_count(ACCOUNT.address, 'pending')
    tx_params = {
        'chainId': w3.eth.chain_id,
        'from': ACCOUNT.address,
        'nonce': nonce,
        **get_fee_parameters()
    }

    # FIX #5: Symulacja transakcji bezpośrednio przed jej złożeniem
    try:
        estimated_gas = pool.functions.liquidationCall(
            COLLATERAL_ASSET,
            DEBT_ASSET,
            user_address,
            debt_to_cover,
            False
        ).estimate_gas(tx_params)
        
        tx_params['gas'] = int(estimated_gas * 1.2)
    except ContractLogicError as e:
        print(f"[!] Kontrakt wypluł revert podczas symulacji liquidationCall: {e}")
        return
    except Exception as e:
        print(f"[!] Błąd przy szacowaniu limitu gazu: {e}")
        return

    # Składanie i rozgłaszanie transakcji
    try:
        tx_in_flight = True
        tx_data = pool.functions.liquidationCall(
            COLLATERAL_ASSET,
            DEBT_ASSET,
            user_address,
            debt_to_cover,
            False
        ).build_transaction(tx_params)

        signed_tx = w3.eth.account.sign_transaction(tx_data, PRIVATE_KEY)
        tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction)
        print(f"[+] Transakcja wysłana w sieć! Tx Hash: {tx_hash.hex()}")
        
        # FIX #10: Sprawdzenie statusu w receipt po likwidacji
        receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=30)
        if receipt['status'] == 1:
            print(f"[SUKCES] Pozycja zlikwidowana w bloku {receipt['blockNumber']}!")
        else:
            print(f"[FAIL] Transakcja weszła do bloku, ale wywaliła REVERT (Status 0). Gaz poszedł w błoto.")

    except Exception as e:
        print(f"[!] Krytyczny błąd podczas nadawania transakcji: {e}")
    finally:
        tx_in_flight = False

# ------------------------------------------------------------------------------
# 5. Pętla monitorująca
# ------------------------------------------------------------------------------
def monitor_user(user_address: str):
    account_data = pool.functions.getUserAccountData(user_address).call()
    health_factor = account_data[5] / 10**18
    
    print(f"Target: {user_address} | Health Factor: {health_factor:.6f}")

    if health_factor < 1.0:
        print("[!] NAMIERZONO POZYCJĘ DO LIKWIDACJI!")
        execute_liquidation(user_address)

if __name__ == "__main__":
    while True:
        try:
            monitor_user(TARGET_USER)
            time.sleep(1)
        except KeyboardInterrupt:
            print("\nPrzerwano działanie bota na żądanie użytkownika.")
            break
        except Exception as e:
            print(f"ERROR: {e}")
            time.sleep(3)

Na L2 nie ma czegoś takiego jak mempool. W ogóle. Wszystko śmiga w trybie FCFS (kto pierwszy, ten lepszy). Kto pierwszy wstanie, ten zgarnia pulę.

I podczas gdy Twój skrypt zamula na time.sleep(1), wyspecjalizowane boty HFT siedzą na socketach w tym samym serwerze, gdzie kręci się walidator. Szanse na ręczne wyprzedzenie margin calla masz ZEROWE.

Gdzie tak naprawdę leży zysk (i dlaczego wszyscy dalej biorą pożyczki)

Po co w ogóle pakować się w takie ryzyko?

  • Arbitraż stóp procentowych (Interest Rate Arbitrage). Bierzesz USDT na 4% APY na platformie A i wrzucasz do Vaulta na 12% APY na platformie B. Różnica 8% ląduje w Twojej kieszeni. Ale tu kryje się ryzyko smart kontraktu: jeśli platforma B zaliczy depeg albo zostanie zhakowana przez reentrancy, zostajesz z realnym długiem wobec platformy A.
  • Delegowanie płynności i tokenizacja zastawu. Spójrz chociażby na Pendle czy Morpho. Deponujesz stETH, dostajesz stablecoiny, kupujesz za nie tokeny PT (Principal Tokens) ze stałym oprocentowaniem. Skomplikowane? Tak. Zyskowne? Jak najbardziej — do pierwszych problemów z wyrocznią tokenów LST.
  • Optymalizacja podatkowa. Realizacja zysków = konieczność zapłaty podatku. Pożyczka pod zastaw zyskującego aktywa = brak faktu sprzedaży. Nie ma sprzedaży — nie ma podatku. Pragmatyczne? Jak najbardziej.

Ludzie zapominają jednak o kaskadowych likwidacjach. W maju 2021 roku oraz podczas upadku FTX całe protokoły stawały się niewypłacalne (bad debt), bo cena zastawu leciała na łeb na szyję szybciej, niż boty nadążały z zamykaniem długów. W efekcie oberwali zwykli dostawcy płynności, którzy po prostu wrzucili swoje stablecoiny na procent.

Izolowane pule depozytowe vs Cross-Margin: gdzie tkwi pułapka

Mnóstwo świeżaków wcina się na minę po prostu dlatego, że nie ogarniają architektury zarządzania ryzykiem. W DeFi mamy dwa fundamentalnie różne podejścia: Cross-Margin (jeden wspólny kocioł) oraz Izolowane Rynki (sektorowe rynki w stylu Morpho czy Euler v2).

W Cross-Margin (domyślny tryb na Aave) cały Twój portfel zabezpieczenia działa jak jedna wspólna tarcza. Wrzucasz WBTC, ETH i DAI — po czym pożyczasz USDC. Jeśli spadnie tylko cena WBTC, poduszką bezpieczeństwa staje się DAI. Wygodne? Jak najbardziej. Ale jeśli jeden z Twoich aktywów zabezpieczających leci prosto w przepaść (pamiętamy depeg stETH z 2022 roku czy jakikolwiek przekręt na zmostkowanym tokenie), ciągnie za sobą CAŁĄ pozycję. Czyszczą Cię do zera.

W izolowanych pulach ograniczasz ryzyko tylko do jednej konkretnej pary — na przykład dedykowanego vaulta wstETH / USDC.

[Twój depozyt] ---> [Izolowana pula A (ETH/USDC)]  ---> Ryzyko ograniczone do puli A
                ---> [Izolowana pula B (PEPE/USDC)] ---> Scam na PEPE = strata tylko w puli B

Jeśli jakiś gównotoken w puli B zaliczy glebę o 99% — tracisz wyłącznie to, co wpłaciłeś do puli B. Twój główny Ether leżący w puli A jest w stu procentach bezpieczny.

Jasne, ogarnianie trzech osobnych pozycji to drętwota i płacisz więcej za gas. Ale przy pracy z dużą zmiennością to jedyna rozsądna strategia.

Wyrocznie: jak tracisz kasę bez żadnego exploita na smart kontrakcie

Smart kontrakt protokołu pożyczkowego sam z siebie jest ślepy i głuchy. Nie ma pojęcia, ile w tej sekundzie kosztuje ETH — po prostu ślepo wierzy wyroczni (oraclowi). I tu zaczyna się cała jazda.

Oto główne grzechy wyroczni, na których ludzie palą swoje depozyty:

  • Stale Prices (Nieświeże ceny). Wyrocznia nie pcha ceny na blockchain w każdej sekundzie (bo opłaty za gas wykończyłyby każdego dostawcę), tylko przy odchyleniu, powiedzmy, o 0.5% albo raz na 24 godziny (tzw. heartbeat). Jeśli rynek zaliczy impulsywny zjazd w dół o 5% w 3 sekundy i od razu odbije, wyrocznia może zaktualizować cenę DOKŁADNIE NA SAMYM DNIE. Kontrakt widzi HF na poziomie 0.99, daje zielone światło likwidatorom i pozycja idzie do piachu. Rynek odskakuje w górę, a Ty zostajesz z ręką w nocniku.
  • Illiquid DEX Feeds (Manipulacja na rynku spot). Jeśli protokół korzysta z wyroczni TWAP z Uniswap v3 dla mało płynnego tokena, wieloryb jednym potężnym strzałem sprzedażowym zepchnie cenę w podłogę, wywoła kaskadę likwidacji w protokole pożyczkowym, a potem odkupi aktywo za bezcen. Klasyka gatunku.

Poniższa tabela pokazuje realną matematykę strat przy likwidacji na różnych poziomach spadku zabezpieczenia (przy początkowym LTV 75% i Liquidation Bonus 5%):

Spadek ceny zabezpieczeniaHealth FactorStan pozycjiStraty pożyczkobiorcy z początkowego depozytu
-5%1.26Bezpiecznie0% (tylko niezrealizowana strata na wartości zabezpieczenia)
-15%1.13Strefa ryzyka0% (wymagane dorzucenie zabezpieczenia)
-25%0.99LIKWIDACJA~15-20% (kara dla likwidatora + spread)
-40% (Flash Crash)< 0.80Czysty zaor100% utraconego zabezpieczenia (zostajesz tylko z pożyczką)

Checklist przetrwania: jak brać pożyczki i nie dać się zaorać

Jeśli pakujesz się w zdecentralizowane pożyczki, trzymaj się twardych zasad higieny. Sam przetestowałem je na własnej skórze po kilku bolesnych revertach i przymusowych likwidacjach.

  • Trzymaj HF nie niżej niż 1.5 - 1.8. Zapomnij o igraniu z ogniem przy HF 1.05. Byle cień szpilki na wykresie i jesteś trup.
  • Zautomatyzuj dopłacanie (Self-Kicker). Używaj narzędzi typu Gelato Automation albo Chainlink Automation. Napisz prostego bota, który przy spadku HF poniżej 1.2 automatycznie przerzuci stablecoiny z Twojego portfela do kontraktu, żeby spłacić część długu.
  • Monitoruj wyrocznie. Bądź świadomy, jaka wyrocznia obsługuje Twój basen. Jeśli to Chainlink typu push — kontroluj heartbeat. Jeśli Pyth — sprawdzaj przedziały ufności (confidence intervals).
  • Hedge'uj pozycję przez perpy. Wziąłeś pożyczkę pod ETH? Otwórz shorta na ETH na derywatach z dźwignią 1x na wartość pożyczki. Zamykasz ryzyko w wartości dolarowej i masz pozycję delta-neutral.

Kredyt w crypto to potężna dźwignia finansowa, ale w rękach kogoś nieogarniętego zamienia się w gilotynę z tykającym zegarem. Kontrakt ma głęboko w nosie Twoje przemyślenia co do kierunku rynku.

Podsumuj ten wpis na blogu za pomocą:

FAQ

Likwidacja w Aave v3 następuje automatycznie, gdy wskaźnik Health Factor pozycji pożyczkowej spada poniżej wartości 1,0 w wyniku spadku wyceny zastawu lub wzrostu wartości zaciągniętego długu. Zewnętrzne boty likwidacyjne wywołują funkcję liquidationCall na kontrakcie Pool, spłacając do 50% zadłużenia użytkownika w zamian za przejęcie ekwiwalentu jego kolaterału powiększonego o premię likwidacyjną wynoszącą od 1% do 15%.

Wskaźnik Health Factor oblicza się dzieląc całkowitą wartość zdeponowanego zabezpieczenia pomnożoną przez zagregowany próg likwidacji (Liquidation Threshold) przez sumę zaciągniętego długu wyrażoną w ETH. Aby zapobiec likwidacji, inwestor musi utrzymać wskaźnik powyżej 1,0 poprzez spłatę części długu za pomocą metody repay, deponowanie dodatkowych aktywów akceptowalnych jako zabezpieczenie lub włączenie trybu High Efficiency Mode (eMode) dla powiązanych cenowo aktywów.

Opłacalność likwidacji zależy od różnicy między uzyskaną premią za przejęcie zabezpieczenia (Liquidation Bonus) a skumulowanym kosztem gazu w modelu EIP-1559 oraz poślizgiem cenowym (slippage) na giełdach DEX. Przed wysłaniem transakcji boty wykonują statyczną symulację wywołania poprzez estimateGas w celu weryfikacji dochodowości, równoważąc parametry maxFeePerGas i maxPriorityFeePerGas z wielkością zlikwidowanego długu.
Piter Wacker

I am a trading specialist with expertise in market analysis, risk management, and investment strategies. I focus on identifying opportunities, executing trades with discipline, and delivering consistent results.

...

Dodaj opinię

Twój adres e-mail nie zostanie opublikowany. Obowiązkowe pola są oznaczone*