def main():
    migrator = None
    bridge_connector = None
    rewards_liquidator = None
    migration_executor_addr = None

    if c.wh_migrator_addr is None:
        log.nb('Wormhole migration components are not yet deployed')
        if c.get_is_live():
            warn_live()
            return
        executor = accounts[0]
        (bridge_connector, rewards_liquidator,
         migrator) = deploy_wormhole_migration_components(
             executor, {'from': executor})
        migration_executor_addr = executor.address
    else:
        log.ok('Wormhole migration components are already deployed')
        migrator = AnchorVaultMigrator.at(c.wh_migrator_addr)
        bridge_connector = BridgeConnectorWormhole.at(c.bridge_connector_addr)
        rewards_liquidator = RewardsLiquidator.at(c.rewards_liquidator_addr)
        migration_executor_addr = c.wh_migration_executor_addr

    vault = Contract.from_abi('AnchorVault', c.vault_proxy_addr,
                              AnchorVault.abi)

    log.ok('AnchorVaultMigrator', migrator.address)
    assert_equals('  executor', migrator.executor(), migration_executor_addr)
    assert_equals('  state', migrator.state(), 0)
    assert_equals('  pre_migration_admin', migrator.pre_migration_admin(),
                  vault.admin())

    if c.get_is_live():
        warn_live()
        return

    with chain_snapshot():
        executor = accounts.at(migration_executor_addr, force=True)

        migrate_wormhole(migrator, executor, bridge_connector,
                         rewards_liquidator)

        check_vault(
            vault_proxy_addr=c.vault_proxy_addr,
            vault_impl_addr=c.vault_impl_addr,
            beth_token_addr=c.beth_token_addr,
            bridge_connector_addr=bridge_connector.address,
            rewards_liquidator_addr=rewards_liquidator.address,
            insurance_connector_addr=c.insurance_connector_addr,
            terra_rewards_distributor_addr=c.terra_rewards_distributor_addr,
            vault_admin=c.dev_multisig_addr,
            vault_liquidations_admin=c.vault_liquidations_admin_addr,
            rew_liq_max_steth_eth_price_difference_percent=c.
            rew_liq_max_steth_eth_price_difference_percent,
            rew_liq_max_eth_usdc_price_difference_percent=c.
            rew_liq_max_eth_usdc_price_difference_percent,
            rew_liq_max_usdc_ust_price_difference_percent=c.
            rew_liq_max_usdc_ust_price_difference_percent,
            rew_liq_max_steth_ust_price_difference_percent=c.
            rew_liq_max_steth_ust_price_difference_percent)
Beispiel #2
0
    def push(self):
        """Push todo to gist.github.com"""
        github = Github()
        gist_id = GistId().get()
        token = GithubToken().get()

        github.login(token)

        if not self.todo.name:
            name = "Todo"
        else:
            name = self.todo.name

        files = {
            name: {
                "content": self.todo_content
            }
        }

        log.info(
            "Pushing '%s' to https://gist.github.com/%s .." % (name, gist_id)
        )
        response = github.edit_gist(gist_id, files=files)

        if response.status_code == 200:
            log.ok("Pushed success.")
        elif response.status_code == 401:
            log.warning("Github token out of date, empty the old token")
            GithubToken().save('')  # empty the token!
            self.push()  # and repush
        else:
            log.error("Pushed failed. %d" % response.status_code)
Beispiel #3
0
    def get(self):
        """
          call this method to get a token::

            token = GithubToken().get()

          what the get() does:
            1) read from "~/.todo/token"
            2) check if the token read is empty.
               (yes)-> 1) if empty,
                          ask user for user&passwd to access api.github.com
                        2) fetch the token, set to this instance and store it.
            3) return the token (a string)
        """
        if self.is_empty:
            user = ask_input.text("Github user:"******"Password for %s:" % user)

            log.info("Authorize to github.com..")
            response = Github().authorize(user, password)

            if response.status_code == 201:
                # 201 created
                log.ok("Authorized success.")
                # get token from dict
                token = response.json()["token"]
                self.save(token)
            else:
                log.error("Authorization failed. %d" % response.status_code)
        return self.content
Beispiel #4
0
def deploy_wormhole_migration_components(executor, tx_params):
    log.h('Deploying Wormhole migration components...')

    bridge_connector = BridgeConnectorWormhole.deploy(c.wormhole_token_bridge_addr, tx_params)
    log.ok('BridgeConnectorWormhole', bridge_connector.address)

    print()
    rewards_liquidator = RewardsLiquidator.deploy(
        c.vault_proxy_addr,
        c.dev_multisig_addr,
        int(c.rew_liq_max_steth_eth_price_difference_percent * 10**18 / 100),
        int(c.rew_liq_max_eth_usdc_price_difference_percent * 10**18 / 100),
        int(c.rew_liq_max_usdc_ust_price_difference_percent * 10**18 / 100),
        int(c.rew_liq_max_steth_ust_price_difference_percent * 10**18 / 100),
        tx_params
    )
    log.ok('RewardsLiquidator', rewards_liquidator.address)

    print()
    migrator = AnchorVaultMigrator.deploy(
        rewards_liquidator,
        bridge_connector,
        tx_params
    )
    log.ok('AnchorVaultMigrator', migrator.address)

    vault = Contract.from_abi('AnchorVault', c.vault_proxy_addr, AnchorVault.abi)

    assert_equals('  executor', migrator.executor(), executor.address)
    assert_equals('  state', migrator.state(), 0)
    assert_equals('  pre_migration_admin', migrator.pre_migration_admin(), vault.admin())

    return (bridge_connector, rewards_liquidator, migrator)
Beispiel #5
0
    def pull(self, name=None):
        """Pull todo from remote gist server"""

        if not name:  # if not name figured out
            if self.todo.name:
                name = self.todo.name  # use the todo.txt's name
            else:
                log.error("Please tell me todo's name to pull.")

        github = Github()
        gist_id = GistId().get()

        resp = github.get_gist(gist_id)

        if resp.status_code != 200:
            log.error("Pull failed.%d" % resp.status_code)

        dct = resp.json()  # get out the data

        u_name = name.decode("utf8")  # decode to unicode

        # Note that data back from github.com is unicode
        if u_name not in dct["files"]:
            log.error("File '%s' not in gist: %s" % (name, gist_id))

        u_url = dct["files"][u_name]["raw_url"]
        url = u_url.encode("utf8")

        response = requests.get(url)

        if response.status_code == 200:
            todo_content = response.text.encode("utf8")
            self.todo_txt.write(todo_content)
            log.ok("Pulled success to file '%s'" % self.todo_txt.path)
        else:
            log.error("Failed to pull file from %s" % url)
Beispiel #6
0
def run(browser, account, is_first=True):
    log.status("Total points: {}".format(browser.execute_script("""
        return document.getElementsByClassName("points_count")[0].innerHTML;
    """)))
    sleep(5)
    if is_first:
        log.status("Opening facebook post like page...")
        browser.execute_script("""
            document.querySelector("a[href='/free_points/facebook_post_like']").click();
            """)

        log.ok("Done.")
        sleep(5)

    window_before = browser.window_handles[0]

    try:
        browser.execute_script("""
            document.querySelector(".single_like_button").click();
            """)
    except:
        browser.execute_script("""
        location.reload(); 
        """)
        run(browser, account, is_first)

    window_after = browser.window_handles[1]
    browser.switch_to_window(window_after)

    if is_first:
        try:
            browser.execute_script("""
                    var btns = document.getElementById("mobile_login_bar").getElementsByTagName("a");
                    if (btns[0].innerHTML == "Log In") {
                        btns[0].click();
                    } else {
                        btns[1].click();
                    }
                    """)
            sleep(2)
            browser.execute_script("""
                    document.getElementById("m_login_email").value = "{}";
                    document.getElementById("m_login_password").value = "{}";
                    document.querySelector("button[value='Log In']").click();
                    """.format(account["email"], account["password"]))
            sleep(3)
        except:
            browser.close()
            browser.switch_to_window(window_before)
            run(browser, account, is_first=True)

    try:
        browser.execute_script("""
            document.querySelector("a[data-sigil*='like-reaction-flyout']").click()
            """)
    except:
        pass
    sleep(5)

    browser.close()
    browser.switch_to_window(window_before)
    run(browser, account, is_first=False)
Beispiel #7
0
    def get(self, answer=None):  # add answer to figure which approach to go
        """
        call this method to get a gist_id::
            gist_id = GistId().get()
        what the get() dose:
          1) read the gist_id from file "~/.todo/gist_id"
          2) check if the gist_id if empty
             (yes)-> 1) if the gist_id is empty, ask user to input it or
                     new a gist directly.
                     2) save the new gist_id
          3) return the gist_id
        """

        if self.is_empty:
            print "Tell me the gist's id you want to push to:"
            print " 1. New a gist right now."
            print " 2. Let me input a gist's id."
            if answer is None:
                answer = ask_input.text("Input your answer(1/2):")
            if answer == '2':
                self.save(ask_input.text("Gist id:"))
            elif answer == '1':
                # new a gist
                todo_content = TodoTxt().read()
                todo = parser.parse(todo_content)
                if not todo.name:
                    name = "Todo"
                else:
                    name = todo.name

                files = {
                    name: {
                        "content": todo_content
                    }
                }

                resp = None

                github = Github()
                token = GithubToken().get()
                github.login(token)  # need to login
                log.info("Create a new gist..")
                resp = github.create_gist(files=files, description="Todo")

                if resp.status_code == 201:
                    dct = resp.json()
                    html_url = dct["html_url"].encode("utf8")
                    log.ok("Create success:%s ,"
                           "pushed at file '%s'" % (html_url, name))
                    self.save(dct["id"])
                    sys.exit()
                elif resp.status_code == 401:
                    log.warning("Github access denied, empty the old token")
                    GithubToken().save('')  # empty the token!
                    # and re create
                    self.get(answer='1')
                else:
                    log.error("Create gist failed. %d" % resp.status_code)
            else:  # exit if else input
                log.error("Invalid answer.")
        return self.content
def check_vault(vault_proxy_addr, vault_impl_addr, beth_token_addr,
                bridge_connector_addr, rewards_liquidator_addr,
                insurance_connector_addr, terra_rewards_distributor_addr,
                vault_admin, vault_liquidations_admin,
                rew_liq_max_steth_eth_price_difference_percent,
                rew_liq_max_eth_usdc_price_difference_percent,
                rew_liq_max_usdc_ust_price_difference_percent,
                rew_liq_max_steth_ust_price_difference_percent):
    # Needed to properly decode LogMessagePublished events of Wormhole bridge
    wormhole = interface.Wormhole(c.wormhole_addr)

    vault_proxy = AnchorVaultProxy.at(vault_proxy_addr)
    vault_impl = AnchorVault.at(vault_impl_addr)
    vault = Contract.from_abi('AnchorVault', vault_proxy.address,
                              AnchorVault.abi)
    beth_token = bEth.at(beth_token_addr)
    ust_token = interface.WormholeWrappedToken(c.ust_token_addr)
    steth_token = interface.Lido(c.steth_token_addr)

    bridge_connector = BridgeConnectorWormhole.at(bridge_connector_addr)
    rewards_liquidator = RewardsLiquidator.at(rewards_liquidator_addr)
    insurance_connector = InsuranceConnector.at(insurance_connector_addr)

    terra_rewards_distributor_wh_encoded_addr = wh.encode_addr(
        terra_rewards_distributor_addr)

    log.ok('vault admin', vault_admin)

    print()

    log.ok('stETH', steth_token.address)
    log.ok('UST', ust_token.address)

    print()

    log.ok('bETH', beth_token.address)
    assert_equals('  admin', beth_token.admin(), vault_admin)
    assert_equals('  minter', beth_token.minter(), vault_proxy)
    # assert_equals('  totalSupply', beth_token.totalSupply(), 0)
    assert_equals('  name', beth_token.name(), 'bETH')
    assert_equals('  symbol', beth_token.symbol(), 'bETH')
    assert_equals('  decimals', beth_token.decimals(), 18)

    print()

    log.ok('AnchorVault impl', vault_impl.address)

    assert_equals('  admin', vault_impl.admin(), ZERO_ADDRESS)
    assert_equals('  bridge_connector', vault_impl.bridge_connector(),
                  ZERO_ADDRESS)
    assert_equals('  rewards_liquidator', vault_impl.rewards_liquidator(),
                  ZERO_ADDRESS)
    assert_equals('  insurance_connector', vault_impl.insurance_connector(),
                  ZERO_ADDRESS)

    print()

    no_liquidation_interval = 0
    restricted_liquidation_interval = 26 * 60 * 60

    log.ok('AnchorVaultProxy', vault_proxy.address)
    assert_equals('  proxy_getAdmin', vault_proxy.proxy_getAdmin(),
                  vault_admin)
    assert_equals('  proxy_getIsOssified', vault_proxy.proxy_getIsOssified(),
                  False)
    assert_equals('  implementation', vault_proxy.implementation(), vault_impl)
    assert_equals('  admin', vault.admin(), vault_admin)
    assert_equals('  beth_token', vault.beth_token(), beth_token.address)
    assert_equals('  steth_token', vault.steth_token(), steth_token.address)
    assert_equals('  bridge_connector', vault.bridge_connector(),
                  bridge_connector.address)
    assert_equals('  rewards_liquidator', vault.rewards_liquidator(),
                  rewards_liquidator.address)
    assert_equals('  insurance_connector', vault.insurance_connector(),
                  insurance_connector.address)
    assert_equals('  vault_liquidations_admin', vault.liquidations_admin(),
                  vault_liquidations_admin)
    assert_equals('  no_liquidation_interval', vault.no_liquidation_interval(),
                  no_liquidation_interval)
    assert_equals('  restricted_liquidation_interval',
                  vault.restricted_liquidation_interval(),
                  restricted_liquidation_interval)
    assert_equals('  anchor_rewards_distributor',
                  vault.anchor_rewards_distributor(),
                  terra_rewards_distributor_wh_encoded_addr)
    assert_equals('  get_rate', vault.get_rate(), 10**18)

    print()

    log.ok('BridgeConnectorWormhole', bridge_connector.address)
    assert_equals('  wormhole_token_bridge',
                  bridge_connector.wormhole_token_bridge(),
                  c.wormhole_token_bridge_addr)

    print()

    log.ok('RewardsLiquidator', rewards_liquidator.address)
    assert_equals('  admin', rewards_liquidator.admin(), vault_admin)
    assert_equals('  vault', rewards_liquidator.vault(), vault_proxy.address)
    assert_equals(
        '  max_steth_eth_price_difference_percent',
        rewards_liquidator.max_steth_eth_price_difference_percent(),
        int(rew_liq_max_steth_eth_price_difference_percent * 10**18 / 100))
    assert_equals(
        '  max_eth_usdc_price_difference_percent',
        rewards_liquidator.max_eth_usdc_price_difference_percent(),
        int(rew_liq_max_eth_usdc_price_difference_percent * 10**18 / 100))
    assert_equals(
        '  max_usdc_ust_price_difference_percent',
        rewards_liquidator.max_usdc_ust_price_difference_percent(),
        int(rew_liq_max_usdc_ust_price_difference_percent * 10**18 / 100))
    assert_equals(
        '  max_steth_ust_price_difference_percent',
        rewards_liquidator.max_steth_ust_price_difference_percent(),
        int(rew_liq_max_steth_ust_price_difference_percent * 10**18 / 100))

    print()

    log.ok('InsuranceConnector', insurance_connector.address)

    print()

    log.ok('liquidations admin', vault_liquidations_admin)
    log.ok(
        'no liquidation interval',
        f'{no_liquidation_interval} sec ({no_liquidation_interval / 3600} hrs)'
    )
    log.ok(
        'restricted liquidation interval',
        f'{restricted_liquidation_interval} sec ({restricted_liquidation_interval / 3600} hrs)'
    )
    log.ok('terra rewards distributor',
           terra_rewards_distributor_wh_encoded_addr)

    print()

    if c.get_is_live():
        print('Running on a live network, cannot run further checks.')
        print('Run on a mainnet fork to do this.')
        return

    log.h('Performing AnchorVault fork checks')

    with chain_snapshot():
        if not vault.can_deposit_or_withdraw():
            log.h('Selling rewards...')
            tx = vault.collect_rewards(
                {'from': accounts.at(vault_liquidations_admin, force=True)})
            # tx.info()
            assert_equals('AnchorVault.can_deposit_or_withdraw',
                          vault.can_deposit_or_withdraw(), True)

        beth_supply_before = beth_token.totalSupply()
        bridge_balance_before = beth_token.balanceOf(
            c.wormhole_token_bridge_addr)

        log.ok('bETH total supply', beth_supply_before)
        log.ok('bridge bETH balance', bridge_balance_before)

        log.h('Obtaining stETH...')

        holder_1 = accounts[0]
        holder_2 = accounts[1]

        steth_token.submit(ZERO_ADDRESS, {
            'from': holder_1,
            'value': 3 * 10**18
        })
        assert steth_token.balanceOf(holder_1) > 0

        log.ok('holder_1 balance', steth_token.balanceOf(holder_1))
        assert_equals('holder_2 balance', steth_token.balanceOf(holder_2), 0)

        log.h('Submitting stETH...')

        terra_recipient_1 = '0x0000000000000000000000008badf00d8badf00d8badf00d8badf00d8badf00d'
        steth_token.approve(vault, 2 * 10**18, {'from': holder_1})
        tx = vault.submit(2 * 10**18, terra_recipient_1, b'', vault.version(),
                          {'from': holder_1})
        # tx.info()

        assert 'Deposited' in tx.events
        assert tx.events['Deposited'][0].address == vault.address
        log.ok('Deposited event emitted')

        deposited_amount = tx.events['Deposited']['amount']
        assert deposited_amount >= 1.999 * 10**18 and deposited_amount <= 2 * 10**18
        log.ok('Deposited.amount', deposited_amount)

        assert_equals('holder_1 balance', beth_token.balanceOf(holder_1), 0)

        beth_supply = beth_token.totalSupply()
        assert beth_supply == beth_supply_before + deposited_amount
        assert_equals('bETH total supply', beth_supply,
                      beth_supply_before + deposited_amount)

        bridge_balance = beth_token.balanceOf(c.wormhole_token_bridge_addr)
        assert bridge_balance == bridge_balance_before + deposited_amount
        assert_equals('bridge bETH balance', bridge_balance,
                      bridge_balance_before + deposited_amount)

        assert 'LogMessagePublished' in tx.events
        assert tx.events['LogMessagePublished'][0].address == c.wormhole_addr
        log.ok('LogMessagePublished event emitted')

        expected_payload = wh.assemble_transfer_payload(
            token_address=beth_token.address,
            normalized_amount=wh.normalize_amount(deposited_amount, 18),
            to_address=terra_recipient_1,
            token_chain_id=wh.CHAIN_ID_ETHERUM,
            to_chain_id=wh.CHAIN_ID_TERRA,
            fee=0)

        assert tx.events['LogMessagePublished'][0][
            'payload'] == expected_payload
        log.ok('LogMessagePublished.payload', expected_payload)

        log.h('Submitting ETH...')

        bridge_balance_before = bridge_balance
        beth_supply_before = beth_supply

        terra_recipient_2 = '0x000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef'
        tx = vault.submit(1 * 10**18, terra_recipient_2, b'', vault.version(),
                          {
                              'from': holder_2,
                              'value': 1 * 10**18
                          })
        # tx.info()

        assert 'Deposited' in tx.events
        assert tx.events['Deposited'][0].address == vault.address
        log.ok('Deposited event emitted')

        deposited_amount = tx.events['Deposited']['amount']
        assert deposited_amount >= 0.999 * 10**18 and deposited_amount <= 1 * 10**18
        log.ok('Deposited.amount', deposited_amount)

        assert_equals('holder_2 balance', beth_token.balanceOf(holder_2), 0)

        beth_supply = beth_token.totalSupply()
        assert beth_supply == beth_supply_before + deposited_amount
        assert_equals('bETH total supply', beth_supply,
                      beth_supply_before + deposited_amount)

        bridge_balance = beth_token.balanceOf(c.wormhole_token_bridge_addr)
        assert bridge_balance == bridge_balance_before + deposited_amount
        assert_equals('bridge bETH balance', bridge_balance,
                      bridge_balance_before + deposited_amount)

        assert 'LogMessagePublished' in tx.events
        assert tx.events['LogMessagePublished'][0].address == c.wormhole_addr
        log.ok('LogMessagePublished event emitted')

        expected_payload = wh.assemble_transfer_payload(
            token_address=beth_token.address,
            normalized_amount=wh.normalize_amount(deposited_amount, 18),
            to_address=terra_recipient_2,
            token_chain_id=wh.CHAIN_ID_ETHERUM,
            to_chain_id=wh.CHAIN_ID_TERRA,
            fee=0)

        assert tx.events['LogMessagePublished'][0][
            'payload'] == expected_payload
        log.ok('LogMessagePublished.payload', expected_payload)

        log.h('Rebasing stETH by 0.02%...')

        lido_oracle_report(steth_rebase_percent=0.02)
        assert_equals('AnchorVault.can_deposit_or_withdraw',
                      vault.can_deposit_or_withdraw(), False)

        log.h('Selling rewards...')

        liquidations_admin = accounts.at(vault.liquidations_admin(),
                                         force=True)
        tx = vault.collect_rewards({'from': liquidations_admin})
        # tx.info()

        assert 'RewardsCollected' in tx.events
        assert tx.events['RewardsCollected'][0].address == vault.address
        log.ok('RewardsCollected event emitted')

        ust_amount = tx.events['RewardsCollected'][0]['ust_amount']
        assert ust_amount > 0
        log.ok('RewardsCollected.ust_amount', ust_amount)

        assert 'LogMessagePublished' in tx.events
        assert tx.events['LogMessagePublished'][0].address == c.wormhole_addr
        log.ok('LogMessagePublished event emitted')

        expected_payload = wh.assemble_transfer_payload(
            # See https://github.com/certusone/wormhole/blob/aff369f/ethereum/contracts/bridge/Bridge.sol#L97-L103
            # For wrapped tokens, the "token address" field is set to the address of the token on its native chain
            token_address=str(ust_token.nativeContract()),
            normalized_amount=wh.normalize_amount(ust_amount,
                                                  ust_token.decimals()),
            to_address=terra_rewards_distributor_addr,
            token_chain_id=ust_token.chainId(),
            to_chain_id=wh.CHAIN_ID_TERRA,
            fee=0)

        assert tx.events['LogMessagePublished'][0][
            'payload'] == expected_payload
        log.ok('LogMessagePublished.payload', expected_payload)