예제 #1
0
def cleanup_safe(geb: GfDeployment, collateral: Collateral, address: Address):
    assert isinstance(geb, GfDeployment)
    assert isinstance(collateral, Collateral)
    assert isinstance(address, Address)
    safe = geb.safe_engine.safe(collateral.collateral_type, address)
    collateral_type = geb.safe_engine.collateral_type(
        collateral.collateral_type.name)

    # If tax_collector.tax_single has been called, we won't have sufficient system_coin to repay the SAFE
    #if collateral_type.accumulated_rate > Ray.from_number(1):
    #    return

    # Return if this address doens't have enough system to coin to repay full debt
    amount_to_raise = Wad(
        Ray(safe.generated_debt) * collateral_type.accumulated_rate)
    if amount_to_raise > geb.system_coin.balance_of(address):
        return

    # Repay borrowed system coin
    geb.approve_system_coin(address)

    # Put all the user's system coin back into the safe engine
    if geb.system_coin.balance_of(address) >= Wad(0):
        assert geb.system_coin_adapter.join(
            address,
            geb.system_coin.balance_of(address)).transact(from_address=address)

    amount_to_raise = Wad(
        Ray(safe.generated_debt) * collateral_type.accumulated_rate)

    print(
        f'amount_to_raise={str(amount_to_raise)}, rate={str(collateral_type.accumulated_rate)}, system_coin={str(geb.safe_engine.coin_balance(address))}'
    )
    if safe.generated_debt > Wad(0):
        wrap_modify_safe_collateralization(geb, collateral, address, Wad(0),
                                           amount_to_raise * -1)

    # Withdraw collateral
    collateral.approve(address)
    safe = geb.safe_engine.safe(collateral.collateral_type, address)
    # delta_collateral = Wad((Ray(safe.generated_debt) * collateral_type.accumulated_rate) / collateral_type.safety_price)
    # print(f'delta_collateral={str(delta_collateral)}, locked_collateral={str(safe.locked_collateral)}')
    if safe.generated_debt == Wad(0) and safe.locked_collateral > Wad(0):
        wrap_modify_safe_collateralization(geb, collateral, address,
                                           safe.locked_collateral * -1, Wad(0))

    assert collateral.adapter.exit(
        address,
        geb.safe_engine.token_collateral(
            collateral.collateral_type,
            address)).transact(from_address=address)
    TestSAFEEngine.ensure_clean_safe(geb, collateral, address)
예제 #2
0
def geb(web3) -> GfDeployment:
    # for local dockerized parity testchain
    deployment = GfDeployment.from_node(web3=web3, system_coin='rai')
    validate_contracts_loaded(deployment)
    return deployment
예제 #3
0
new_collateral_amount = Wad.from_number(sys.argv[1])
new_debt_amount = Wad.from_number(sys.argv[2])

ETH_RPC_URL = os.environ['ETH_RPC_URL']

web3 = Web3(
    HTTPProvider(endpoint_uri=ETH_RPC_URL, request_kwargs={"timeout": 60}))
while web3.eth.syncing:
    print("Node is syncing")
    time.sleep(5)

print(f"Current block number: {web3.eth.blockNumber}")
web3.eth.defaultAccount = os.environ['ETH_ACCOUNT']
register_keys(web3, [os.environ['ETH_KEYPASS']])

geb = GfDeployment.from_node(web3, 'rai')
our_address = Address(web3.eth.defaultAccount)

collateral = geb.collaterals['ETH-A']
collateral_type = geb.safe_engine.collateral_type(
    collateral.collateral_type.name)

# Get SAFE status before modification
safe = geb.safe_engine.safe(collateral_type, our_address)
if safe.generated_debt > Wad(0):
    coll_ratio = (safe.locked_collateral * collateral_type.liquidation_price *
                  geb.oracle_relayer.liquidation_c_ratio(collateral_type)) / (
                      safe.generated_debt *
                      collateral_type.accumulated_rate) * 100
else:
    coll_ratio = 0
예제 #4
0
from pyflex.keys import register_keys
from pyflex.numeric import Wad

web3 = Web3(
    HTTPProvider(endpoint_uri=os.environ['ETH_RPC_URL'],
                 request_kwargs={"timeout": 10}))
web3.eth.defaultAccount = sys.argv[
    1]  # ex: 0x0000000000000000000000000000000aBcdef123
if len(sys.argv) > 2:
    register_keys(
        web3, [sys.argv[2]]
    )  # ex: key_file=~keys/default-account.json,pass_file=~keys/default-account.pass
    run_transactions = True
else:
    run_transactions = False
geb = GfDeployment.from_node(web3)
our_address = Address(web3.eth.defaultAccount)

# Choose the desired collateral; in this case we'll wrap some Eth
collateral = geb.collaterals['ETH-A']
collateral_type = collateral.collateral_type

# Set an amount of collateral to join and an amount of system coin to draw
collateral_amount = Wad.from_number(0.2)
system_coin_amount = Wad.from_number(20.0)

if collateral.collateral.balance_of(our_address) > collateral_amount:
    if run_transactions and collateral.collateral_type.name.startswith("ETH"):
        # Wrap ETH to produce WETH
        assert collateral.collateral.deposit(collateral_amount).transact()
예제 #5
0
 def test_from_node(self, web3: Web3):
     geb_testnet = GfDeployment.from_node(web3, 'rai')
     validate_contracts_loaded(geb_testnet)
예제 #6
0
 def test_to_json(self, web3: Web3, geb: GfDeployment):
     config_out = geb.to_json()
     dict = json.loads(config_out)
     assert "GEB_PROT" in dict
     assert "GEB_COIN" in dict
     assert len(dict) > 20
예제 #7
0
    def __init__(self, args: list, **kwargs):
        """Pass in arguements assign necessary variables/objects and instantiate other Classes"""

        parser = argparse.ArgumentParser("settlement-keeper")

        parser.add_argument(
            "--rpc-uri",
            type=str,
            default="http://localhost:8545",
            help="JSON-RPC host (default: `http://localhost:8545')")

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

        parser.add_argument(
            "--network",
            type=str,
            required=True,
            help=
            "Network that you're running the Keeper on (options, 'mainnet', 'kovan', 'testnet')"
        )

        parser.add_argument(
            '--previous-settlement',
            dest='settlement_facilitated',
            action='store_true',
            help=
            'Include this argument if this keeper previously helped to facilitate the processing phase of ES'
        )

        parser.add_argument(
            "--graph-endpoint",
            type=str,
            default=None,
            help=
            "When specified, safe history will be initialized from a Graph node, "
            "reducing load on the Ethereum node for collateral auctions")

        parser.add_argument(
            "--eth-from",
            type=str,
            required=True,
            help=
            "Ethereum address from which to send transactions; checksummed (e.g. '0x12AebC')"
        )

        parser.add_argument(
            "--eth-key",
            type=str,
            nargs='*',
            help=
            "Ethereum private key(s) to use (e.g. 'key_file=/path/to/keystore.json,pass_file=/path/to/passphrase.txt')"
        )

        parser.add_argument(
            "--gf-deployment-file",
            type=str,
            required=False,
            help=
            "Json description of all the system addresses (e.g. /Full/Path/To/configFile.json)"
        )

        parser.add_argument(
            "--safe-engine-deployment-block",
            type=int,
            required=False,
            default=0,
            help=
            "Block that the SAFEEngine from gf-deployment-file was deployed at (e.g. 8836668"
        )

        parser.add_argument(
            "--max-errors",
            type=int,
            default=100,
            help=
            "Maximum number of allowed errors before the keeper terminates (default: 100)"
        )

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

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

        parser.add_argument("--gas-initial-multiplier",
                            type=str,
                            default=1.0,
                            help="gas strategy tuning")
        parser.add_argument("--gas-reactive-multiplier",
                            type=str,
                            default=2.25,
                            help="gas strategy tuning")
        parser.add_argument("--gas-maximum",
                            type=str,
                            default=5000,
                            help="gas strategy tuning")

        parser.set_defaults(settlement_facilitated=False)
        self.arguments = parser.parse_args(args)

        self.web3 = kwargs['web3'] if 'web3' in kwargs else \
                Web3(HTTPProvider(endpoint_uri=self.arguments.rpc_uri,
                                  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)

        if self.arguments.gf_deployment_file:
            self.geb = GfDeployment.from_json(
                web3=self.web3,
                conf=open(self.arguments.gf_deployment_file, "r").read())
        else:
            self.geb = GfDeployment.from_network(
                web3=self.web3, network=self.arguments.network)

        self.deployment_block = self.arguments.safe_engine_deployment_block

        self.max_errors = self.arguments.max_errors
        self.errors = 0

        self.settlement_facilitated = self.arguments.settlement_facilitated

        self.confirmations = 0

        # Create gas strategy
        if self.arguments.ethgasstation_api_key:
            self.gas_price = DynamicGasPrice(self.arguments, self.web3)
        else:
            self.gas_price = DefaultGasPrice()

        logging.basicConfig(
            format='%(asctime)-15s %(levelname)-8s %(message)s',
            level=(logging.DEBUG if self.arguments.debug else logging.INFO))
from pyflex.deployment import GfDeployment
from pyflex.keys import register_keys
from pyflex.numeric import Wad
from pyflex.proxy import DSProxy

endpoint_uri = f"{os.environ['SERVER_ETH_RPC_HOST']}:{os.environ['SERVER_ETH_RPC_PORT']}"
web3 = Web3(
    HTTPProvider(endpoint_uri=endpoint_uri, request_kwargs={"timeout": 10}))
web3.eth.defaultAccount = sys.argv[
    1]  # ex: 0x0000000000000000000000000000000aBcdef123
register_keys(
    web3, [sys.argv[2]]
)  # ex: key_file=~keys/default-account.json,pass_file=~keys/default-account.pass
safeid = int(sys.argv[3])

geb = GfDeployment.from_network(web3, "kovan")
our_address = Address(web3.eth.defaultAccount)

proxy = geb.proxy_registry.proxies(our_address)
if proxy == Address("0x0000000000000000000000000000000000000000"):
    print(f"No proxy exists for our address. Building one first")
    geb.proxy_registry.build(our_address).transact()

proxy = DSProxy(web3, Address(geb.proxy_registry.proxies(our_address)))

print(f"Default account: {our_address.address}")
print(
    f"{our_address} has a DS-Proxy - {proxy.address.address}, test will continue"
)

print(f"SAFE of Safe ID {safeid} - {geb.safe_manager.safe(safeid)}")
예제 #9
0
def geb(web3) -> GfDeployment:

    deployment = GfDeployment.from_network(web3=web3, network="testnet")
    validate_contracts_loaded(deployment)

    return deployment
예제 #10
0
def create_almost_risky_safe(geb: GfDeployment,
                             c: Collateral,
                             collateral_amount: Wad,
                             auction_income_recipient_address: Address,
                             draw_system_coin=True) -> SAFE:
    assert isinstance(geb, GfDeployment)
    assert isinstance(c, Collateral)
    assert isinstance(auction_income_recipient_address, Address)
    logging.debug("Creating almost risky safe")
    print("create_almost_risky")
    print(
        f"Liquidation price {geb.safe_engine.collateral_type(c.collateral_type.name).safety_price}"
    )
    print(
        f"Safety price {geb.safe_engine.collateral_type(c.collateral_type.name).liquidation_price}"
    )

    # Ensure vault isn't already unsafe (if so, this shouldn't be called)
    safe = geb.safe_engine.safe(c.collateral_type,
                                auction_income_recipient_address)
    assert is_safe_safe(
        geb.safe_engine.collateral_type(c.collateral_type.name), safe)

    # Add collateral to auction_income_recipient vault if necessary
    c.approve(auction_income_recipient_address)
    token = Token(c.collateral_type.name, c.collateral.address,
                  c.adapter.decimals())
    print(
        f"collateral_amount={collateral_amount} locked_collateral={safe.locked_collateral}"
    )
    delta_collateral = collateral_amount - safe.locked_collateral
    if delta_collateral > Wad(0):
        safe_engine_balance = geb.safe_engine.token_collateral(
            c.collateral_type, auction_income_recipient_address)
        balance = token.normalize_amount(
            c.collateral.balance_of(auction_income_recipient_address))
        print(
            f"before join: delta_collateral={delta_collateral} safe_engine_balance={safe_engine_balance} balance={balance} safe_engine_gap={delta_collateral - safe_engine_balance}"
        )
        if safe_engine_balance < delta_collateral:
            safe_engine_gap = delta_collateral - safe_engine_balance
            if balance < safe_engine_gap:
                if c.collateral_type.name.startswith("ETH"):
                    wrap_eth(geb, auction_income_recipient_address,
                             safe_engine_gap)
                else:
                    raise RuntimeError("Insufficient collateral balance")
            amount_to_join = token.unnormalize_amount(safe_engine_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(
                auction_income_recipient_address, amount_to_join).transact(
                    from_address=auction_income_recipient_address)
        safe_engine_balance = geb.safe_engine.token_collateral(
            c.collateral_type, auction_income_recipient_address)
        print(
            f"after join: delta_collateral={delta_collateral} safe_engine_balance={safe_engine_balance} balance={balance} safe_engine_gap={delta_collateral - safe_engine_balance}"
        )
        assert safe_engine_balance >= delta_collateral
        assert geb.safe_engine.modify_safe_collateralization(
            c.collateral_type, auction_income_recipient_address,
            delta_collateral,
            Wad(0)).transact(from_address=auction_income_recipient_address)

    # Put auction_income_recipient SAFE at max possible debt
    delta_debt = max_delta_debt(geb, c,
                                auction_income_recipient_address) - Wad(1)
    if delta_debt > Wad(0):
        print(
            f"Attempting to modify safe collateralization with delta_debt={delta_debt}"
        )
        assert geb.safe_engine.modify_safe_collateralization(
            c.collateral_type, auction_income_recipient_address, Wad(0),
            delta_debt).transact(from_address=auction_income_recipient_address)

    # Draw our Dai, simulating the usual behavior
    safe = geb.safe_engine.safe(c.collateral_type,
                                auction_income_recipient_address)
    if draw_system_coin and safe.generated_debt > Wad(0):
        geb.approve_system_coin(auction_income_recipient_address)
        assert geb.system_coin_adapter.exit(
            auction_income_recipient_address, safe.generated_debt).transact(
                from_address=auction_income_recipient_address)
        print(f"Exited {safe.generated_debt} System coin from safe")

    logging.debug("Almost risky safe created")
예제 #11
0
def get_geb(web3):
    return GfDeployment.from_node(web3, 'rai')
예제 #12
0
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)

web3 = web3_via_http(endpoint_uri=os.environ['ETH_RPC_URL'])
web3.eth.defaultAccount = sys.argv[
    1]  # ex: 0x0000000000000000000000000000000aBcdef123
register_keys(
    web3, [sys.argv[2]]
)  # ex: key_file=~keys/default-account.json,pass_file=~keys/default-account.pass
our_address = Address(web3.eth.defaultAccount)
weth = GfDeployment.from_node(web3, 'rai').collaterals['ETH-A'].collateral
stuck_txes_to_submit = int(sys.argv[3]) if len(sys.argv) > 3 else 1

GWEI = 1000000000
increasing_gas = GeometricGasPrice(initial_price=int(1 * GWEI),
                                   every_secs=30,
                                   coefficient=1.5,
                                   max_price=100 * GWEI)


class TestApp:
    def main(self):
        self.startup()

        pending_txes = get_pending_transactions(web3)
        pprint(