Keepers-compatible contracts
Learn how to make smart contracts Keepers-compatible with the
arkadiko-automation-trait-v1
trait 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:
initialize
,check-job
andrun-job
- Include a read-only
check-job
function that contains the logic that will be executed off-chain to see ifrun-job
should be executed. Therun-job
function can use on-chain data from any other Clarity smart contract, including use of theat-block
function to access historical data. - Include a public
run-job
function that will be executed on-chain whencheck-job
returns(ok true)
.
After you register the contract as an Arkadiko Job, the Keepers Network simulates the
check-job
read-only function off-chain during every block to determine if the job needs to run. When check-job
returns (ok true)
, the Keepers Network calls run-job
on-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
(impl-trait .arkadiko-automation-trait-v1.automation-trait)
(define-public (initialize)
(ok true)
)
(define-read-only (check-job)
(let (
(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))
(ok true)
)
)
(define-public (run-job)
(begin
(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))
(ok true)
)
)
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-height
is greater or equal to the end-epoch-block
height, we should return (ok true)
. Otherwise, we return (ok false)
.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
check-job
and run-job
as 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-job
that is designed to start a transfer at a specific time, validate the condition to ensure third-party calls to your run-job
function 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-job
function is allowed before execution.For example, if you have a
run-job
that 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-job
might 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
run-job
when the check-job
conditions 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.
Last modified 10mo ago