예제 #1
0
def test_liquidations_debt_changes(
    snx,
    chain,
    gov,
    vault,
    strategy,
    susd,
    susd_vault,
    susd_whale,
    snx_whale,
    bob,
    snx_oracle,
):
    chain.snapshot()
    # Move stale period to 16 days
    resolver = Contract(strategy.resolver())
    settings = Contract(
        resolver.getAddress(encode_single("bytes32", b"SystemSettings")))
    settings.setRateStalePeriod(24 * 3600 * 16, {"from": settings.owner()})
    settings.setDebtSnapshotStaleTime(24 * 3600 * 16,
                                      {"from": settings.owner()})

    snx.transfer(bob, Wei("1000 ether"), {"from": snx_whale})
    snx.approve(vault, 2**256 - 1, {"from": bob})
    # bob deposits back and the debt pool skyrockets
    vault.deposit({"from": bob})

    # Invest with an SNX price of 20
    snx_oracle.updateSnxPrice(Wei("20 ether"), {"from": gov})
    strategy.harvest({"from": gov})

    chain.sleep(86400 + 1)  # just over 24h
    chain.mine()

    assert strategy.balanceOfWant() == Wei("1000 ether")
    assert strategy.balanceOfSusd() == 0
    assert strategy.balanceOfSusdInVault() == Wei("4000 ether")
    # debt pool value increases (main assets are ETH and WBTC so increasing its price increases debt pool value)
    debtCache = Contract(
        resolver.getAddress(encode_single("bytes32", b"DebtCache")))

    # done to cache from infura
    try:
        print("Taking Debt Snapshot, this will take a while...")
        debtCache.takeDebtSnapshot({"from": debtCache.owner()})
    except:
        print(
            "Failed. This is expected due to timeout but it is useful to cache, next call will go through"
        )

    # debt pool goes up to the sky
    previous_debt = strategy.balanceOfDebt()

    snx_oracle.updateBTCPrice(Wei("250000 ether"), {"from": gov})
    snx_oracle.updateETHPrice(Wei("10000 ether"), {"from": gov})
    debtCache.takeDebtSnapshot({"from": debtCache.owner()})
    print("debt", strategy.balanceOfDebt())
    # check that our debt has increased when debt pool value has increased
    assert strategy.balanceOfDebt() > previous_debt
    # the strategy can now be liquidated
    synthetix = Contract(
        resolver.getAddress(encode_single("bytes32", b"Synthetix")))
    liquidations = Contract(
        resolver.getAddress(encode_single("bytes32", b"Liquidations")))
    # flag account for liquidation, then wait three days to allow the account to repay
    liquidations.flagAccountForLiquidation(strategy, {"from": snx_whale})
    chain.sleep(3600 * 24 * 3 + 1)  # a bit over 3 days (see Synthetix docs)
    chain.mine()

    # repay debt
    amount_needed = liquidations.calculateAmountToFixCollateral(
        strategy.balanceOfDebt(),
        strategy.balanceOfWant() * 20)
    previous_whale_balance = snx.balanceOf(susd_whale)
    synthetix.liquidateDelinquentAccount(strategy, amount_needed,
                                         {"from": susd_whale})

    assert strategy.getCurrentRatio() == strategy.getIssuanceRatio()

    vault.withdraw(vault.balanceOf(bob), bob, 10_000, {"from": bob})

    assert snx.balanceOf(bob) < Wei("1000 ether")
    assert previous_whale_balance < snx.balanceOf(
        susd_whale
    )  # the whale receives SNX (debt paid + 10%) as reward for liquidating
    assert (amount_needed * 11 / 200 * 0.999 < Wei("1000 ether") -
            snx.balanceOf(bob) < amount_needed * 11 / 200 * 1.001
            )  # the losses where correctly calculated

    chain.revert()
예제 #2
0
def test_liquidations_snx_price_change(
    snx,
    chain,
    gov,
    vault,
    strategy,
    susd,
    susd_vault,
    susd_whale,
    snx_whale,
    bob,
    snx_oracle,
):
    chain.snapshot()
    # Move stale period to 6 days
    resolver = Contract(strategy.resolver())
    settings = Contract(
        resolver.getAddress(encode_single("bytes32", b"SystemSettings")))
    settings.setRateStalePeriod(24 * 3600 * 16, {"from": settings.owner()})
    settings.setDebtSnapshotStaleTime(24 * 3600 * 16,
                                      {"from": settings.owner()})

    snx.transfer(bob, Wei("1000 ether"), {"from": snx_whale})
    snx.approve(vault, 2**256 - 1, {"from": bob})
    # bob deposits and the price collapses
    vault.deposit({"from": bob})

    # Invest with an SNX price of 20
    snx_oracle.updateSnxPrice(Wei("20 ether"), {"from": gov})
    strategy.harvest({"from": gov})

    chain.sleep(86400 + 1)  # just over 24h
    chain.mine()

    assert strategy.balanceOfWant() == Wei("1000 ether")
    assert strategy.balanceOfSusd() == 0
    assert strategy.balanceOfSusdInVault() == Wei("4000 ether")

    # price collapses
    snx_oracle.updateSnxPrice(Wei("7 ether"), {"from": gov})

    # the strategy can now be liquidated
    synthetix = Contract(
        resolver.getAddress(encode_single("bytes32", b"Synthetix")))
    liquidations = Contract(
        resolver.getAddress(encode_single("bytes32", b"Liquidations")))
    # flag account for liquidation, then wait three days to allow the account to repay
    liquidations.flagAccountForLiquidation(strategy, {"from": snx_whale})
    chain.sleep(3600 * 24 * 3 + 1)  # a bit over 3 days (see Synthetix docs)
    chain.mine()

    # repay debt
    amount_needed = liquidations.calculateAmountToFixCollateral(
        strategy.balanceOfDebt(),
        strategy.balanceOfWant() * 7)
    previous_whale_balance = snx.balanceOf(susd_whale)
    synthetix.liquidateDelinquentAccount(strategy, amount_needed,
                                         {"from": susd_whale})

    assert strategy.getCurrentRatio() == strategy.getIssuanceRatio()

    vault.withdraw(vault.balanceOf(bob), bob, 10_000, {"from": bob})

    assert snx.balanceOf(bob) < Wei("1000 ether")
    assert previous_whale_balance < snx.balanceOf(
        susd_whale
    )  # the whale receives SNX (debt paid + 10%) as reward for liquidating
    assert (amount_needed * 11 / 70 * 0.999 < Wei("1000 ether") -
            snx.balanceOf(bob) < amount_needed * 11 / 70 * 1.001
            )  # the losses where correctly calculated
    chain.revert()