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)
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) ])
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))
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] = {}
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)
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]
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": {}, })
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)
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))
def __init__(self, ilk_id): self.id = ilk_id self.pip = None self.mat = Ray(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": {
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": {
def __init__(self): self.step = 0 self.cut = Ray(0)
def price(self, top, dur): if dur >= self.tau: return 0 return top * Ray.from_number((self.tau - dur) / self.tau)
def __init__(self, vat): self.ADDRESS = "spotter" self.vat = vat self.ilks = {} self.par = Ray(0)
def is_unsafe(urn, ilk): return ilk.spot > Ray(0) and Rad(urn.ink * ilk.spot) < Rad(urn.art * ilk.rate)
def price(self, top, dur): return top * (self.cut**Ray.from_number(dur / self.step))
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)
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)