Skip to content

Commit

Permalink
refactor: upgrade keeper script (yearn#92)
Browse files Browse the repository at this point in the history
* feat: upgrade keeper script for gas strategy, gas cost estimates, etc
* chore: upgrade to brownie v1.12.0
* chore: upgrade to Brownie v1.12.1 for keeper script
* fix: forgot f in f-string
  • Loading branch information
fubuloubu committed Dec 2, 2020
1 parent 6f56f6e commit cdc55ef
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 27 deletions.
2 changes: 1 addition & 1 deletion requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
black==19.10b0
eth-brownie>=1.11.12,<2.0.0
eth-brownie>=1.12.1,<2.0.0
86 changes: 60 additions & 26 deletions scripts/keep.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from brownie import accounts, network, interface, Vault
from brownie import accounts, network, interface, Vault, Token
from brownie.network.gas.strategies import GasNowScalingStrategy
from decimal import Decimal
from eth_utils import is_checksum_address
import requests
from time import sleep


GAS_BUFFER = 1.2

gas_strategy = GasNowScalingStrategy()


def get_address(msg: str) -> str:
while True:
addr = input(msg)
Expand All @@ -13,13 +19,6 @@ def get_address(msg: str) -> str:
print(f"I'm sorry, but '{addr}' is not a checksummed address")


def get_gas_price(confirmation_speed: str = "fast"):
if "mainnet" not in network.show_active():
return 10 ** 9 # 1 gwei
data = requests.get("https://www.gasnow.org/api/v3/gas/price").json()
return data["data"][confirmation_speed]


def main():
print(f"You are using the '{network.show_active()}' network")
bot = accounts.load("bot")
Expand All @@ -30,45 +29,80 @@ def main():
strategies.append(interface.StrategyAPI(get_address("Strategy to farm: ")))

vault = Vault.at(strategies[0].vault())
want = Token.at(vault.token())

for strategy in strategies:
assert (
strategy.keeper() == bot.address
), "Bot is not set as keeper! [{strategy.address}]"
assert strategy.vault() == vault.address, "Vault mismatch! [{strategy.address}]"
assert (
strategy.vault() == vault.address
), f"Vault mismatch! [{strategy.address}]"

while True:
gas_price = get_gas_price()
starting_balance = bot.balance()

no_action = True
calls_made = 0
total_gas_estimate = 0
for strategy in strategies:
# Display some relevant statistics
symbol = vault.symbol()[1:]
symbol = want.symbol()
credit = vault.creditAvailable(strategy) / 10 ** vault.decimals()
print(f"[{strategy.address}] Credit Available: {credit:0.3f} {symbol}")
debt = vault.debtOutstanding(strategy) / 10 ** vault.decimals()
print(f"[{strategy.address}] Debt Outstanding: {debt:0.3f} {symbol}")

# TODO: Actually estimate gas
if strategy.tendTrigger(40000 * gas_price):
starting_gas_price = next(gas_strategy.get_gas_price())

try:
tend_gas_estimate = int(
GAS_BUFFER * strategy.tend.estimate_gas({"from": bot})
)
total_gas_estimate += tend_gas_estimate
except ValueError:
print(f"[{strategy.address}] `tend` estimate fails")
tend_gas_estimate = None

try:
harvest_gas_estimate = int(
GAS_BUFFER * strategy.harvest.estimate_gas({"from": bot})
)
total_gas_estimate += harvest_gas_estimate
except ValueError:
print(f"[{strategy.address}] `harvest` estimate fails")
harvest_gas_estimate = None

if harvest_gas_estimate and strategy.harvestTrigger(
harvest_gas_estimate * starting_gas_price
):
try:
strategy.tend({"from": bot, "gas_price": gas_price})
no_action = False
strategy.harvest({"from": bot, "gas_price": gas_strategy})
calls_made += 1
except:
print("Call failed")
print(f"[{strategy.address}] `harvest` call fails")

elif strategy.harvestTrigger(180000 * gas_price):
elif tend_gas_estimate and strategy.tendTrigger(
tend_gas_estimate * starting_gas_price
):
try:
strategy.harvest({"from": bot, "gas_price": gas_price})
no_action = False
strategy.tend({"from": bot, "gas_price": gas_strategy})
calls_made += 1
except:
print("Call failed")
print(f"[{strategy.address}] `tend` call fails")

# Check running 10 `tend`s & `harvest`s per strategy at estimated gas price
# would empty the balance of the bot account
if bot.balance() < 10 * total_gas_estimate * starting_gas_price:
print(f"Need more ether please! {bot.address}")

if no_action:
# Wait a minute if we didn't make any calls
if calls_made > 0:
gas_cost = (starting_balance - bot.balance()) / 10 ** 18
num_harvests = bot.balance() // (starting_balance - bot.balance())
print(f"Made {calls_made} calls, spent {gas_cost} ETH on gas.")
print(
f"At this rate, it'll take {num_harvests} harvests to run out of gas."
)
else:
print("Sleeping for 60 seconds...")
sleep(60)

if bot.balance() < 10 ** 8 * gas_price:
# Less than 100m gas left to spend
print(f"Need more ether please! {bot.address}")

0 comments on commit cdc55ef

Please sign in to comment.