예제 #1
0
 def __init__(self, ilk_id):
     self.id = ilk_id
     self.Art = Wad(0)
     self.rate = Ray(0)
     self.spot = Ray(0)
     self.line = Rad(0)
     self.dust = Rad(0)
예제 #2
0
 def track_stat(state, action, results):
     ilk = state["vat"].ilks[ilk_id]
     if action["key"] == "T_END":
         state["stats"]["num_unsafe_vaults"] = len([
             1 for urn in state["vat"].urns[ilk_id].values()
             if ilk.spot > Ray(0) and Rad(urn.ink * ilk.spot) < Rad(urn.art * ilk.rate)
         ])
예제 #3
0
    def kick(self, tab, lot, usr, kpr, now):
        require(tab > Rad(0), "Clipper/zero-tab")
        require(lot > Wad(0), "Clipper/zero-lot")
        require(bool(usr), "Clipper/zero-usr")
        require(self.kicks < (1 << 31) - 1, "Clipper/overflow")

        self.kicks += 1
        sale_id = self.kicks
        self.active.append(sale_id)

        pip = self.spotter.ilks[self.ilk_id].pip
        val = pip.peek(now)

        self.sales[sale_id] = Sale(
            len(self.active) - 1,
            tab,
            lot,
            usr,
            now,
            Ray(val / Wad(self.spotter.par)) * self.buf,
            sale_id,
        )

        if self.tip > Rad(0) or self.chip > Wad(0):
            self.vat.suck(self.vow.ADDRESS, kpr,
                          self.tip + tab * Rad(self.chip))
예제 #4
0
 def init(self, ilk_id):
     """ This specifically is *not* the __init__ method. """
     require(not self.ilks.get(ilk_id), "Vat/ilk-already-init")
     self.ilks[ilk_id] = Ilk(ilk_id)
     self.ilks[ilk_id].rate = Ray.from_number(1)
     # This is not canon lol
     self.urns[ilk_id] = {}
     self.gem[ilk_id] = {}
예제 #5
0
    def __init__(self, vat, spotter, dog, ilk_id):
        self.ADDRESS = f"clipper-{ilk_id}"

        self.vat = vat
        self.spotter = spotter
        self.dog = dog
        self.ilk_id = ilk_id
        self.buf = Ray.from_number(1)

        self.vow = None
        self.calc = None
        self.tail = 0
        self.cusp = Ray(0)
        self.kicks = 0
        self.active = []
        self.sales = {}
        self.locked = 0
        self.stopped = 0
        self.chip = Wad(0)
        self.tip = Rad(0)
예제 #6
0
    def bark(self, ilk_id, urn_id, kpr, now):
        ink = self.vat.urns[ilk_id][urn_id].ink
        art = self.vat.urns[ilk_id][urn_id].art
        milk = self.ilks[ilk_id]

        rate = self.vat.ilks[ilk_id].rate
        spot = self.vat.ilks[ilk_id].spot
        dust = self.vat.ilks[ilk_id].dust
        require(spot > Ray(0) and spot * ink < rate * art, "Dog/not-unsafe")

        room = min(self.Hole - self.Dirt, milk.hole - milk.dirt)
        require(room > Rad(0) and room >= dust, "Dog/liquidation-limit-hit")

        dart = min(art, Wad(room / Rad(rate)) / milk.chop)

        if Rad(rate * (art - dart)) < dust:
            # Q: What if art > room?
            # Resetting dart = art here can push past liq limit
            dart = art

        dink = ink * dart / art

        require(dink > Wad(0), "Dog/null-auction")
        require(
            dart <= Wad.from_number(2**255)
            and dink <= Wad.from_number(2**255),
            "Dog/overflow",
        )

        self.vat.grab(
            ilk_id,
            urn_id,
            milk.clip.ADDRESS,
            self.vow.ADDRESS,
            Wad(0) - dink,
            Wad(0) - dart,
        )

        due = Rad(rate * dart)
        self.vow.fess(due, now)

        tab = due * Rad(milk.chop)
        self.Dirt += tab
        self.ilks[ilk_id].dirt = milk.dirt + tab

        milk.clip.kick(tab, dink, urn_id, kpr, now)
        return [tab]
예제 #7
0
 def open_max_vaults(self, actions):
     for ilk_id in self.ilks:
         vat_ilk = self.vat.ilks[ilk_id]
         if self.ilks[ilk_id].balanceOf(
                 self.ADDRESS) > 0 and vat_ilk.spot > Ray(0):
             dink = Wad.from_number(self.ilks[ilk_id].balanceOf(
                 self.ADDRESS))
             dart = self.spot_paddings[ilk_id] * vat_ilk.spot * dink
             if dart > Wad(vat_ilk.dust) and Rad(
                     dart * vat_ilk.rate) <= Rad(dink * vat_ilk.spot):
                 actions.append({
                     "key": "OPEN_VAULT",
                     "keeper": self,
                     "handler": self.open_vault,
                     "args": [ilk_id, dink, dart],
                     "kwargs": {},
                 })
예제 #8
0
    def bite(self, ilk_id, urn, now):
        # TODO: Remove `now` once better timekeeping solution is implemented

        rate = self.vat.ilks[ilk_id].rate
        spot = self.vat.ilks[ilk_id].spot
        dust = self.vat.ilks[ilk_id].dust
        ink = self.vat.urns[ilk_id][urn].ink
        art = self.vat.urns[ilk_id][urn].art

        require(spot > Ray(0) and Rad(ink * spot) < Rad(art * rate),
                "Cat/not-unsafe")

        milk = self.ilks[ilk_id]

        room = self.box - self.litter
        require(self.litter < self.box and room >= dust,
                "Cat/liquidation-limit-hit")

        dart = Wad.min(art,
                       Wad(Rad.min(milk.dunk, room)) / Wad(rate) / milk.chop)
        dink = Wad.min(ink, ink * dart / art)

        require(dart > Wad(0) and dink > Wad(0), "Cat/null-auction")
        require(
            dart <= Wad.from_number(2**255)
            and dink <= Wad.from_number(2**255),
            "Cat/overflow",
        )

        self.vat.grab(ilk_id, urn, self.ADDRESS, self.vow.ADDRESS,
                      Wad(0) - dink,
                      Wad(0) - dart)
        self.vow.fess(Rad(dart * rate), now)

        tab = Rad(dart * rate * milk.chop)
        self.litter += tab

        milk.flip.kick(urn, self.vow.ADDRESS, tab, dink, Rad(0), now)
예제 #9
0
    def redo(self, sale_id, kpr, now):
        usr = self.sales[sale_id].usr
        tic = self.sales[sale_id].tic
        top = self.sales[sale_id].top

        require(bool(usr), "Clipper/not-running-auction")

        (done, _) = self.status(tic, top, now)
        require(done, "Clipper/cannot-reset")

        tab = self.sales[sale_id].tab
        lot = self.sales[sale_id].lot
        self.sales[sale_id].tic = now

        pip = self.spotter.ilks[self.ilk_id].pip
        val = pip.peek(now)
        price = Ray(val / Wad(self.spotter.par))
        self.sales[sale_id].top = price * self.buf

        if self.tip > Rad(0) or self.chip > Wad(0):
            dust = self.vat.ilks[self.ilk_id].dust
            if tab >= dust and Rad(lot * price) >= dust:
                self.vat.suck(self.vow.ADDRESS, kpr,
                              self.tip + tab * Rad(self.chip))
예제 #10
0
 def __init__(self, ilk_id):
     self.id = ilk_id
     self.pip = None
     self.mat = Ray(0)
예제 #11
0
         "amount":
         1,
         "get_params":
         lambda state: [
             [{
                 "ilk_id": "WETH",
                 "token": state["ilks"]["WETH"],
                 "init_balance": 0
             }],
             state["cat"],
             state["vat"],
         ],
     },
 },
 "Spotter": {
     "par": Ray(1000000000000000000000000000),
     "WETH": {
         "pip": PipLike("price_feeds/eth_black_thursday_10min.json"),
         "mat": Wad(1500000000000000000),
     },
 },
 "timesteps": 144,
 "Vat": {
     "Line": Rad(1621230562029182607785180351895167282074137639278363742),
     "WETH": {
         "line":
         Rad(590000000000000000000000000000000000000000000000000000),
         "dust": Rad(500000000000000000000000000000000000000000000000),
     },
 },
 "Vow": {
예제 #12
0
    incentive_amount(),
    num_new_barks(),
    num_unsafe_vaults("WETH"),
    num_sales_taken(),
    auction_debt(),
    ilk_price("WETH"),
    gas_price_gwei(),
    avg_time_to_liquidation("WETH"),
]
parameters = {
    "Abacus": {
        "tau": 72
    },
    "Clipper": {
        "WETH": {
            "buf": Ray.from_number(1.05),
            "tail": 72,
            "cusp": Ray.from_number(0.5),
            "chip": Wad.from_number(0.08),
            "tip": Rad.from_number(1000),
        }
    },
    "Dog": {
        "Hole": Rad(15000000000000000000000000000000000000000000000000000),
        "WETH": {
            "chop": Wad.from_number(1.13),
            "hole": Rad(15000000000000000000000000000000000000000000000000000),
        },
    },
    "Keepers": {
        "NaiveVaultKeeper": {
예제 #13
0
 def __init__(self):
     self.step = 0
     self.cut = Ray(0)
예제 #14
0
 def price(self, top, dur):
     if dur >= self.tau:
         return 0
     return top * Ray.from_number((self.tau - dur) / self.tau)
예제 #15
0
 def __init__(self, vat):
     self.ADDRESS = "spotter"
     self.vat = vat
     self.ilks = {}
     self.par = Ray(0)
예제 #16
0
 def is_unsafe(urn, ilk):
     return ilk.spot > Ray(0) and Rad(urn.ink * ilk.spot) < Rad(urn.art * ilk.rate)
예제 #17
0
 def price(self, top, dur):
     return top * (self.cut**Ray.from_number(dur / self.step))
예제 #18
0
 def poke(self, ilk_id, now):
     val = self.ilks[ilk_id].pip.peek(now)
     spot = Ray(val / Wad(self.par) / self.ilks[ilk_id].mat)
     self.vat.file_ilk(ilk_id, "spot", spot)
예제 #19
0
 def status(self, tic, top, now):
     price = self.calc.price(top, now - tic)
     done = now - tic > self.tail or Ray(price) / top < self.cusp
     return (done, price)