# Keepers-compatible contracts

### Overview <a href="#overview" id="overview"></a>

Learn how to make smart contracts **Keepers-compatible** with the `arkadiko-automation-trait-v1` trait and its functions.

### Example Contract <a href="#example-contract" id="example-contract"></a>

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` and `run-job`
* Include a read-only `check-job` function that contains the logic that will be executed off-chain to see if `run-job` should be executed. The `run-job` function can use on-chain data from any other Clarity smart contract, including use of the `at-block` function to access historical data.
* Include a public `run-job` function that will be executed on-chain when `check-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](/protocol/liquidation-pool.md). 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.

#### Best practices <a href="#best-practices" id="best-practices"></a>

**Trigger ONLY when conditions are met**

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.

**Trigger ONLY when data is verified**

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.

**When triggering is not harmful**

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.

**Test your contract**

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.<br>

### &#x20;<a href="#best-practices" id="best-practices"></a>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.arkadiko.finance/keepers/keepers-compatible-contracts.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
