Adding new Keep3r jobs to Autotask

Hi

I’ve successfully setup autotask and got it running. However I’ve noticed some new jobs available on the keep3r network. I was wondering if there’s a guide on how to add new jobs to the existing autotask for regular non-dev guys like myself. Hopefully there are others out there who have successfully added new jobs to their autotask and can help.

I am trying to find out if it is as simple as adding the ABI to the const ABIs variable and then adding the contract address and the workFn to the const Jobs or requires much more fiddling around with the code.

If this is indeed just added ABI and contract address, is there a way to know which methods from the ABI to include instead of the full set?

I’m looking at adding jobs like:
MetaKeep3r, SushiswapV1Oracle, HegicKeep3rV2, MMStrategyKeeperV1, etc

Cheers
Alvin

1 Like

Hey Alvin! For most jobs, it should just be a matter of adding ABI, contract address, and functions to call. These are in two places in the script: first, in the Jobs definitions, where you need to add the job name, the contract address, the name of the workableFn function to query to detect if there is work to be done, and the name of the workFn function to send a transaction in order to do that work.

The second is in the list of ABIs. You need to add an entry for each new job (using the same job name as you did in the Jobs list above) with the contract ABI. You don’t need the full ABI: just including the definitions for the workable and work functions is enough.

Note that the script, as is, only supports functions that don’t require any parameters. If you want to work jobs that require params, you’ll need to find out how to calculate them before calling the functions.

Hope this helps!

1 Like

Hi @AlvinP,

We mention this briefly in the documentation.

Do you have any suggestions on how this could be improved?

Hi @spalladino

Thanks for the guidance, useful as always. I think I understand the logic but I’m having trouble with the execution. For example, I added the SushiswapV1Oracle job and I get the following error:

2020-12-16T01:49:47.200Z undefined ERROR Uncaught Exception {"errorType":"Runtime.UserCodeSyntaxError","errorMessage":"SyntaxError: Unexpected identifier","stack":["Runtime.UserCodeSyntaxError: SyntaxError: Unexpected identifier"," at _loadUserApp (/var/runtime/UserFunction.js:98:13)"," at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)"," at Object.<anonymous> (/var/runtime/index.js:43:30)"," at Module._compile (internal/modules/cjs/loader.js:1015:30)"," at Object.Module._extensions..js (internal/modules/cjs/loader.js:1035:10)"," at Module.load (internal/modules/cjs/loader.js:879:32)"," at Function.Module._load (internal/modules/cjs/loader.js:724:14)"," at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)"," at internal/main/run_main_module.js:17:47"]}

In the autotask script, I added the following ABI
SushiswapV1Oracle: [{"inputs":[],"name":"work","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"workForFree","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

For const Jobs , I added the following:
{ name: 'SushiswapV1Oracle', address: '0xf67Ab1c914deE06Ba0F264031885Ea7B276a7cDa', workableFn: : 'workable', workFN: 'work'},

I suspect I may be making a mistake in defining the name of the workableFN and workFN.

This is the contract address : https://etherscan.io/address/0xf67ab1c914dee06ba0f264031885ea7b276a7cda#code
Would be great if you can help me figure this out. I have so much to learn.

1 Like

Hi @AlvinP,

It looks like you have two colons when you should only have one after workableFn.

{ name: 'SushiswapV1Oracle', address: '0xf67Ab1c914deE06Ba0F264031885Ea7B276a7cDa', workableFn: : 'workable', workFN: 'work'}, 

Compare this with:

 { name: 'UniswapV2SlidingOracle', address: '0xCA2E2df6A7a7Cf5bd19D112E8568910a6C2D3885', workableFn: 'workable', workFn: 'work' },
  { name: 'HegicPoolKeep3r',        address: '0x5DDe926b0A31346f2485900C5e64c2577F43F774', workableFn: 'workable', workFn: 'claimRewards' },
  { name: 'YearnV1EarnKeep3r',      address: '0xe7F4ab593aeC81EcA754Da1B3B7cE0C42a13Ec0C', workableFn: 'workable', workFn: 'work' },

Thank @abcoathup, you’re a star! I went back to check the script again and found also I didn’t have , after each line of ABI so that was throwing the syntax error as well. Now the error I get is as follows:

AUTOTASK START
2020-12-16T11:51:47.611Z INFO Starting work…
2020-12-16T11:51:47.613Z INFO Error working SushiswapV1Oracle: contract[job.workableFn] is not a function
2020-12-16T11:51:47.626Z INFO Error working Keep3rV1Oracle: contract[job.workableFn] is not a function
2020-12-16T11:52:43.175Z INFO YearnV1EarnKeep3r is not workable
2020-12-16T11:52:43.208Z INFO HegicPoolKeep3r is not workable
END RequestId: 6e0efd34-52bb-4a1b-9592-6a634d4e9571
AUTOTASK COMPLETE
`

Their respective contract source codes I got from here:https://etherscan.io/address/0xf67ab1c914dee06ba0f264031885ea7b276a7cda#code and https://etherscan.io/address/0x73353801921417f465377c8d898c6f4c0270282c#code

Thanks so much.

Alvin

That error looks like the function you’ve defined as workableFn is not found in the contract’s ABI, but it doesn’t seem to be the case. Just in case: note that all names are case sensitive in javascript. You’re using workFN instead of workFn in the SushiSwap job definition, which will cause the work tx to fail. Perhaps you have a similar issue with the definition of the workableFn?

1 Like

Thanks @spalladino for responding to so quickly. I spotted that workFN error earlier and changed it to workFn before getting the most recent errors above.

I did check again in the contract ABI and it has workable as well as work. Not sure if I need to but I did look at the contract code and found that there are functions called work and workable. Am I missing something else you think?

Cheers
Alvin

1 Like

Hi @AlvinP,

add the ABI of the contract you want to work to the ABIs object in the snippet, and add an entry to Jobs with the contract name and address, as well as the names of the workable and work functions.

It sounds like you have done this, so you should be ok to try it out.

do,you have 200 kp3r? there is a minimum for this job

1 Like

hi @Bolo

I saw some keeper doing the Keep3rV1Oracle job with less than 1 keep3r bonded
e.g. https://keep3r.live/keeper/0x9f6fdc2565cfc9ab8e184753bafc8e94c0f985a0
so I got the impression that 200 kp3r bond is not required. Did I miss something?

1 Like

Hi @abcoathup

I’ve gone back to the sushiswap job contract and copied the relevant ABI to my script again just to be sure. I still get the same error below as before. Do you think you can explain what contract [job.workableFn] is not a function mean?

I’ve attached the ABI section of my script below in case you happen to spot something that I missed.
const ABIs = { //UniswapV2SlidingOracle: [{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"work","outputs":[],"stateMutability":"nonpayable","type":"function"}], HegicPoolKeep3r: [{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}], YearnV1EarnKeep3r: [{"inputs":[],"name":"work","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}], SushiswapV1Oracle: [{"inputs":[],"name":"work","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}], Keep3rV1Oracle: [{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}], Registry: [{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"keepers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonding","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"bondings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonding","type":"address"}],"name":"activate","outputs":[],"stateMutability":"nonpayable","type":"function"}], }
@Bolo are you able to work the any other jobs besides the HegicPool and YearnV1 ones?

Cheers
Alvin

1 Like

yes but not for SushiJob. you need a minimum of 200

1 Like

Hi @AlvinP,

Sorry for the delay in getting back to you. I was on vacation for the holidays.

Were you able to resolve the issue?

Hi @Bolo,

Do you know if there is a list of Jobs including the minimum amount of K3PR required?
The only way I have seen is to check the smart contract.

hi @abcoathup

Thanks for following up. Hope you enjoyed the break. Still got the same error: contract[job.workableFn] is not a function. Is there something wrong in my script?

I’ve commented out the sushi job since @Bolo mentioned I needed 200kp3r bonded. I was looking in the contract but don’t know where it is defined though.

1 Like

Hi @AlvinP,

I assume there is a typo in your script for that particular job in the ABI or the Job definition.

Feel free to share your ABI and Job definitions:

// ABIs for jobs and registry (contain only the methods needed, not the full ABIs of the contracts)
const ABIs = {
  UniswapV2SlidingOracle: [{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"work","outputs":[],"stateMutability":"nonpayable","type":"function"}],
  HegicPoolKeep3r: [{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}],
  YearnV1EarnKeep3r: [{"inputs":[],"name":"work","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],
  Registry: [{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"keepers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonding","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"bondings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonding","type":"address"}],"name":"activate","outputs":[],"stateMutability":"nonpayable","type":"function"}],
}

// Definition for all jobs to execute
const Jobs = [
  { name: 'UniswapV2SlidingOracle', address: '0xCA2E2df6A7a7Cf5bd19D112E8568910a6C2D3885', workableFn: 'workable', workFn: 'work' },
  { name: 'HegicPoolKeep3r',        address: '0x5DDe926b0A31346f2485900C5e64c2577F43F774', workableFn: 'workable', workFn: 'claimRewards' },
  { name: 'YearnV1EarnKeep3r',      address: '0xe7F4ab593aeC81EcA754Da1B3B7cE0C42a13Ec0C', workableFn: 'workable', workFn: 'work' },
];

In the contract there is a minKeep with a value of 200 K$PR. https://keep3r.network/keep3r/job/0xf67Ab1c914deE06Ba0F264031885Ea7B276a7cDa

    uint public minKeep = 200e18;

    modifier keeper() {
        require(KP3R.isMinKeeper(msg.sender, minKeep, 0, 0), "::isKeeper: keeper is not registered");
        _;
    }

I had a week in a National Park with lots of time hiking and at the beach. It was awesome.

Thanks @abcoathup for the prompt reply.
I’ve checked the Keep3rV1Oracle and indeed there is a uint public minKeep = 200e18; which means it also has a minimum bonded requirement. That is probably why I was getting the error for both this and the sushiswap job. Thanks for sharing how to check it in the contract.

Today I’m trying to add a new job called LidoKeep3r and the contract is at https://etherscan.io/address/0x1ee5c83c4b43aaed21613d5cc7835d36078ce03f#code
I noticed the syntax of the ABI is slightly different so I copied and pasted the whole lot since I don’t know which bits are needed.

my code is as below:

const ABIs = {
  HegicPoolKeep3r: [{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"}],
  YearnV1EarnKeep3r: [{"inputs":[],"name":"work","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"workable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],
  LidoKeep3r: [{"name":"work","outputs":[],"inputs":[],"stateMutability":"nonpayable","type":"function","gas":50465},{"name":"workable","outputs":[{"type":"bool","name":""}],"inputs":[],"stateMutability":"view","type":"function","gas":4117}],
  Registry: [{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"keepers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonding","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"bond","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"bondings","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonding","type":"address"}],"name":"activate","outputs":[],"stateMutability":"nonpayable","type":"function"}],
}

const Jobs = [
  { name: 'HegicPoolKeep3r',        address: '0x5DDe926b0A31346f2485900C5e64c2577F43F774', workableFn: 'workable', workFn: 'claimRewards' },
  { name: 'YearnV1EarnKeep3r',      address: '0xe7F4ab593aeC81EcA754Da1B3B7cE0C42a13Ec0C', workableFn: 'workable', workFn: 'work' },
  { name: 'LidoKeep3r',      address: '0x1EE5C83C4B43aaEd21613D5cc7835D36078ce03F',  workableFn: 'workable', workFn: 'work' },
];

and the error I got was

2020-12-30T03:06:55.477Z	INFO	Error working LidoKeep3r: execution reverted

any idea what this means?

1 Like

Hi @AlvinP,

The LidoKeep3r contract is written in Vyper. It doesn’t look like reasons are provided in the reverts unfortunately, so all you can see is that it has reverted.

I am not that familiar with Vyper, so you may want to check if there is a minimum K3PR requirement.

You may want to ask in: https://gov.yearn.finance/c/projects/keep3r/20

I don’t think so. I am checking manually each contract if there is a method minKeeper

1 Like