Пример #1
0
def create_risky_cdp(mcd: DssDeployment,
                     c: Collateral,
                     collateral_amount: Wad,
                     gal_address: Address,
                     draw_dai=True) -> Urn:
    assert isinstance(mcd, DssDeployment)
    assert isinstance(c, Collateral)
    assert isinstance(gal_address, Address)

    # Ensure vault isn't already unsafe (if so, this shouldn't be called)
    urn = mcd.vat.urn(c.ilk, gal_address)
    assert is_cdp_safe(mcd.vat.ilk(c.ilk.name), urn)

    # Add collateral to gal vault if necessary
    c.approve(gal_address)
    token = Token(c.ilk.name, c.gem.address, c.adapter.dec())
    print(f"collateral_amount={collateral_amount} ink={urn.ink}")
    dink = collateral_amount - urn.ink
    if dink > Wad(0):
        vat_balance = mcd.vat.gem(c.ilk, gal_address)
        balance = token.normalize_amount(c.gem.balance_of(gal_address))
        print(
            f"before join: dink={dink} vat_balance={vat_balance} balance={balance} vat_gap={dink - vat_balance}"
        )
        if vat_balance < dink:
            vat_gap = dink - vat_balance
            if balance < vat_gap:
                if c.ilk.name.startswith("ETH"):
                    wrap_eth(mcd, gal_address, vat_gap)
                else:
                    raise RuntimeError("Insufficient collateral balance")
            amount_to_join = token.unnormalize_amount(vat_gap)
            if amount_to_join == Wad(
                    0):  # handle dusty balances with non-18-decimal tokens
                amount_to_join += token.unnormalize_amount(token.min_amount)
            assert c.adapter.join(
                gal_address, amount_to_join).transact(from_address=gal_address)
        vat_balance = mcd.vat.gem(c.ilk, gal_address)
        print(
            f"after join: dink={dink} vat_balance={vat_balance} balance={balance} vat_gap={dink - vat_balance}"
        )
        assert vat_balance >= dink
        assert mcd.vat.frob(c.ilk, gal_address, dink,
                            Wad(0)).transact(from_address=gal_address)

    # Put gal CDP at max possible debt
    dart = max_dart(mcd, c, gal_address) - Wad(1)
    if dart > Wad(0):
        print(f"Attempting to frob with dart={dart}")
        assert mcd.vat.frob(c.ilk, gal_address, Wad(0),
                            dart).transact(from_address=gal_address)

    # Draw our Dai, simulating the usual behavior
    urn = mcd.vat.urn(c.ilk, gal_address)
    if draw_dai and urn.art > Wad(0):
        mcd.approve_dai(gal_address)
        assert mcd.dai_adapter.exit(gal_address,
                                    urn.art).transact(from_address=gal_address)
        print(f"Exited {urn.art} Dai from urn")
Пример #2
0
 def setup_method(self):
     self.web3 = Web3(HTTPProvider("http://localhost:8555"))
     self.web3.eth.defaultAccount = self.web3.eth.accounts[0]
     self.our_address = Address(self.web3.eth.defaultAccount)
     self.token1 = DSToken.deploy(self.web3, 'AAA')
     self.token1.mint(Wad.from_number(10000)).transact()
     self.token1_tokenclass = Token('AAA', self.token1.address, 18)
     self.token2 = DSToken.deploy(self.web3, 'BBB')
     self.token2.mint(Wad.from_number(10000)).transact()
     self.token2_tokenclass = Token('BBB', self.token2.address, 18)
     price_oracle = OasisMockPriceOracle.deploy(self.web3)
     self.otc = MatchingMarket.deploy(self.web3, self.token1.address, Wad(0), price_oracle.address)
     self.otc.add_token_pair_whitelist(self.token1.address, self.token2.address).transact()
     self.otc.approve([self.token1, self.token2], directly())
     for amount in [11,55,44,34,36,21,45,51,15]:
         self.otc.make(p_token=self.token1_tokenclass, pay_amount=Wad.from_number(1),
                       b_token=self.token2_tokenclass, buy_amount=Wad.from_number(amount)).transact()
Пример #3
0
    def test_mint_token_pool_low_price_and_slippage(self):
        """ Test minting a position for a pool that is a small fraction """
        test_token_1 = Token(
            "test_1", Address("0x0000000000000000000000000000000000000001"),
            18)
        test_token_2 = Token(
            "test_2", Address("0x0000000000000000000000000000000000000002"),
            18)

        token_1_balance = Wad.from_number(10)
        token_2_balance = Wad.from_number(100)

        # sqrt_price_ratio = self.get_starting_sqrt_ratio(3000, 1)
        sqrt_price_ratio = self.get_starting_sqrt_ratio(
            Wad.from_number(3000).value,
            Wad.from_number(1).value)
        current_tick = get_tick_at_sqrt_ratio(sqrt_price_ratio)
        ticks = []
        test_pool = Pool(test_token_1, test_token_2, FEES.MEDIUM.value,
                         sqrt_price_ratio, 0, current_tick, ticks)

        # set Position.from_amounts() params
        tick_lower = current_tick - TICK_SPACING.MEDIUM.value * 5
        tick_upper = current_tick + TICK_SPACING.MEDIUM.value * 7
        rounded_tick_lower = Tick.nearest_usable_tick(
            tick_lower, TICK_SPACING.MEDIUM.value)
        rounded_tick_upper = Tick.nearest_usable_tick(
            tick_upper, TICK_SPACING.MEDIUM.value)
        calculated_position = Position.from_amounts(
            test_pool, rounded_tick_lower, rounded_tick_upper,
            token_1_balance.value, token_2_balance.value, False)

        test_liquidity = calculated_position.liquidity

        test_position = Position(test_pool, rounded_tick_lower,
                                 rounded_tick_upper, test_liquidity)

        amount_0, amount_1 = test_position.mint_amounts()

        slippage_tolerance = Fraction(2, 100)
        amount_0_min, amount_1_min = test_position.mint_amounts_with_slippage(
            slippage_tolerance)

        # check that mint amounts will pass periphery contract assertions
        assert amount_0_min > 0 and amount_1_min > 0
        assert amount_0_min < amount_0 and amount_1_min < amount_1
Пример #4
0
    def exit_gem(self):
        if not self.collateral:
            return

        token = Token(self.collateral.ilk.name.split('-')[0], self.collateral.gem.address, self.collateral.adapter.dec())
        vat_balance = self.vat.gem(self.ilk, self.our_address)
        if vat_balance > token.min_amount:
            self.logger.info(f"Exiting {str(vat_balance)} {self.ilk.name} from the Vat")
            assert self.gem_join.exit(self.our_address, token.unnormalize_amount(vat_balance)).transact(gas_price=self.gas_price)
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='uniswap-market-maker-keeper')
        self.add_arguments(parser=parser)
        self.arguments = parser.parse_args(args)
        setup_logging(self.arguments)

        provider = HTTPProvider(
            endpoint_uri=self.arguments.rpc_host,
            request_kwargs={'timeout': self.arguments.rpc_timeout})
        self.web3: Web3 = kwargs['web3'] if 'web3' in kwargs else Web3(
            provider)

        self.web3.eth.defaultAccount = self.arguments.eth_from
        register_keys(self.web3, self.arguments.eth_key)
        self.our_address = Address(self.arguments.eth_from)

        self.uniswap_router = UniswapRouter(
            web3=self.web3,
            router=Address(self.arguments.uniswap_router_address))

        self.first_token = ERC20Token(web3=self.web3,
                                      address=Address(
                                          self.arguments.first_token_address))
        self.second_token = ERC20Token(
            web3=self.web3,
            address=Address(self.arguments.second_token_address))

        self.token_first = Token(name=self.arguments.first_token_name,
                                 address=Address(
                                     self.arguments.first_token_address),
                                 decimals=self.arguments.first_token_decimals)

        self.token_second = Token(
            name=self.arguments.second_token_name,
            address=Address(self.arguments.second_token_address),
            decimals=self.arguments.second_token_decimals)

        self.min_eth_balance = Wad.from_number(self.arguments.min_eth_balance)

        self.gas_price = GasPriceFactory().create_gas_price(self.arguments)
        self.max_delta_on_percent = self.arguments.max_delta_on_percent

        self.price_feed = PriceFeedFactory().create_price_feed(self.arguments)
Пример #6
0
    def setup_method(self):
        self.web3 = Web3(HTTPProvider("http://localhost:8555"))
        self.web3.eth.defaultAccount = self.web3.eth.accounts[0]
        self.our_address = Address(self.web3.eth.defaultAccount)
        self.token1 = DSToken.deploy(self.web3, 'AAA')
        self.token1_tokenclass = Token('AAA', self.token1.address, 18)
        self.token1.mint(Wad.from_number(10000)).transact()
        self.token2 = DSToken.deploy(self.web3, 'BBB')
        self.token2_tokenclass = Token('BBB', self.token2.address, 6)
        self.token2.mint(Wad.from_number(10000)).transact()

        support_abi = Contract._load_abi(__name__, '../pymaker/abi/MakerOtcSupportMethods.abi')
        support_bin = Contract._load_bin(__name__, '../pymaker/abi/MakerOtcSupportMethods.bin')
        support_address = Contract._deploy(self.web3, support_abi, support_bin, [])

        price_oracle = OasisMockPriceOracle.deploy(self.web3)
        self.otc = MatchingMarket.deploy(self.web3, self.token1.address, Wad(0), price_oracle.address, support_address)
        self.otc.add_token_pair_whitelist(self.token1.address, self.token2.address).transact()
        self.otc.approve([self.token1, self.token2], directly())
Пример #7
0
    def setup_method(self):

        # Use Ganache docker container
        self.web3 = Web3(HTTPProvider("http://0.0.0.0:8555"))
        self.web3.eth.defaultAccount = Web3.toChecksumAddress(
            "0x9596C16D7bF9323265C2F2E22f43e6c80eB3d943")
        register_private_key(
            self.web3,
            "0x91cf2cc3671a365fcbf38010ff97ee31a5b7e674842663c56769e41600696ead"
        )

        self.our_address = Address(self.web3.eth.defaultAccount)

        self.weth_address = self._deploy(self.web3, self.weth_abi,
                                         self.weth_bin, [])
        self.factory_address = self._deploy(self.web3, self.factory_abi,
                                            self.factory_bin,
                                            [self.our_address.address])
        self.router_address = self._deploy(
            self.web3, self.router_abi, self.router_bin,
            [self.factory_address.address, self.weth_address.address])
        self._weth_contract = self._get_contract(self.web3, self.weth_abi,
                                                 self.weth_address)

        self.ds_dai = DSToken.deploy(self.web3, 'DAI')
        self.ds_usdc = DSToken.deploy(self.web3, 'USDC')
        self.token_dai = Token("DAI", self.ds_dai.address, 18)
        self.token_usdc = Token("USDC", self.ds_usdc.address, 6)
        self.token_weth = Token("WETH", self.weth_address, 18)

        self.dai_usdc_uniswap = UniswapV2(self.web3, self.token_dai,
                                          self.token_usdc, self.our_address,
                                          self.router_address,
                                          self.factory_address)
        self.dai_eth_uniswap = UniswapV2(self.web3, self.token_dai,
                                         self.token_weth, self.our_address,
                                         self.router_address,
                                         self.factory_address)

        ## Useful for debugging failing transactions
        logger = logging.getLogger('eth')
        logger.setLevel(8)
Пример #8
0
    def __init__(self, data: dict):
        assert (isinstance(data, dict))

        self.tokens = [
            Token(name=key,
                  address=Address(value['tokenAddress'])
                  if 'tokenAddress' in value else None,
                  decimals=value['tokenDecimals']
                  if 'tokenDecimals' in value else 18)
            for key, value in data['tokens'].items()
        ]
Пример #9
0
    def setup_method(self):
        self.ds_dai = DSToken.deploy(self.web3, 'DAI')
        self.ds_usdc = DSToken.deploy(self.web3, 'USDC')
        self.token_dai = Token("DAI", self.ds_dai.address, 18)
        self.token_usdc = Token("USDC", self.ds_usdc.address, 6)
        self.token_weth = Token("WETH", self.weth_address, 18)

        self.position_manager.approve(self.token_dai)
        self.position_manager.approve(self.token_usdc)
        self.position_manager.approve(self.token_weth)
        self.swap_router.approve(self.token_dai)
        self.swap_router.approve(self.token_usdc)
        self.swap_router.approve(self.token_weth)

        dai_balance = Wad.from_number(10000000)
        usdc_balance = Wad.from_number(10000000)

        self.ds_dai.mint(dai_balance).transact(from_address=self.our_address)
        self.ds_usdc.mint(
            self.token_usdc.unnormalize_amount(usdc_balance)).transact(
                from_address=self.our_address)
Пример #10
0
    def setup_method(self):
        # Use Ganache docker container
        self.web3 = Web3(HTTPProvider("http://0.0.0.0:8555"))
        self.web3.eth.defaultAccount = Web3.toChecksumAddress(
            "0x9596C16D7bF9323265C2F2E22f43e6c80eB3d943")
        self.our_address = Address(self.web3.eth.defaultAccount)

        self.private_key = "0x91cf2cc3671a365fcbf38010ff97ee31a5b7e674842663c56769e41600696ead"
        register_private_key(self.web3, self.private_key)

        self.weth_address = Contract._deploy(self.web3, self.weth_abi,
                                             self.weth_bin, [])
        self.factory_address = Contract._deploy(self.web3, self.factory_abi,
                                                self.factory_bin,
                                                [self.our_address.address])
        self.router_address = Contract._deploy(
            self.web3, self.router_abi, self.router_bin,
            [self.factory_address.address, self.weth_address.address])
        self._weth_contract = Contract._get_contract(self.web3, self.weth_abi,
                                                     self.weth_address)

        self.ds_dai = DSToken.deploy(self.web3, 'DAI')
        self.ds_dai.mint(
            Wad.from_number(500)).transact(from_address=self.our_address)
        self.token_dai = Token("DAI", self.ds_dai.address, 18)
        self.token_weth = Token("WETH", self.weth_address, 18)

        token_config = {
            "tokens": {
                "DAI": {
                    "tokenAddress": self.ds_dai.address.address
                },
                "WETH": {
                    "tokenAddress": self.weth_address.address
                }
            }
        }
        # write token config with locally deployed addresses to file
        with open("test-token-config.json", "w+") as outfile:
            outfile.write(json.dumps(token_config))
Пример #11
0
    def test_liquidity_given_balance(self):
        """ Test liquidity and mint amount calculations """
        test_token_1 = Token(
            "test_1", Address("0x0000000000000000000000000000000000000001"),
            18)
        test_token_2 = Token(
            "test_2", Address("0x0000000000000000000000000000000000000002"), 6)

        token_1_balance = test_token_1.unnormalize_amount(Wad.from_number(10))
        token_2_balance = test_token_2.unnormalize_amount(Wad.from_number(500))

        sqrt_price_ratio = self.get_starting_sqrt_ratio(
            Wad.from_number(1).value,
            test_token_2.unnormalize_amount(Wad.from_number(3000)).value)
        current_tick = get_tick_at_sqrt_ratio(sqrt_price_ratio)
        ticks = []
        test_pool = Pool(test_token_1, test_token_2, FEES.MEDIUM.value,
                         sqrt_price_ratio, 0, current_tick, ticks)

        tick_lower = current_tick - TICK_SPACING.MEDIUM.value * 5
        tick_upper = current_tick + TICK_SPACING.MEDIUM.value * 7
        rounded_tick_lower = Tick.nearest_usable_tick(
            tick_lower, TICK_SPACING.MEDIUM.value)
        rounded_tick_upper = Tick.nearest_usable_tick(
            tick_upper, TICK_SPACING.MEDIUM.value)
        calculated_position = Position.from_amounts(
            test_pool, rounded_tick_lower, rounded_tick_upper,
            token_1_balance.value, token_2_balance.value, False)

        test_liquidity = calculated_position.liquidity
        assert test_liquidity == 252860870269028

        test_position = Position(test_pool, rounded_tick_lower,
                                 rounded_tick_upper, test_liquidity)

        amount_0, amount_1 = test_position.mint_amounts()
        assert amount_0 == 95107120950731527
        assert amount_1 == 208677042
    def instantiate_tokens(self, pair: str) -> Tuple[Token, Token]:
        assert (isinstance(pair, str))

        def get_address(value) -> Address:
            return Address(
                value['tokenAddress']) if 'tokenAddress' in value else None

        def get_decimals(value) -> int:
            return value['tokenDecimals'] if 'tokenDecimals' in value else 18

        token_a_name = 'WETH' if self.is_eth and self.eth_position == 0 else self.pair(
        ).split('-')[0]
        token_b_name = 'WETH' if self.is_eth and self.eth_position == 1 else self.pair(
        ).split('-')[1]

        token_a = Token(token_a_name,
                        get_address(self.token_config[token_a_name]),
                        get_decimals(self.token_config[token_a_name]))
        token_b = Token(token_b_name,
                        get_address(self.token_config[token_b_name]),
                        get_decimals(self.token_config[token_b_name]))

        return token_a, token_b
Пример #13
0
    def setup_method(self):
        # reduce logspew
        logging.getLogger("web3").setLevel(logging.INFO)
        logging.getLogger("urllib3").setLevel(logging.INFO)
        logging.getLogger("asyncio").setLevel(logging.INFO)

        self.web3 = Web3(HTTPProvider("http://localhost:8555"))
        self.web3.eth.defaultAccount = self.web3.eth.accounts[0]
        self.our_address = Address(self.web3.eth.defaultAccount)

        self.price_oracle = OasisMockPriceOracle.deploy(self.web3)
        self.price_oracle.set_price(Wad.from_number(10))

        self.token1 = DSToken.deploy(self.web3, 'AAA')
        self.token1_tokenclass = Token('AAA', self.token1.address, 18)
        self.token1.mint(Wad.from_number(10000)).transact()
        self.token2 = DSToken.deploy(self.web3, 'BBB')
        self.token2_tokenclass = Token('BBB', self.token2.address, 18)
        self.token2.mint(Wad.from_number(10000)).transact()
        self.token3 = DSToken.deploy(self.web3, 'CCC')
        self.token3_tokenclass = Token('CCC', self.token3.address, 18)
        self.token3.mint(Wad.from_number(10000)).transact()
        self.otc = None
Пример #14
0
    def deploy_liquidity_token(self) -> Token:

        # deploy uniswap contracts
        self.weth_address = self._deploy(self.web3, self.weth_abi, self.weth_bin, [])
        self.factory_address = self._deploy(self.web3, self.factory_abi, self.factory_bin, [self.our_address.address])
        self.router_address = self._deploy(self.web3, self.router_abi, self.router_bin, [self.factory_address.address, self.weth_address.address])
        self._weth_contract = self._get_contract(self.web3, self.weth_abi, self.weth_address)

        # deploy dai contract and instantiate DAI token
        self.ds_dai = DSToken.deploy(self.web3, 'DAI')
        self.token_dai = Token("DAI", self.ds_dai.address, 18)
        self.token_weth = Token("WETH", self.weth_address, 18)

        # self.dai_usdc_uniswap = UniswapV2(self.web3, self.token_dai, self.token_usdc, self.our_address, self.router_address, self.factory_address)
        self.dai_eth_uniswap = UniswapV2(self.web3, self.token_dai, self.token_weth, self.our_address, self.router_address, self.factory_address)

        # add liquidity
        self.add_liquidity_eth()

        # set liquidity token
        self.dai_eth_uniswap.set_pair_token(self.dai_eth_uniswap.get_pair_address(self.token_dai.address, self.token_weth.address))
        liquidity_token = self.dai_eth_uniswap.pair_token

        return liquidity_token
Пример #15
0
    def deploy_tokens(self):
        self.ds_dai = DSToken.deploy(self.web3, 'DAI')
        self.ds_keep = DSToken.deploy(self.web3, 'KEEP')
        self.ds_lev = DSToken.deploy(self.web3, 'LEV')
        self.ds_usdc = DSToken.deploy(self.web3, 'USDC')
        self.ds_wbtc = DSToken.deploy(self.web3, 'WBTC')

        self.token_dai = Token("DAI", self.ds_dai.address, 18)
        self.token_keep = Token("KEEP", self.ds_keep.address, 18)
        self.token_lev = Token("LEV", self.ds_lev.address, 9)
        self.token_usdc = Token("USDC", self.ds_usdc.address, 6)
        self.token_wbtc = Token("WBTC", self.ds_wbtc.address, 8)
        self.token_weth = Token("WETH", self.weth_address, 18)
Пример #16
0
    def setup_method(self):

        # Use Ganache docker container
        self.web3 = Web3(HTTPProvider("http://0.0.0.0:8555"))
        self.web3.eth.defaultAccount = Web3.toChecksumAddress("0x9596C16D7bF9323265C2F2E22f43e6c80eB3d943")
        register_private_key(self.web3, "0x91cf2cc3671a365fcbf38010ff97ee31a5b7e674842663c56769e41600696ead")
        self.our_address = Address(self.web3.eth.defaultAccount)

        self.ds_reward_token = DSToken.deploy(self.web3, 'REWARD')
        self.reward_token = Token("REWARD", self.ds_reward_token.address, 18)

        # Deploy UniswapV2 contracts and set liquidity token
        self.liquidity_token = self.deploy_liquidity_token()

        self.staking_rewards_address = self._deploy(self.web3, self.staking_rewards_abi, self.staking_rewards_bin, [self.our_address.address, self.reward_token.address.address, self.liquidity_token.address.address])

        self.uniswap_staking_rewards = UniswapStakingRewards(self.web3, self.our_address, Address(self.staking_rewards_address), "UniswapStakingRewards")

        ## Useful for debugging failing transactions
        logger = logging.getLogger('eth')
        logger.setLevel(8)
    def deploy_staking_rewards(self, liquidity_token_address: Address):
        self.ds_reward_dai = DSToken.deploy(self.web3, 'REWARD_DAI')
        self.reward_token = Token("REWARD_DAI", self.ds_dai.address, 18)

        self.uni_staking_rewards_address = Contract._deploy(self.web3, self.uni_staking_rewards_abi, self.uni_staking_rewards_bin, [self.our_address.address, self.reward_token.address.address, liquidity_token_address.address])
        self.uni_staking_rewards = UniswapStakingRewards(self.web3, self.our_address, Address(self.uni_staking_rewards_address), "UniswapStakingRewards")
Пример #18
0
 def set_pair_token(self, pair_address: Address):
     self.pair_address = pair_address
     self._pair_contract = self._get_contract(self.web3, self.pair_abi['abi'], self.pair_address)
     self.pair_token = Token('Liquidity', self.pair_address, 18)
     self.is_new_pool = False
Пример #19
0
    def test_should_mint_with_nonstandard_decimals(self):
        """ mint a position with one of the tokens having nonstandard decimals.
            Verify that the positions price and minted amounts accounts for decimals.
        """
        test_token_1 = Token(
            "test_1", Address("0x0000000000000000000000000000000000000001"),
            18)
        test_token_2 = Token(
            "test_2", Address("0x0000000000000000000000000000000000000002"), 6)

        # instantiate test pool
        # sqrt_price_ratio = self.get_starting_sqrt_ratio(Wad.from_number(1).value, Wad.from_number(3500).value)
        sqrt_price_ratio = self.get_starting_sqrt_ratio(1, 3500)
        current_tick = get_tick_at_sqrt_ratio(sqrt_price_ratio)
        ticks = []
        test_pool = Pool(test_token_1, test_token_2, FEES.MEDIUM.value,
                         sqrt_price_ratio, 0, current_tick, ticks)

        # based upon current price (expressed in token1/token0), determine the tick to mint the position at
        tick_spacing = TICK_SPACING.MEDIUM.value
        desired_price = PriceFraction(test_token_1, test_token_2, 1, 3500)
        desired_tick = PriceFraction.get_tick_at_price(desired_price)

        # identify upper and lower tick bounds for the position
        desired_lower_tick = Tick.nearest_usable_tick(
            desired_tick - tick_spacing * 5, tick_spacing)
        desired_upper_tick = Tick.nearest_usable_tick(
            desired_tick + tick_spacing * 7, tick_spacing)

        # calculate amount to add for each position.
        ## since test_token_2 has 6 decimals, we must unnormalize the Wad amount from 18 -> 6
        token_1_balance = Wad.from_number(10)
        token_2_balance = Wad.from_number(100)

        token_1_to_add = test_token_1.unnormalize_amount(token_1_balance).value
        token_2_to_add = test_token_2.unnormalize_amount(token_2_balance).value
        # token_1_to_add = token_1_balance.value
        # token_2_to_add = token_2_balance.value

        calculated_position = Position.from_amounts(test_pool,
                                                    desired_lower_tick,
                                                    desired_upper_tick,
                                                    token_1_to_add,
                                                    token_2_to_add, False)

        amount_0, amount_1 = calculated_position.mint_amounts()

        slippage_tolerance = Fraction(2, 100)
        amount_0_min, amount_1_min = calculated_position.mint_amounts_with_slippage(
            slippage_tolerance)

        # check that mint amounts will pass periphery contract assertions
        assert amount_0 > 0 and amount_1 > 0
        assert amount_0_min > 0 and amount_1_min > 0
        assert amount_0_min < amount_0 and amount_1_min < amount_1

        # assume pool.tick_current < desired_upper_tick
        expected_amount_0 = SqrtPriceMath.get_amount_0_delta(
            test_pool.square_root_ratio_x96,
            get_sqrt_ratio_at_tick(desired_upper_tick),
            calculated_position.liquidity, True)
        expected_amount_1 = SqrtPriceMath.get_amount_1_delta(
            get_sqrt_ratio_at_tick(desired_lower_tick),
            test_pool.square_root_ratio_x96, calculated_position.liquidity,
            True)

        assert amount_0 == expected_amount_0
        assert amount_1 == expected_amount_1

        # get amounts from liquidity
        price_lower_tick = pow(1.0001, calculated_position.tick_lower)
        price_upper_tick = pow(1.0001, calculated_position.tick_upper)

        assert price_lower_tick < 3500 < price_upper_tick

        position_token_0 = calculated_position.liquidity / math.sqrt(
            price_upper_tick)
        position_token_1 = calculated_position.liquidity * math.sqrt(
            price_lower_tick)

        # compare original sqrt_price_ratio_x96 to the ratio determined by liquidity to mint
        assert str(sqrt_price_ratio)[:2] == str(
            encodeSqrtRatioX96(int(position_token_1),
                               int(position_token_0)))[:2]
        assert sqrt_price_ratio // Q96 == encodeSqrtRatioX96(
            int(position_token_1), int(position_token_0)) // (2**96)
Пример #20
0
    def __init__(self, args: list, **kwargs):
        parser = argparse.ArgumentParser(prog='oasis-market-maker-keeper')

        parser.add_argument(
            "--endpoint-uri",
            type=str,
            help="JSON-RPC uri (example: `http://localhost:8545`)")

        parser.add_argument(
            "--rpc-host",
            default="localhost",
            type=str,
            help="[DEPRECATED] JSON-RPC host (default: `localhost')")

        parser.add_argument(
            "--rpc-port",
            default=8545,
            type=int,
            help="[DEPRECATED] JSON-RPC port (default: `8545')")

        parser.add_argument("--rpc-timeout",
                            type=int,
                            default=10,
                            help="JSON-RPC timeout (in seconds, default: 10)")

        parser.add_argument(
            "--eth-from",
            type=str,
            required=True,
            help="Ethereum account from which to send transactions")

        parser.add_argument(
            "--eth-key",
            type=str,
            nargs='*',
            help=
            "Ethereum private key(s) to use (e.g. 'key_file=aaa.json,pass_file=aaa.pass')"
        )

        parser.add_argument("--tub-address",
                            type=str,
                            required=False,
                            help="Ethereum address of the Tub contract")

        parser.add_argument("--oasis-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the OasisDEX contract")

        parser.add_argument(
            "--oasis-support-address",
            type=str,
            required=False,
            help="Ethereum address of the OasisDEX support contract")

        parser.add_argument("--buy-token-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the buy token")

        parser.add_argument("--sell-token-address",
                            type=str,
                            required=True,
                            help="Ethereum address of the sell token")

        parser.add_argument("--buy-token-name",
                            type=str,
                            required=True,
                            help="Ethereum address of the buy token")

        parser.add_argument("--sell-token-name",
                            type=str,
                            required=True,
                            help="Ethereum address of the sell token")

        parser.add_argument("--buy-token-decimals",
                            type=int,
                            required=True,
                            help="Ethereum address of the buy token")

        parser.add_argument("--sell-token-decimals",
                            type=int,
                            required=True,
                            help="Ethereum address of the sell token")

        parser.add_argument("--config",
                            type=str,
                            required=True,
                            help="Bands configuration file")

        parser.add_argument("--price-feed",
                            type=str,
                            required=True,
                            help="Source of price feed")

        parser.add_argument(
            "--price-feed-expiry",
            type=int,
            default=120,
            help="Maximum age of the price feed (in seconds, default: 120)")

        parser.add_argument("--spread-feed",
                            type=str,
                            help="Source of spread feed")

        parser.add_argument(
            "--spread-feed-expiry",
            type=int,
            default=3600,
            help="Maximum age of the spread feed (in seconds, default: 3600)")

        parser.add_argument("--control-feed",
                            type=str,
                            help="Source of control feed")

        parser.add_argument(
            "--control-feed-expiry",
            type=int,
            default=86400,
            help="Maximum age of the control feed (in seconds, default: 86400)"
        )

        parser.add_argument("--order-history",
                            type=str,
                            help="Endpoint to report active orders to")

        parser.add_argument(
            "--order-history-every",
            type=int,
            default=30,
            help=
            "Frequency of reporting active orders (in seconds, default: 30)")

        parser.add_argument(
            "--round-places",
            type=int,
            default=2,
            help="Number of decimal places to round order prices to (default=2)"
        )

        parser.add_argument(
            "--min-eth-balance",
            type=float,
            default=0,
            help="Minimum ETH balance below which keeper will cease operation")

        parser.add_argument("--gas-price",
                            type=int,
                            default=0,
                            help="Gas price (in Wei)")

        parser.add_argument(
            "--smart-gas-price",
            dest='smart_gas_price',
            action='store_true',
            help=
            "Use smart gas pricing strategy, based on the ethgasstation.info feed"
        )

        parser.add_argument("--ethgasstation-api-key",
                            type=str,
                            default=None,
                            help="ethgasstation API key")

        parser.add_argument(
            "--refresh-frequency",
            type=int,
            default=10,
            help="Order book refresh frequency (in seconds, default: 10)")

        parser.add_argument("--debug",
                            dest='debug',
                            action='store_true',
                            help="Enable debug output")

        self.arguments = parser.parse_args(args)
        setup_logging(self.arguments)

        if 'web3' in kwargs:
            self.web3 = kwargs['web3']
        elif self.arguments.endpoint_uri:
            self.web3: Web3 = web3_via_http(self.arguments.endpoint_uri,
                                            self.arguments.rpc_timeout)
        else:
            self.logger.warning(
                "Configuring node endpoint by host and port is deprecated; please use --endpoint-uri"
            )
            self.web3 = Web3(
                HTTPProvider(
                    endpoint_uri=
                    f"http://{self.arguments.rpc_host}:{self.arguments.rpc_port}",
                    request_kwargs={"timeout": self.arguments.rpc_timeout}))

        self.web3.eth.defaultAccount = self.arguments.eth_from
        register_keys(self.web3, self.arguments.eth_key)
        self.our_address = Address(self.arguments.eth_from)
        self.otc = MatchingMarket(
            web3=self.web3,
            address=Address(self.arguments.oasis_address),
            support_address=Address(self.arguments.oasis_support_address)
            if self.arguments.oasis_support_address else None)

        tub = Tub(web3=self.web3, address=Address(self.arguments.tub_address)) \
            if self.arguments.tub_address is not None else None

        self.token_buy = ERC20Token(web3=self.web3,
                                    address=Address(
                                        self.arguments.buy_token_address))
        self.token_sell = ERC20Token(web3=self.web3,
                                     address=Address(
                                         self.arguments.sell_token_address))
        self.buy_token = Token(name=self.arguments.buy_token_name,
                               address=Address(
                                   self.arguments.buy_token_address),
                               decimals=self.arguments.buy_token_decimals)
        self.sell_token = Token(name=self.arguments.sell_token_name,
                                address=Address(
                                    self.arguments.sell_token_address),
                                decimals=self.arguments.sell_token_decimals)
        self.min_eth_balance = Wad.from_number(self.arguments.min_eth_balance)
        self.bands_config = ReloadableConfig(self.arguments.config)
        self.gas_price = GasPriceFactory().create_gas_price(
            self.web3, self.arguments)
        self.price_feed = PriceFeedFactory().create_price_feed(
            self.arguments, tub)
        self.spread_feed = create_spread_feed(self.arguments)
        self.control_feed = create_control_feed(self.arguments)
        self.order_history_reporter = create_order_history_reporter(
            self.arguments)

        self.history = History()
        self.order_book_manager = OrderBookManager(
            refresh_frequency=self.arguments.refresh_frequency)
        self.order_book_manager.get_orders_with(lambda: self.our_orders())
        self.order_book_manager.place_orders_with(self.place_order_function)
        self.order_book_manager.cancel_orders_with(self.cancel_order_function)
        self.order_book_manager.enable_history_reporting(
            self.order_history_reporter, self.our_buy_orders,
            self.our_sell_orders)
        self.order_book_manager.start()
Пример #21
0
NonfungiblePositionManager_abi = Contract._load_abi(__name__, '../pyexchange/abi/NonfungiblePositionManager.abi')['abi']

# Uniswap contracts are deployed to the same addresses on every network
position_manager_address = Address("0xC36442b4a4522E871399CD717aBDD847Ab11FE88")
swap_router_address = Address("0xE592427A0AEce92De3Edee1F18E0157C05861564")
factory_address = Address("0x1F98431c8aD98523631AE4a59f267346ea31F984")
ticklens_address = Address("0xbfd8137f7d1516D3ea5cA83523914859ec47F573")
mainnet_weth_address = Address("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
quoter_address = Address("0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6")

DAI_KOVAN_ADDRESS = Address("0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa")
DAI_MAINNET_ADDRESS = Address("0x6B175474E89094C44Da98b954EedeAC495271d0F")
WETH_KOVAN_ADDRESS = Address("0xd0a1e359811322d97991e03f863a0c30c2cf029c")
USDC_KOVAN_ADDRESS = Address("0x198419c5c340e8de47ce4c0e4711a03664d42cb2")

weth_token_kovan = Token("WETH", WETH_KOVAN_ADDRESS, 18)
weth_token_mainnet = Token("WETH", mainnet_weth_address, 18)
dai_token_kovan = Token("DAI", DAI_KOVAN_ADDRESS, 18)
dai_token_mainnet = Token("DAI", DAI_MAINNET_ADDRESS, 18)
usdc_token_kovan = Token("USDC", USDC_KOVAN_ADDRESS, 6)

provider = sys.argv[1]
private_key = sys.argv[2]
account_address = Address(sys.argv[3])

http_provider = HTTPProvider(provider)
web3 = Web3(http_provider)
web3.eth.defaultAccount = Web3.toChecksumAddress(account_address.address)
register_private_key(web3, private_key)

# useful for debugging
Пример #22
0
WETH_KOVAN_ADDRESS = Address("0xd0a1e359811322d97991e03f863a0c30c2cf029c")
DAI_ADDRESS = Address("0x6B175474E89094C44Da98b954EedeAC495271d0F")
DAI_KOVAN_ADDRESS = Address("0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa")
USDC_ADDRESS = Address("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48")
MKR_ADDRESS = Address("0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2")
MKR_KOVAN_ADDRESS = Address("0xAaF64BFCC32d0F15873a02163e7E500671a4ffcD")
FACTORY_ADDRESS = Address("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f")
ROUTER_ADDRESS = Address("0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D")

web3 = Web3(HTTPProvider(sys.argv[1], request_kwargs={"timeout": 600}))
web3.eth.defaultAccount = sys.argv[2]
register_key(web3, sys.argv[3])

Transact.gas_estimate_for_bad_txs = 210000

dai = Token("DAI", DAI_KOVAN_ADDRESS, 18)
weth_kovan = Token("WETH", WETH_KOVAN_ADDRESS, 18)
weth_mainnet = Token("WETH", WETH_ADDRESS, 18)
usdc_kovan = Token("USDC", USDC_KOVAN_ADDRESS, 6)
usdc_mainnet = Token("USDC", USDC_MAINNET_ADDRESS, 6)

wbtc = Token('WBTC', Address("0xe0c9275e44ea80ef17579d33c55136b7da269aeb"), 8)
uniswap = UniswapV2(web3, dai, weth_kovan)

dai_weth_pair = Token(
    "POOL", uniswap.get_pair_address(DAI_KOVAN_ADDRESS, WETH_KOVAN_ADDRESS),
    18)
# uniswap.approve(wbtc, web3.toWei(5, 'ether'))
# uniswap.approve(weth, web3.toWei(5, 'ether'))

# amounts_in = uniswap.get_amounts_in(web3.toWei(0.5, 'ether'), [DAI_KOVAN_ADDRESS.address, MKR_KOVAN_ADDRESS.address])
Пример #23
0
 def setup_class(self):
     self.token = Token(
         "COW", Address('0xbeef00000000000000000000000000000000BEEF'), 4)
logging.basicConfig(format='%(asctime)-15s %(levelname)-8s %(message)s', level=logging.DEBUG)
# reduce logspew
logging.getLogger('urllib3').setLevel(logging.INFO)
logging.getLogger("web3").setLevel(logging.INFO)
logging.getLogger("asyncio").setLevel(logging.INFO)
logging.getLogger("requests").setLevel(logging.INFO)

# Usage:
# python3 tests/manual_test_create_unsafe_vault [ADDRESS] [KEY] [COLLATERAL_TYPE]

mcd = DssDeployment.from_node(web3)
our_address = Address(web3.eth.defaultAccount)
collateral = mcd.collaterals[str(sys.argv[3])] if len(sys.argv) > 3 else mcd.collaterals['ETH-A']
ilk = mcd.vat.ilk(collateral.ilk.name)
token = Token(collateral.gem.symbol(), collateral.gem.address, collateral.adapter.dec())
urn = mcd.vat.urn(collateral.ilk, our_address)
# mcd.approve_dai(our_address)                  # Uncomment upon first execution for the account
# Transact.gas_estimate_for_bad_txs = 20000     # Uncomment to debug transaction failures onchain
# mcd.spotter.poke(ilk).transact()              # Uncomment if the Kovan spot price is out-of-sync
osm_price = collateral.pip.peek()
action = sys.argv[4] if len(sys.argv) > 4 else "create"


def r(value, decimals=1):
    return round(float(value), decimals)


logging.info(f"{ilk.name:<6}: dust={r(ilk.dust)} osm_price={r(osm_price)} mat={r(mcd.spotter.mat(ilk))} spot={r(ilk.spot)} ")
logging.info(f"{'':<7} duty={mcd.jug.duty(ilk)} min_amount={token.min_amount}")
Пример #25
0
 def get_token(self, symbol):
     decimal = self.tokens[symbol].get(
         'tokenDecimals') if self.tokens[symbol].get(
             'tokenDecimals') else 18
     return Token(symbol, Address(self.tokens[symbol]['tokenAddress']),
                  decimal)