Learn how to make smart contracts Keepers-compatible with the
arkadiko-automation-trait-v1trait and its functions.
Keepers-compatible contracts must meet the following requirements:
- Implement trait
arkadiko-automation-trait-v1. You can refer to the Arkadiko Contracts on GitHub to find the trait interface.
- The automation trait has three functions that need to be implemented:
- Include a read-only
check-jobfunction that contains the logic that will be executed off-chain to see if
run-jobshould be executed. The
run-jobfunction can use on-chain data from any other Clarity smart contract, including use of the
at-blockfunction to access historical data.
- Include a public
run-jobfunction that will be executed on-chain when
After you register the contract as an Arkadiko Job, the Keepers Network simulates the
check-jobread-only function off-chain during every block to determine if the job needs to run. When
(ok true), the Keepers Network calls
run-jobon-chain and charges 10 DIKO plus the STX gas fee from your account. This cycle repeats until the job is cancelled or runs out of funding.
;; Add DIKO to liquidation pool every 1008 blocks
(end-epoch-block (unwrap-panic (contract-call? 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.arkadiko-liquidation-rewards-diko-v1-1 get-end-epoch-block)))
(asserts! (>= block-height end-epoch-block) (ok false))
(asserts! (unwrap-panic (check-job)) (ok false))
;; TODO - Update for mainnet
(unwrap-panic (contract-call? 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.arkadiko-liquidation-rewards-diko-v1-1 add-rewards 'ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.arkadiko-liquidation-rewards-v1-2))
In the above example, we would like to add an amount of DIKO tokens to the Arkadiko liquidation pool which is used as rewards for people depositing USDA. More information about the liquidation pool can be found here. Let's analyze the above lines of code.
On line 2, we import the arkadiko automation trait that will require us to implement the three required methods: initialize, check-job and run-job. In this case, we don't need any initialization logic (which you need to execute yourself on deployment), so we simply return (ok true).
The check-job read-only function will call an Arkadiko read-only function to get the
end-epoch-block. Or in other words, we get the block height at which we should add new DIKO to the liquidation rewards. Alternatively, we could have also written custom logic in this smart contract to keep the last block execution and execute it every 1008 blocks. When the current
block-heightis greater or equal to the
end-epoch-blockheight, we should return
(ok true). Otherwise, we return
IMPORTANT: Your check-job function should never return an error (e.g. (err false)), since that would make the whole execution process fail. Simply return (ok true) or (ok false)
The run-job public function simply executes the transfer of DIKO through a liquidation rewards contract and returns (ok true). Always end your execution with an error code or an ok code.
Some actions must be performed only when specific conditions are met. Check all of the preconditions within
run-jobas well to ensure that state change occurs only when necessary.
In this pattern, it is undesirable for the state change to occur until the next time the Arkadiko Job is checked by the network and the conditions are met. It is a best practice to stop any state change or effects by performing the same checks or similar checks that you use in
check-job. These checks validate the conditions before doing the work.
For example, if you have a contract where you create a block-height based timer in
check-jobthat is designed to start a transfer at a specific time, validate the condition to ensure third-party calls to your
run-jobfunction do not start the transfer at a different block height.
Some actions must be performed using data you intend to use. Validated that the
run-jobfunction is allowed before execution.
For example, if you have a
run-jobthat funds a wallet, ensure you have a list of permissable addresses to compare against to prevent third-party calling your function to send money to their address.
Sometimes actions must be performed when conditions are met, but performing actions when conditions are not met is still acceptable. Condition checks within
run-jobmight not be required, but it can still be a good practice to short circuit expensive and unnecessary on-chain processing when it is not required.
It might be desirable to call
check-jobconditions haven't yet been tested by Arkadiko Keepers, so any specific checks that you perform are entirely use case specific.
As with all smart contract testing, it is important to test the boundaries of your smart contract in order to ensure it operates as intended. Similarly, it is important to make sure your Keepers-compatible contract operates within the parameters of the Job Registry.
Test all of your mission-critical contracts, and stress-test the contract to confirm the performance and correct operation of your use case under load and adversarial conditions. The Arkadiko Keeper Network will continue to operate under stress, but so should your contract.