Setting up custom price feeds on chainlink node

#node #fluxmonitor #pricefeed

Setup FluxMonitoring contract

FluxMonitoring contract contains in @chainlink/contracts/src/v0.6. You just need to import that in your new contract file or deploy directly FluxMonitoring contract. Example:

// SPDX-License-Identifier: MIT
pragma solidity 0.6.6;

import "@chainlink/contracts/src/v0.6/FluxAggregator.sol";

constructor

  • _link - Use chainlink token address

  • _paymentAmount - The amount paid of LINK paid to each oracle per submission, in wei (units of 10⁻¹⁸ LINK). We can use 100000000000000000 (0.1 LINK) for Ethereum network

  • _timeout - is the number of seconds after the previous round that are allowed to lapse before allowing an oracle to skip an unfinished round. We can use 180

  • _validator - optional. Contract address for validate answers. Without validator contract we can use 0x0000000000000000000000000000000000000000

  • _minSubmissionValue - lower limit of incoming value. We can use 0

  • _maxSubmissionValue - higher limit of incoming value. If you not sure about limits, use a value that is several times the most positive cost estimate, but not exceeding max value for int256. We can use 9999999999999999

  • _decimals - represents the number of decimals to offset the answer by. If external value is decimal, use 0. But in other case, use by instuction. By example, comes price 1922,34. We should use _decimals equals to 2 for translate value between float and decimal, because contract must take an integer value, but actually value is float. The job will also have a multiply rule of 100.

  • _description - Just small description for your job

After construct

  • Deploy contract

  • Fund your deployed FluxMonitoring contract with LINK

  • Call updateAvailableFunds

  • Set available oracles by call changeOralces. More on that below

Change Oracles

For change available oracles, use changeOracles function. Only owner of this contract can perform action! Caution! For addresses you need to use address from Chainlink Node UI, not your Operator contract address!!!

  • _removed - addresses for remove from flux monitoring job processing. If there is nothing to remove, use []

  • _added - addresses for enable flux monitoring job processing.

  • _addedAdmins - admin addresses, that are allowed to transfer LINK tokens. If there is nothing to add, use []

  • _minSubmissions - is the new minimum submission count for each round. We can use 1

  • _maxSubmissions - is the new maximum submission count for each round. We can use 2

  • _restartDelay - is the number of rounds an Oracle has to wait before they can initiate a round. We can use 0.

Optional. Change round settings

If you need to change round settings, by example round payment, use updateFutureRounds.

  • _paymentAmount - new round payment in LINK. Caution! Operator should support new payment amount by chainlink node config property named MINIMUM_CONTRACT_PAYMENT_LINK_JUELS. Before change, we recommends contact with oracle operators which you are using to avoid mistakes in job.

  • _minSubmissions - is the new minimum submission count for each round

  • _maxSubmissions - is the new maximum submission count for each round

  • _restartDelay - is the number of rounds an Oracle has to wait before they can initiate a round

  • _timeout - is the number of seconds after the previous round that are allowed to lapse before allowing an oracle to skip an unfinished round

Setup job

Explore more about job parameters through FluxMonitoring job docs.

Pay attention to the following

Receiving datasource value often consist of sequentially pipeline tasks:

  • http

  • jsonparse

  • multiply - must contain a number that, when multiplied, produces an decimal value. By example: jsonparse result is 1923.84, therefore we need to use multiply times=100

  • add to common task median

Job example with 2 datasources

type = "fluxmonitor"
schemaVersion = 1
name = "ETH/USD Test"
externalJobID = "YOUR_JOB_ID_UUID"
forwardingAllowed = false
maxTaskDuration = "30s"
absoluteThreshold = 0
contractAddress = "YOUR_FLUX_MONITORING_CONTRACT_ADDRESS"
drumbeatEnabled = true
drumbeatSchedule = "CRON_TZ=UTC * */20 * * * *"
idleTimerPeriod = "15s"
idleTimerDisabled = true
pollTimerPeriod = "1m0s"
pollTimerDisabled = false
threshold = 0.5
observationSource = """
    // data source 1
    ds1 [type="http" method=GET url="<https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD>"]
    ds1_parse [type="jsonparse" path="USD"]
    ds1_multiply     [type="multiply" input="$(ds1_parse)" times=100]

    // data source 2
    ds2 [type="http" method=GET url="<https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD>"]
    ds2_parse [type="jsonparse" path="USD"]
    ds2_multiply     [type="multiply" input="$(ds2_parse)" times=100]

    ds1 -> ds1_parse -> ds1_multiply -> medianized_answer
    ds2 -> ds2_parse -> ds2_multiply -> medianized_answer

    medianized_answer [type=median]
"""

It is worth paying attention to the fields to control the launch of queries.

  • drumbeatSchedule - starting a new round by cron. Requires idleTimerDisabled = false

  • idleTimerPeriod - launching a new round at a specified interval regardless of the price deviation. Maximum supported formatting value is h. Requires drumbeatEnabled = false.

  • pollTimerPeriod - the interval after which a new round will be requested if the price has changed. Used in conjunction with threshold / absoluteThreshold parameters. The maximum supported value of formatting is h.

Fields for price deviation control:

  • threshold - the value of the deviation in percentage from the previous round, after which a new round should be requested

  • absoluteThreshold - the value in units of the previous round after which a new round must be requested

Manually requesting rounds

If you need to request rounds manually, you will need to disable timer requests and add the wallet address from which data will be requested to the list of authorized addresses for the request

In job

You should disable time-based requests.

idleTimerDisabled = true
drumbeatEnabled = false
pollTimerDisabled = true

After that, the automatic requests will no longer work

In FluxAggregator smart contract

You should call FluxAggregator->setRequesterPermissions with arguments:

  • _requester - address from which the requests will be executed. Starts with 0x

  • _authorized - true

  • _delay - number of rounds the requester must wait before starting another round. We use 0.

Update price manually

after doing all the manipulations, just call FluxAggregator->requestNewRound

Add access restrictions to your price feed data

If you only want to supply your data to a limited range of projects/contracts, this section is for you. In general terms, the access scheme will look like this. EACAggregatorProxy -> SimpleWriteAccessController -> FluxAggregator

Add a restricted access contract

Use the SimpleWriteAccessController to do this. Just compile and deploy.

To add the client address to the list of allowed addresses, you will need to use the SimpleWriteAccessController->addAccess function call.

To remove a user from the allowed list, use the SimpleWriteAccessController->removeAccess function call.

If you need to disable or enable permission checking for some time, use the SimpleWriteAccessController->disableAccessCheck / SimpleWriteAccessController->enableAccessCheck calls respectively. Important: By default, right after unloading a contract, the rights check will be enabled.

Add a proxy contract to access the FluxAggregator

First, compile the EACAggregatorProxy contract. In order to unload the resulting contract, you will need valid FluxAggregator and SimpleWriteAccessController contracts:

  • _aggregator - the address of the FluxAggregator contract for which access control should be implemented

  • _accessController - the address of the SimpleWriteAccessController contract, which contains the rights for access to the FluxAggregator.

If you need to change the SimpleWriteAccessController, you can do this by calling EACAggregatorProxy->setController

Withdrawal of funds

The reward works as follows:

  • Your Chainlink Node processes the round

  • When the round is created, the FluxAggregator contract will reserve the payout (rather than transfer it immediately) for your Chainlink Node Address

If you want to check the current amount reserved, you need to call FluxAggregator -> withdrawablePayment with your Chainlink Node Address.

If you want to withdraw your reserved payments to your Chainlink Node Address, you will need to call FluxAggregator->withdrawPayment, where you specify the Chainlink Node Address where you want the reserved payments to go and the amount of funds to be transferred. Important: This function is only available to the oracle administrator.

Troubleshooting

Gas estimation failed: ‘execution reverted: insufficient funds for payment’

You need to fund your contract with LINK and after that call updateAvailableFunds.

Formula:

MIN_LINK_REQUIRED = numberOfUsingOracles * oracleFee * numberOfRound

Example:

3 oracles * 0.07LINK * 2 rounds = 0.42 LINK

No job runs and console reports: not eligible to submit

If jobs list is empty and your chainlink node console logs contains job run error not eligible to submit, the reason is most likely in incorrect node address. Remember that you need to use address from Chainlink Node UI, not your Operator contract address!!! You can change available oracles through calling changeOracles.

The Client needs to ensure that the FluxAggregator contract has enough funds to pay the oracles. The error indicates the contract has run out out funds.

Sources

Last updated