def test_fog_and_woe_and_bust(self, deployment: Deployment): # given deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact() # and deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(4)).transact() deployment.tub.draw(1, Wad.from_number(1000)).transact() # and DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(150).value).transact() # when deployment.tub.bite(1).transact() # then assert deployment.tap.fog() == Wad.from_number(4) assert deployment.tap.woe() == Wad.from_number(1000) assert deployment.skr.balance_of(deployment.our_address) == Wad.from_number(6) assert deployment.sai.balance_of(deployment.our_address) == Wad.from_number(1000) # when deployment.tap.bust(Wad.from_number(2)).transact() assert deployment.tap.fog() == Wad.from_number(2) assert deployment.tap.woe() == Wad.from_number(700) assert deployment.skr.balance_of(deployment.our_address) == Wad.from_number(8) assert deployment.sai.balance_of(deployment.our_address) == Wad.from_number(700)
def test_bite_and_safe(self, deployment: Deployment): # given deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact() # when deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(4)).transact() deployment.tub.draw(1, Wad.from_number(1000)).transact() # then assert deployment.tub.safe(1) # when DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(150).value).transact() # then assert not deployment.tub.safe(1) # when deployment.tub.bite(1).transact() # then assert deployment.tub.safe(1)
def prepare_unsafe_cup(deployment: Deployment): deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(250).value).transact() deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(4)).transact() deployment.tub.draw(1, Wad.from_number(1000)).transact() # price goes down, the cup becomes unsafe DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(150).value).transact()
def from_json(web3: Web3, conf: str): conf = json.loads(conf) mom = DSGuard(web3, Address(conf['MCD_MOM'])) vat = Vat(web3, Address(conf['MCD_VAT'])) vow = Vow(web3, Address(conf['MCD_VOW'])) drip = Drip(web3, Address(conf['MCD_DRIP'])) pit = Pit(web3, Address(conf['MCD_PIT'])) cat = Cat(web3, Address(conf['MCD_CAT'])) flap = Flapper(web3, Address(conf['MCD_FLAP'])) flop = Flopper(web3, Address(conf['MCD_FLOP'])) dai = DSToken(web3, Address(conf['MCD_DAI'])) dai_adapter = DaiAdapter(web3, Address(conf['MCD_JOIN_DAI'])) dai_move = DaiVat(web3, Address(conf['MCD_MOVE_DAI'])) mkr = DSToken(web3, Address(conf['MCD_GOV'])) collaterals = [] for name in conf['COLLATERALS']: collateral = Collateral(Ilk(name)) collateral.gem = DSToken(web3, Address(conf[name])) collateral.adapter = GemAdapter(web3, Address(conf[f'MCD_JOIN_{name}'])) collateral.mover = GemVat(web3, Address(conf[f'MCD_MOVE_{name}'])) collateral.flipper = Flipper(web3, Address(conf[f'MCD_FLIP_{name}'])) collateral.pip = DSValue(web3, Address(conf[f'PIP_{name}'])) collateral.spotter = Spotter(web3, Address(conf[f'MCD_SPOT_{name}'])) collaterals.append(collateral) return DssDeployment.Config(mom, vat, vow, drip, pit, cat, flap, flop, dai, dai_adapter, dai_move, mkr, collaterals)
def test_cash(self, deployment: Deployment): # given deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact() # and deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(4)).transact() deployment.tub.draw(1, Wad.from_number(1000)).transact() # and gem_before = deployment.gem.balance_of(deployment.our_address) # when deployment.top.cage().transact() deployment.tap.cash(Wad.from_number(500)).transact() # then gem_after = deployment.gem.balance_of(deployment.our_address) assert gem_after - gem_before == Wad.from_number(2) # when deployment.tap.cash(Wad.from_number(500)).transact() # then gem_after = deployment.gem.balance_of(deployment.our_address) assert gem_after - gem_before == Wad.from_number(4)
def from_json(web3: Web3, conf: str): conf = json.loads(conf) pause = DSPause(web3, Address(conf['MCD_PAUSE'])) vat = Vat(web3, Address(conf['MCD_VAT'])) vow = Vow(web3, Address(conf['MCD_VOW'])) jug = Jug(web3, Address(conf['MCD_JUG'])) cat = Cat(web3, Address(conf['MCD_CAT'])) dai = DSToken(web3, Address(conf['MCD_DAI'])) dai_adapter = DaiJoin(web3, Address(conf['MCD_JOIN_DAI'])) flapper = Flapper(web3, Address(conf['MCD_FLAP'])) flopper = Flopper(web3, Address(conf['MCD_FLOP'])) mkr = DSToken(web3, Address(conf['MCD_GOV'])) spotter = Spotter(web3, Address(conf['MCD_SPOT'])) collaterals = {} for name in DssDeployment.Config._infer_collaterals_from_addresses(conf.keys()): ilk = Ilk(name[0].replace('_', '-')) if name[1] == "ETH": gem = DSEthToken(web3, Address(conf[name[1]])) else: gem = DSToken(web3, Address(conf[name[1]])) # TODO: If problematic, skip pip for deployments which use a medianizer. collateral = Collateral(ilk=ilk, gem=gem, adapter=GemJoin(web3, Address(conf[f'MCD_JOIN_{name[0]}'])), flipper=Flipper(web3, Address(conf[f'MCD_FLIP_{name[0]}'])), pip=DSValue(web3, Address(conf[f'PIP_{name[1]}']))) collaterals[ilk.name] = collateral return DssDeployment.Config(pause, vat, vow, jug, cat, flapper, flopper, dai, dai_adapter, mkr, spotter, collaterals)
def test_joy_and_boom(self, deployment: Deployment): # given deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() deployment.tub.mold_tax(Ray(1000100000000000000000000000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact() # and deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(4)).transact() deployment.tub.draw(1, Wad.from_number(1000)).transact() # when deployment.time_travel_by(3600) deployment.tub.drip().transact() # then assert deployment.skr.balance_of(deployment.our_address) == Wad.from_number(6) assert deployment.tap.joy() == Wad(433303616582911495481) # when deployment.tap.boom(Wad.from_number(1)).transact() # then assert deployment.skr.balance_of(deployment.our_address) == Wad.from_number(5) assert deployment.tap.joy() == Wad(183303616582911495481)
def test_draw_and_tab_and_din_and_wipe(self, deployment: Deployment): # given deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250.45).value).transact() # and deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(5)).transact() # when deployment.tub.draw(1, Wad.from_number(50)).transact() # then assert deployment.sai.balance_of(deployment.our_address) == Wad.from_number(50) assert deployment.tub.tab(1) == Wad.from_number(50) assert deployment.tub.din() == Wad.from_number(50) # when deployment.tub.wipe(1, Wad.from_number(30)).transact() # then assert deployment.sai.balance_of(deployment.our_address) == Wad.from_number(20) assert deployment.tub.tab(1) == Wad.from_number(20) assert deployment.tub.din() == Wad.from_number(20)
def test_should_execute_arbitrage_in_one_transaction_if_tx_manager_configured( self, deployment: Deployment): # given tx_manager = TxManager.deploy(deployment.web3) # and keeper = ArbitrageKeeper(args=args( f"--eth-from {deployment.our_address.address}" f" --tub-address {deployment.tub.address}" f" --tap-address {deployment.tap.address}" f" --oasis-address {deployment.otc.address}" f" --base-token {deployment.sai.address}" f" --min-profit 13.0 --max-engagement 100.0" f" --tx-manager {tx_manager.address}"), web3=deployment.web3) # and DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() deployment.tub.mold_gap(Wad.from_number(1.05)).transact() deployment.tub.join(Wad.from_number(1000)).transact() deployment.tap.mold_gap(Wad.from_number(1.05)).transact() # and deployment.sai.mint(Wad.from_number(1000)).transact() # and deployment.otc.approve( [deployment.gem, deployment.sai, deployment.skr], directly()) deployment.otc.add_token_pair_whitelist( deployment.sai.address, deployment.skr.address).transact() deployment.otc.add_token_pair_whitelist( deployment.skr.address, deployment.gem.address).transact() deployment.otc.add_token_pair_whitelist( deployment.gem.address, deployment.sai.address).transact() deployment.otc.make(deployment.skr.address, Wad.from_number(105), deployment.sai.address, Wad.from_number(100)).transact() deployment.otc.make(deployment.gem.address, Wad.from_number(110), deployment.skr.address, Wad.from_number(105)).transact() deployment.otc.make(deployment.sai.address, Wad.from_number(115), deployment.gem.address, Wad.from_number(110)).transact() assert len(deployment.otc.get_orders()) == 3 # when keeper.approve() block_number_before = deployment.web3.eth.blockNumber keeper.process_block() block_number_after = deployment.web3.eth.blockNumber # then assert len(deployment.otc.get_orders()) == 0 # and # [keeper used only one transaction, as TxManager is configured] assert (block_number_after - block_number_before) == 1
def test_tag(self, deployment: Deployment): # when DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(250.45).value).transact() # then assert deployment.tub.tag() == Ray.from_number(250.45)
def test_s2s_and_bid_and_ask(self, deployment: Deployment): # when DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(500).value).transact() deployment.tap.mold_gap(Wad.from_number(1.05)).transact() # then assert deployment.tap.bid(Wad.from_number(2)) == Wad.from_number(475)*Wad.from_number(2) assert deployment.tap.s2s() == Ray.from_number(500) assert deployment.tap.ask(Wad.from_number(2)) == Wad.from_number(525)*Wad.from_number(2)
def test_shut(self, deployment: Deployment): # given DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact() deployment.tub.open().transact() # when deployment.tub.shut(1).transact() # then assert deployment.tub.lad(1) == Address('0x0000000000000000000000000000000000000000')
def test_should_bite_unsafe_cups_only(self, deployment: Deployment): # given keeper = BiteKeeper(args=args( f"--eth-from {deployment.web3.eth.defaultAccount} --tub-address {deployment.tub.address}" ), web3=deployment.web3) # and deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(250).value).transact() # and deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(4)).transact() deployment.tub.draw(1, Wad.from_number(1000)).transact() # and assert deployment.tub.safe(1) # when keeper.check_all_cups() # then assert deployment.tub.safe(1) assert deployment.tub.tab(1) == Wad.from_number(1000) # when DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(150).value).transact() # and assert not deployment.tub.safe(1) # and keeper.check_all_cups() # then assert deployment.tub.safe(1) assert deployment.tub.tab(1) == Wad.from_number(0)
def from_json(web3: Web3, conf: str): conf = json.loads(conf) pause = DSPause(web3, Address(conf['MCD_PAUSE'])) vat = Vat(web3, Address(conf['MCD_VAT'])) vow = Vow(web3, Address(conf['MCD_VOW'])) jug = Jug(web3, Address(conf['MCD_JUG'])) cat = Cat(web3, Address(conf['MCD_CAT'])) dai = DSToken(web3, Address(conf['MCD_DAI'])) dai_adapter = DaiJoin(web3, Address(conf['MCD_JOIN_DAI'])) flapper = Flapper(web3, Address(conf['MCD_FLAP'])) flopper = Flopper(web3, Address(conf['MCD_FLOP'])) pot = Pot(web3, Address(conf['MCD_POT'])) mkr = DSToken(web3, Address(conf['MCD_GOV'])) spotter = Spotter(web3, Address(conf['MCD_SPOT'])) ds_chief = DSChief(web3, Address(conf['MCD_ADM'])) esm = ShutdownModule(web3, Address(conf['MCD_ESM'])) end = End(web3, Address(conf['MCD_END'])) proxy_registry = ProxyRegistry(web3, Address(conf['PROXY_REGISTRY'])) dss_proxy_actions = DssProxyActionsDsr( web3, Address(conf['PROXY_ACTIONS_DSR'])) collaterals = {} for name in DssDeployment.Config._infer_collaterals_from_addresses( conf.keys()): ilk = Ilk(name[0].replace('_', '-')) if name[1] == "ETH": gem = DSEthToken(web3, Address(conf[name[1]])) else: gem = DSToken(web3, Address(conf[name[1]])) # PIP contract may be a DSValue, OSM, or bogus address. pip_address = Address(conf[f'PIP_{name[1]}']) network = DssDeployment.NETWORKS.get(web3.net.version, "testnet") if network == "testnet": pip = DSValue(web3, pip_address) else: pip = OSM(web3, pip_address) collateral = Collateral( ilk=ilk, gem=gem, adapter=GemJoin(web3, Address(conf[f'MCD_JOIN_{name[0]}'])), flipper=Flipper(web3, Address(conf[f'MCD_FLIP_{name[0]}'])), pip=pip) collaterals[ilk.name] = collateral return DssDeployment.Config(pause, vat, vow, jug, cat, flapper, flopper, pot, dai, dai_adapter, mkr, spotter, ds_chief, esm, end, proxy_registry, dss_proxy_actions, collaterals)
def test_safe(self, deployment: Deployment): # given deployment.tub.mold_mat(Ray.from_number(1.5)).transact() deployment.tub.mold_axe(Ray.from_number(1.2)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact() # when deployment.tub.open().transact() # then assert deployment.tub.safe(1)
def test_should_obey_min_profit(self, deployment: Deployment): # given keeper = ArbitrageKeeper(args=args( f"--eth-from {deployment.our_address.address}" f" --tub-address {deployment.tub.address}" f" --tap-address {deployment.tap.address}" f" --oasis-address {deployment.otc.address}" f" --base-token {deployment.sai.address}" f" --min-profit 16.0 --max-engagement 1000.0"), web3=deployment.web3) # and DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() deployment.tub.mold_gap(Wad.from_number(1.05)).transact() deployment.tub.join(Wad.from_number(1000)).transact() deployment.tap.mold_gap(Wad.from_number(1.05)).transact() # and deployment.sai.mint(Wad.from_number(1000)).transact() # and deployment.otc.approve( [deployment.gem, deployment.sai, deployment.skr], directly()) deployment.otc.add_token_pair_whitelist( deployment.sai.address, deployment.skr.address).transact() deployment.otc.add_token_pair_whitelist( deployment.skr.address, deployment.gem.address).transact() deployment.otc.add_token_pair_whitelist( deployment.gem.address, deployment.sai.address).transact() deployment.otc.make(deployment.skr.address, Wad.from_number(105), deployment.sai.address, Wad.from_number(100)).transact() deployment.otc.make(deployment.gem.address, Wad.from_number(110), deployment.skr.address, Wad.from_number(105)).transact() deployment.otc.make(deployment.sai.address, Wad.from_number(115), deployment.gem.address, Wad.from_number(110)).transact() assert len(deployment.otc.get_orders()) == 3 # when keeper.approve() keeper.process_block() # then assert len(deployment.otc.get_orders()) == 3 assert deployment.otc.get_orders()[0].buy_amount == Wad.from_number( 100) assert deployment.otc.get_orders()[1].buy_amount == Wad.from_number( 105) assert deployment.otc.get_orders()[2].buy_amount == Wad.from_number( 110)
def test_should_identify_arbitrage_against_oasis_and_exit( self, deployment: Deployment): # given keeper = ArbitrageKeeper(args=args( f"--eth-from {deployment.our_address.address}" f" --tub-address {deployment.tub.address}" f" --tap-address {deployment.tap.address}" f" --oasis-address {deployment.otc.address}" f" --base-token {deployment.gem.address}" f" --min-profit 5.0 --max-engagement 100.0"), web3=deployment.web3) # and # [a price is set, so the arbitrage keeper knows prices of `boom` and `bust`] DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() # and # [we have 100 WETH] deployment.gem.mint(Wad.from_number(100)).transact() # and # [somebody else placed an order on OASIS offering 110 SKR for 100 WETH] second_address = Address(deployment.web3.eth.accounts[1]) deployment.gem.mint(Wad.from_number(110)).transact() deployment.tub.join(Wad.from_number(110)).transact() deployment.skr.transfer(second_address, Wad.from_number(110)).transact() deployment.otc.add_token_pair_whitelist( deployment.skr.address, deployment.gem.address).transact() deployment.otc.approve([deployment.gem, deployment.skr], directly(from_address=second_address)) deployment.otc.make( deployment.skr.address, Wad.from_number(110), deployment.gem.address, Wad.from_number(100)).transact(from_address=second_address) assert deployment.skr.total_supply() == Wad.from_number(110) assert len(deployment.otc.get_orders()) == 1 # when keeper.approve() keeper.process_block() # then # [the order on Oasis has been taken by the keeper] assert len(deployment.otc.get_orders()) == 0 # and # [the total supply of SKR has decreased, so we know the keeper did call exit('110.0')] assert deployment.skr.total_supply() == Wad.from_number(0)
def test_not_empty_cups(self, deployment: Deployment): # given deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250.45).value).transact() # and deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(3)).transact() # when deployment.tub.draw(1, Wad.from_number(50)).transact() # then assert deployment.tub.cups(1).art == Wad.from_number(50) assert deployment.tub.cups(1).ink == Wad.from_number(3)
def test_cage(self, deployment: Deployment): # given deployment.tub.join(Wad.from_number(10)).transact() deployment.tub.mold_cap(Wad.from_number(100000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact() # and deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(4)).transact() deployment.tub.draw(1, Wad.from_number(1000)).transact() # when deployment.top.cage().transact() # then assert deployment.top.fix() == Ray.from_number(0.004)
def test_should_not_do_anything_if_no_arbitrage_opportunities( self, deployment: Deployment): # given keeper = ArbitrageKeeper(args=args( f"--eth-from {deployment.our_address.address}" f" --tub-address {deployment.tub.address}" f" --tap-address {deployment.tap.address}" f" --oasis-address {deployment.otc.address}" f" --base-token {deployment.sai.address}" f" --min-profit 1.0 --max-engagement 1000.0"), web3=deployment.web3) DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() deployment.tap.mold_gap(Wad.from_number(1.05)).transact() # when keeper.approve() keeper.process_block()
def test_lock_and_free(self, deployment: Deployment): # given DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int(Wad.from_number(250).value).transact() deployment.tub.open().transact() deployment.tub.join(Wad.from_number(10)).transact() # when print(deployment.tub.cupi()) deployment.tub.lock(1, Wad.from_number(5)).transact() # then assert deployment.tub.ink(1) == Wad.from_number(5) assert deployment.tub.air() == Wad.from_number(5) # when deployment.tub.free(1, Wad.from_number(3)).transact() # then assert deployment.tub.ink(1) == Wad.from_number(2) assert deployment.tub.air() == Wad.from_number(2)
def __init__(self, tub: Tub): assert(isinstance(tub, Tub)) self.ds_value = DSValue(web3=tub.web3, address=tub.pip())
def from_json(web3: Web3, conf: str): def address_in_configs(key: str, conf: str) -> bool: if key not in conf: return False elif not conf[key]: return False elif conf[key] == "0x0000000000000000000000000000000000000000": return False else: return True conf = json.loads(conf) pause = DSPause(web3, Address(conf['MCD_PAUSE'])) vat = Vat(web3, Address(conf['MCD_VAT'])) vow = Vow(web3, Address(conf['MCD_VOW'])) jug = Jug(web3, Address(conf['MCD_JUG'])) cat = Cat(web3, Address(conf['MCD_CAT'])) if address_in_configs( 'MCD_CAT', conf) else None dog = Dog(web3, Address(conf['MCD_DOG'])) if address_in_configs( 'MCD_DOG', conf) else None dai = DSToken(web3, Address(conf['MCD_DAI'])) dai_adapter = DaiJoin(web3, Address(conf['MCD_JOIN_DAI'])) flapper = Flapper(web3, Address(conf['MCD_FLAP'])) flopper = Flopper(web3, Address(conf['MCD_FLOP'])) pot = Pot(web3, Address(conf['MCD_POT'])) mkr = DSToken(web3, Address(conf['MCD_GOV'])) spotter = Spotter(web3, Address(conf['MCD_SPOT'])) ds_chief = DSChief(web3, Address(conf['MCD_ADM'])) esm = ShutdownModule(web3, Address(conf['MCD_ESM'])) end = End(web3, Address(conf['MCD_END'])) proxy_registry = ProxyRegistry(web3, Address(conf['PROXY_REGISTRY'])) dss_proxy_actions = DssProxyActionsDsr( web3, Address(conf['PROXY_ACTIONS_DSR'])) cdp_manager = CdpManager(web3, Address(conf['CDP_MANAGER'])) dsr_manager = DsrManager(web3, Address(conf['DSR_MANAGER'])) faucet = TokenFaucet( web3, Address(conf['FAUCET'])) if address_in_configs( 'FAUCET', conf) else None collaterals = {} for name in DssDeployment.Config._infer_collaterals_from_addresses( conf.keys()): ilk = vat.ilk(name[0].replace('_', '-')) if name[1] == "ETH": gem = DSEthToken(web3, Address(conf[name[1]])) else: gem = DSToken(web3, Address(conf[name[1]])) if name[1] in [ 'USDC', 'WBTC', 'TUSD', 'USDT', 'GUSD', 'RENBTC' ]: adapter = GemJoin5(web3, Address(conf[f'MCD_JOIN_{name[0]}'])) else: adapter = GemJoin(web3, Address(conf[f'MCD_JOIN_{name[0]}'])) # PIP contract may be a DSValue, OSM, or bogus address. pip_name = f'PIP_{name[1]}' pip_address = Address( conf[pip_name] ) if pip_name in conf and conf[pip_name] else None val_name = f'VAL_{name[1]}' val_address = Address( conf[val_name] ) if val_name in conf and conf[val_name] else None if pip_address: # Configure OSM as price source if name[1].startswith('UNIV2'): pip = Univ2LpOSM(web3, pip_address) else: pip = OSM(web3, pip_address) elif val_address: # Configure price using DSValue pip = DSValue(web3, val_address) else: pip = None auction = None if f'MCD_FLIP_{name[0]}' in conf: auction = Flipper(web3, Address(conf[f'MCD_FLIP_{name[0]}'])) elif f'MCD_CLIP_{name[0]}' in conf: auction = Clipper(web3, Address(conf[f'MCD_CLIP_{name[0]}'])) collateral = Collateral(ilk=ilk, gem=gem, adapter=adapter, auction=auction, pip=pip, vat=vat) collaterals[ilk.name] = collateral return DssDeployment.Config(pause, vat, vow, jug, cat, dog, flapper, flopper, pot, dai, dai_adapter, mkr, spotter, ds_chief, esm, end, proxy_registry, dss_proxy_actions, cdp_manager, dsr_manager, faucet, collaterals)
def set_price(deployment: Deployment, price: Wad): DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( price.value).transact()
def test_should_identify_arbitrage_against_oasis_and_boom( self, deployment: Deployment): # given keeper = ArbitrageKeeper(args=args( f"--eth-from {deployment.our_address.address}" f" --tub-address {deployment.tub.address}" f" --tap-address {deployment.tap.address}" f" --oasis-address {deployment.otc.address}" f" --base-token {deployment.sai.address}" f" --min-profit 100.0 --max-engagement 500000.0"), web3=deployment.web3) # and # [we generate some Dai surplus available for `boom`] DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() deployment.tub.mold_cap(Wad.from_number(10000000000)).transact() deployment.tub.mold_mat(Ray.from_number(1.5)).transact() deployment.tub.mold_axe(Ray.from_number(1.2)).transact() deployment.tub.mold_tax(Ray.from_number(1.0000000001)).transact() deployment.gem.mint(Wad.from_number(1000000)).transact() deployment.tub.join(Wad.from_number(1000000)).transact() deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(1000000)).transact() deployment.tub.draw(1, Wad.from_number(250000000)).transact() time_travel_by(deployment.web3, 60 * 60 * 24 * 180) deployment.tub.wipe(1, Wad.from_number(250000000)).transact() print(deployment.tap.joy()) assert Wad.from_number( 389102) < deployment.tap.joy() < Wad.from_number(389103) # and # [we add a boom/bust spread to make calculations a bit more difficult] deployment.tap.mold_gap(Wad.from_number(0.95)).transact() assert deployment.tap.ask(Wad.from_number(1)) == Wad.from_number(475.0) assert deployment.tap.bid(Wad.from_number(1)) == Wad.from_number(525.0) # and # [we have lots of SAI to invest] deployment.sai.mint(Wad.from_number(5000000.00)).transact() # [we have some SKR to cover rounding errors] deployment.skr.mint(Wad.from_number(0.000000000000000001)).transact() # and # [we should now have 389102.xx SAI available for 741.14 SKR on `boom`] # [now lets pretend somebody else placed an order on OASIS offering 1000 GEM for 500000 SAI] second_address = Address(deployment.web3.eth.accounts[1]) deployment.gem.mint(Wad.from_number(1000)).transact() deployment.gem.transfer(second_address, Wad.from_number(1000)).transact() deployment.otc.approve([deployment.sai, deployment.gem], directly(from_address=second_address)) deployment.otc.make( deployment.gem.address, Wad.from_number(1000), deployment.sai.address, Wad.from_number(500000)).transact(from_address=second_address) assert len(deployment.otc.get_orders()) == 1 # when keeper.approve() keeper.process_block() # and # [the amount of surplus is almost zero, so we know the keeper did call boom()] # [the inequality below is to cater for rounding errors] assert deployment.tap.joy() < Wad.from_number(0.1)
def test_should_identify_arbitrage_against_oasis_and_bust( self, deployment: Deployment): # given keeper = ArbitrageKeeper(args=args( f"--eth-from {deployment.our_address.address}" f" --tub-address {deployment.tub.address}" f" --tap-address {deployment.tap.address}" f" --oasis-address {deployment.otc.address}" f" --base-token {deployment.sai.address}" f" --min-profit 950.0 --max-engagement 14250.0"), web3=deployment.web3) # and # [we generate some bad debt available for `bust`] DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() deployment.tub.mold_cap(Wad.from_number(1000000)).transact() deployment.tub.mold_mat(Ray.from_number(2.0)).transact() deployment.tub.mold_axe(Ray.from_number(2.0)).transact() deployment.gem.mint(Wad.from_number(100)).transact() deployment.tub.join(Wad.from_number(100)).transact() deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(100)).transact() deployment.tub.draw(1, Wad.from_number(25000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(400).value).transact() deployment.tub.bite(1).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() assert deployment.tap.woe() == Wad.from_number(25000) assert deployment.tap.fog() == Wad.from_number(100) # and # [we add a boom/bust spread to make calculations a bit more difficult] deployment.tap.mold_gap(Wad.from_number(0.95)).transact() assert deployment.tap.ask(Wad.from_number(1)) == Wad.from_number(475.0) assert deployment.tap.bid(Wad.from_number(1)) == Wad.from_number(525.0) # and # [we have some SKR to cover rounding errors] deployment.skr.mint(Wad.from_number(0.000000000000000001)).transact() # and # [we should now have 30 SKR available for 14250 SAI on `bust`] # [now lets pretend somebody else placed an order on OASIS offering 15250 SAI for 30 GEM] # [this will be an arbitrage opportunity which can make the bot earn 1000 SAI] second_address = Address(deployment.web3.eth.accounts[1]) deployment.sai.mint(Wad.from_number(15250)).transact() deployment.sai.transfer(second_address, Wad.from_number(15250)).transact() deployment.otc.approve([deployment.sai, deployment.gem], directly(from_address=second_address)) deployment.otc.make( deployment.sai.address, Wad.from_number(15250), deployment.gem.address, Wad.from_number(30)).transact(from_address=second_address) assert len(deployment.otc.get_orders()) == 1 # when keeper.approve() keeper.process_block() # then # [the order on Oasis has been taken by the keeper] assert len(deployment.otc.get_orders()) == 0 # and # [the amount of bad debt has decreased, so we know the keeper did call bust('14250.0')] # [the inequality below is to cater for rounding errors] assert deployment.tap.woe() < Wad.from_number(10800.0)
def test_should_identify_arbitrage_against_0x_and_bust( self, deployment: Deployment): # given # [0x protocol is in place] zrx_token = ERC20Token(web3=deployment.web3, address=deploy_contract(deployment.web3, 'ZRXToken')) token_transfer_proxy_address = deploy_contract(deployment.web3, 'TokenTransferProxy') exchange = ZrxExchange.deploy(deployment.web3, zrx_token.address, token_transfer_proxy_address) deployment.web3.eth.contract(abi=json.loads( pkg_resources.resource_string( 'pymaker.deployment', f'abi/TokenTransferProxy.abi')))( address=token_transfer_proxy_address.address).transact( ).addAuthorizedAddress(exchange.address.address) # and keeper = ArbitrageKeeper(args=args( f"--eth-from {deployment.our_address.address}" f" --tub-address {deployment.tub.address}" f" --tap-address {deployment.tap.address}" f" --oasis-address {deployment.otc.address}" f" --exchange-address {exchange.address}" f" --relayer-api-server http://127.0.0.1:9999/sra/v0" f" --base-token {deployment.sai.address}" f" --min-profit 950.0 --max-engagement 14250.0"), web3=deployment.web3) # and # [we generate some bad debt available for `bust`] DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() deployment.tub.mold_cap(Wad.from_number(1000000)).transact() deployment.tub.mold_mat(Ray.from_number(2.0)).transact() deployment.tub.mold_axe(Ray.from_number(2.0)).transact() deployment.gem.mint(Wad.from_number(100)).transact() deployment.tub.join(Wad.from_number(100)).transact() deployment.tub.open().transact() deployment.tub.lock(1, Wad.from_number(100)).transact() deployment.tub.draw(1, Wad.from_number(25000)).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(400).value).transact() deployment.tub.bite(1).transact() DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(500).value).transact() assert deployment.tap.woe() == Wad.from_number(25000) assert deployment.tap.fog() == Wad.from_number(100) # and # [we add a boom/bust spread to make calculations a bit more difficult] deployment.tap.mold_gap(Wad.from_number(0.95)).transact() assert deployment.tap.ask(Wad.from_number(1)) == Wad.from_number(475.0) assert deployment.tap.bid(Wad.from_number(1)) == Wad.from_number(525.0) # and # [we have some SKR to cover rounding errors] deployment.skr.mint(Wad.from_number(0.000000000000000001)).transact() # and # [we should now have 30 SKR available for 14250 SAI on `bust`] # [now lets pretend we placed an order on 0x offering 15250 SAI for 30 GEM] # [this will be an arbitrage opportunity which can make the bot earn 1000 SAI] deployment.sai.mint(Wad.from_number(15250)).transact() exchange.approve([deployment.sai, deployment.gem], directly()) zrx_order = exchange.sign_order( exchange.create_order(pay_token=deployment.sai.address, pay_amount=Wad.from_number(15250), buy_token=deployment.gem.address, buy_amount=Wad.from_number(30), expiration=int(time.time() + 3600))) keeper.zrx_orders = lambda tokens: [zrx_order] # when keeper.approve() keeper.process_block() # then # [the 0x order has been taken by the keeper] assert exchange.get_unavailable_buy_amount( zrx_order) == Wad.from_number(30) # and # [the amount of bad debt has decreased, so we know the keeper did call bust('14250.0')] # [the inequality below is to cater for rounding errors] assert deployment.tap.woe() < Wad.from_number(10800.0)
def test_fail_when_no_contract_under_that_address(self): # expect with pytest.raises(Exception): DSValue(web3=self.web3, address=Address('0xdeadadd1e5500000000000000000000000000000'))
def set_price(deployment: Deployment, new_price): DSValue(web3=deployment.web3, address=deployment.tub.pip()).poke_with_int( Wad.from_number(new_price).value).transact()