Beispiel #1
0
    def test_bite_and_flip(self, web3, mcd, gal_address, keeper_address):
        # given
        c = mcd.collaterals['ETH-A']
        keeper = AuctionKeeper(args=args(f"--eth-from {keeper_address} "
                                         f"--type flip "
                                         f"--from-block 1 "
                                         f"--ilk {c.ilk.name} "
                                         f"--model ./bogus-model.sh"),
                               web3=mcd.web3)
        keeper.approve()
        unsafe_cdp = create_unsafe_cdp(mcd, c, Wad.from_number(1.2),
                                       gal_address)
        assert len(mcd.active_auctions()["flips"][c.ilk.name]) == 0
        # Keeper won't bid with a 0 Dai balance
        purchase_dai(Wad(20), keeper_address)
        assert mcd.dai_adapter.join(
            keeper_address, Wad(20)).transact(from_address=keeper_address)

        # when
        keeper.check_cdps()
        wait_for_other_threads()

        # then
        print(mcd.cat.past_bites(10))
        assert len(mcd.cat.past_bites(10)) > 0
        urn = mcd.vat.urn(unsafe_cdp.ilk, unsafe_cdp.address)
        assert urn.art == Wad(0)  # unsafe cdp has been bitten
        assert urn.ink == Wad(0)  # unsafe cdp is now safe ...
        assert c.flipper.kicks() == 1  # One auction started
Beispiel #2
0
    def test_bark_and_clip(self, mcd, gal_address):
        # setup
        repay_urn(mcd, self.collateral, gal_address)

        # given 21 Dai / (200 price * 2.0 mat) == 0.21 vault size
        unsafe_cdp = create_unsafe_cdp(mcd, self.collateral, Wad.from_number(0.21), gal_address, draw_dai=False)
        assert self.clipper.active_count() == 0
        kicks_before = self.clipper.kicks()

        # when
        self.keeper.check_vaults()
        wait_for_other_threads()

        # then
        print(mcd.dog.past_barks(10))
        assert len(mcd.dog.past_barks(10)) > 0
        urn = mcd.vat.urn(unsafe_cdp.ilk, unsafe_cdp.address)
        assert urn.art == Wad(0)  # unsafe vault has been barked
        assert urn.ink == Wad(0)  # unsafe vault is now safe ...
        assert self.clipper.kicks() == kicks_before + 1  # One auction started

        # cleanup
        kick = self.collateral.clipper.kicks()
        (needs_redo, auction_price, lot, tab) = self.clipper.status(kick)
        bid_price = Ray(get_collateral_price(self.collateral))
        self.take_below_price(kick, bid_price, self.keeper_address)
Beispiel #3
0
    def test_should_detect_flop(self, web3, c, mcd, other_address, keeper_address):
        # given a count of flop auctions
        reserve_dai(mcd, c, keeper_address, Wad.from_number(230))
        kicks = mcd.flopper.kicks()

        # and an undercollateralized CDP is bitten
        unsafe_cdp = create_unsafe_cdp(mcd, c, Wad.from_number(1), other_address, draw_dai=False)
        assert mcd.cat.bite(unsafe_cdp.ilk, unsafe_cdp).transact()

        # when the auction ends without debt being covered
        time_travel_by(web3, c.flipper.tau() + 1)

        # then ensure testchain is in the appropriate state
        joy = mcd.vat.dai(mcd.vow.address)
        awe = mcd.vat.sin(mcd.vow.address)
        woe = (mcd.vat.sin(mcd.vow.address) - mcd.vow.sin()) - mcd.vow.ash()
        sin = mcd.vow.sin()
        sump = mcd.vow.sump()
        wait = mcd.vow.wait()
        assert joy < awe
        assert woe + sin >= sump
        assert wait == 0

        # when
        self.keeper.check_flop()
        wait_for_other_threads()

        # then ensure another flop auction was kicked off
        assert mcd.flopper.kicks() == kicks + 1

        # clean up by letting the auction expire
        time_travel_by(web3, mcd.flopper.tau() + 1)
Beispiel #4
0
def kick(web3: Web3, mcd: DssDeployment, gal_address, other_address) -> int:
    joy = mcd.vat.dai(mcd.vow.address)
    woe = (mcd.vat.sin(mcd.vow.address) - mcd.vow.sin()) - mcd.vow.ash()
    print(f'joy={str(joy)[:6]}, woe={str(woe)[:6]}')

    if woe < joy:
        # Bite gal CDP
        c = mcd.collaterals['ETH-B']
        unsafe_cdp = create_unsafe_cdp(mcd, c, Wad.from_number(2), other_address, draw_dai=False)
        flip_kick = bite(mcd, c, unsafe_cdp)

        # Generate some Dai, bid on and win the flip auction without covering all the debt
        reserve_dai(mcd, c, gal_address, Wad.from_number(100), extra_collateral=Wad.from_number(1.1))
        c.flipper.approve(mcd.vat.address, approval_function=hope_directly(from_address=gal_address))
        current_bid = c.flipper.bids(flip_kick)
        bid = Rad.from_number(1.9)
        assert mcd.vat.dai(gal_address) > bid
        assert c.flipper.tend(flip_kick, current_bid.lot, bid).transact(from_address=gal_address)
        time_travel_by(web3, c.flipper.ttl()+1)
        assert c.flipper.deal(flip_kick).transact()

    flog_and_heal(web3, mcd, past_blocks=1200, kiss=False)

    # Kick off the flop auction
    woe = (mcd.vat.sin(mcd.vow.address) - mcd.vow.sin()) - mcd.vow.ash()
    assert mcd.vow.sump() <= woe
    assert mcd.vat.dai(mcd.vow.address) == Rad(0)
    assert mcd.vow.flop().transact(from_address=gal_address)
    return mcd.flopper.kicks()
Beispiel #5
0
def kick(mcd, c: Collateral, gal_address) -> int:
    # Ensure we start with a clean urn
    urn = mcd.vat.urn(c.ilk, gal_address)
    assert urn.ink == Wad(0)
    assert urn.art == Wad(0)

    # Bite gal CDP
    unsafe_cdp = create_unsafe_cdp(mcd, c, tend_lot, gal_address)
    return bite(mcd, c, unsafe_cdp)
Beispiel #6
0
def kick(mcd, collateral_clip: Collateral, gal_address) -> int:
    # Ensure we start with a clean urn
    urn = mcd.vat.urn(collateral_clip.ilk, gal_address)
    assert urn.ink == Wad(0)
    assert urn.art == Wad(0)

    # Bark an unsafe vault and return the id
    unsafe_cdp = create_unsafe_cdp(mcd, collateral_clip, Wad.from_number(1.0), gal_address)
    mcd.dog.bark(collateral_clip.ilk, unsafe_cdp).transact()
    barks = mcd.dog.past_barks(1)
    assert len(barks) == 1
    return collateral_clip.clipper.kicks()
Beispiel #7
0
    def test_bite_and_flip(self, mcd, gal_address):
        # given 21 Dai / (200 price * 1.2 mat) == 0.0875 vault size
        unsafe_cdp = create_unsafe_cdp(mcd, self.c, Wad.from_number(0.0875), gal_address, draw_dai=False)
        assert len(mcd.active_auctions()["flips"][self.c.ilk.name]) == 0

        # when
        self.keeper.check_vaults()
        wait_for_other_threads()

        # then
        print(mcd.cat.past_bites(10))
        assert len(mcd.cat.past_bites(10)) > 0
        urn = mcd.vat.urn(unsafe_cdp.ilk, unsafe_cdp.address)
        assert urn.art == Wad(0)  # unsafe cdp has been bitten
        assert urn.ink == Wad(0)  # unsafe cdp is now safe ...
        assert self.c.flipper.kicks() == 1  # One auction started
Beispiel #8
0
    def test_bite_and_flip(self, web3, mcd, gal_address, keeper_address):
        # given
        c = mcd.collaterals['ETH-A']
        keeper = AuctionKeeper(args=args(f"--eth-from {keeper_address} "
                                         f"--type flip "
                                         f"--network testnet "
                                         f"--ilk {c.ilk.name} "
                                         f"--model ./bogus-model.sh"),
                               web3=mcd.web3)
        keeper.approve()
        unsafe_cdp = create_unsafe_cdp(mcd, c, Wad.from_number(1.2),
                                       gal_address)
        assert len(mcd.active_auctions()["flips"][c.ilk.name]) == 0

        # when
        keeper.check_cdps()
        wait_for_other_threads()

        # then
        urn = mcd.vat.urn(unsafe_cdp.ilk, unsafe_cdp.address)
        assert urn.art == Wad(0)  # unsafe cdp has been bitten
        assert urn.ink == Wad(0)  # unsafe cdp is now safe ...
        assert c.flipper.kicks() == 1  # One auction started
Beispiel #9
0
def kick_small_lot(mcd, c: Collateral, gal_address) -> int:
    unsafe_cdp = create_unsafe_cdp(mcd, c, tend_small_lot, gal_address)
    return bite(mcd, c, unsafe_cdp)
Beispiel #10
0
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys

from pymaker.numeric import Wad, Ray, Rad
from tests.conftest import create_unsafe_cdp, is_cdp_safe, mcd, gal_address, web3

mcd = mcd(web3())
address = gal_address(web3())

collateral_amount = Wad.from_number(float(
    sys.argv[1])) if len(sys.argv) > 1 else 1.0
collateral = mcd.collaterals[str(
    sys.argv[2])] if len(sys.argv) > 2 else mcd.collaterals['ETH-C']
urn = mcd.vat.urn(collateral.ilk, address)

if not is_cdp_safe(mcd.vat.ilk(collateral.ilk.name), urn):
    print("CDP is already unsafe; no action taken")
else:
    create_unsafe_cdp(mcd, collateral, Wad.from_number(collateral_amount),
                      address, False)
    print("Created unsafe CDP")