# Introduction

Overview

## What is Tellor?

Tellor is a Layer 1 blockchain built for the purpose of coming to consensus on any subjective data. It is operated by an open public network of staked parties who are crypto-economically incentivized to honestly report requested data.

{% hint style="info" %}
For in-depth information about the design, checkout the [Whitepaper](https://docs.tellor.io/tellor/whitepaper) and our [ADRs](https://github.com/tellor-io/layer/tree/main/adr).
{% endhint %}

### Tellor-1

**`tellor-1` is the tellor mainnet chain-id. Over a year in the making, this is a custom oracle chain for coming to consensus on subjective data.** The network is open for anyone to participate with no barriers to participation other than bridging and staking TRB ([ERC20](https://etherscan.io/token/0x88df592f8eb5d7bd38bfef7deb0fbc02cf3778a0?a=0x8cfc184c877154a8f9ffe0fe75649dbe5e2dbebf)).

{% content-ref url="/pages/Pe4IW2P0OSDraf0cWra8" %}
[Running Tellor](/tellor/running-tellor/getting_started)
{% endcontent-ref %}

### Palmito Testnet (layertest-5)

Palmito is the current testnet equivalent for testing tellor operation and functionaity.

{% content-ref url="/pages/cpgf4r3gLEp7xSXrvVjL" %}
[Running Palmito (testnet)](/tellor/running-palmito-testnet/public-testnet)
{% endcontent-ref %}

### What is a Validator?

Validators in the Tellor network play a crucial role in maintaining the blockchain's integrity and consensus. They are responsible for validating transactions, securing the network, and ensuring the proper functioning of the blockchain. The number of total validators is capped at 100.

#### **Responsibilities of a Validator:**

1. **Transaction Validation:** Validators validate transactions and add them to the chain.
2. **Consensus Participation:** They participate in the consensus mechanism to agree on the state of the chain.
3. **Block Proposal:** Validators propose new blocks and ensure that all committed transactions are included.
4. **Signing:** Validators sign aggregated data values, ensuring their correctness before they are relayed to other chains.

### What is a Reporter?

Reporters are individuals who read data from the internet (and/or any"real world" sources) for submission to the Tellor oracle. The data they report is aggregated and verified via on-chain consensus. Reporters earn TRB rewards for their efforts.

#### **Reporters are responsible for:**

* **Submitting values** for data requests (queries) that are subject to validation and disputes. \*Validators can be reporters but not all reporters will be validators.
* **Monitoring submissions for accuracy**. A robust system of staking and slashing ensures that reporters (and users) are crypto-economically incentivized to monitor their data.


# Whitepaper

Last Edited: 11 Aug 2026

## Introduction

From the initial deployment in August 2019, Tellor has been designed so that no trusted party can prevent users from requesting, reporting or disputing data. Today we continue with the same principles: permissionless validators, reporters, disputers, relayers and users. Anyone can become a validator or reporter via staking, dispute for a fee, get any data by tipping it, and relay the openly available data attestations on Tellor, without the team's intervention. Crypto economic incentives have been in place since inception as we have focused our efforts on being decentralized and secure. Tellor's design supports data liveness guarantee which is only possible because the design allows the protocol to survive even if the team disappears[^1].

Every aspect of Tellor is open source including consensus, bridging, reporting, and relaying so that everyone can audit and participate in the network as validators, reporters, users, and holders.

Throughout the protocol, architecture decisions prioritize censorship resistance, open participation, and security over speed. Slow unstaking, delayed withdrawals, dispute windows, dispute rounds, configurable user by user trust assumptions such as fallbacks, consumer side validation and choice of relay all aim to reduce systemic risk.\
\
Tellor provides a flexible foundation for users to choose how they consume our data. Users can control how much validation, delay, monitoring or redundancy they require and even layer their own governance or additional security.

## How the Chain Works

Tellor is a stand alone L1 built for the purpose of coming to consensus on any subjective data. It works by using a network of staked parties who are crypto-economically incentivized to honestly report requested data.

### Submitting Values

Any staked reporter can submit a value for a given query (i.e. data request, e.g. BTC/USD price). All queries have a report time frame. For that given time period, reporters can add their value to the array of submissions. At the end of the time period, the official value is determined by a weighted aggregation of all the values submitted.

All queries have an aggregation type associated with it (e.g. median, mode, average, etc.). Once the time frame ends, the reports are subject to weighted aggregation. For this reason, larger reporters contribute more to the official value than smaller ones. Each official value takes a minimum of three blocks (target time 2s per block). The first block is the tip (e.g. "I request BTC/USD"). The second block is the reporting and the third is more reporting and aggregation phase, where all values are submitted and then aggregated, at which point an official value is determined for the query. Tips are distributed to all reporters for a given query using their weighted contribution.

Figure A: Tellor process from Tip to Data Aggregation.&#x20;

The reporting time frame begins once a queryId is tipped. All reporters can add their value to the submission array for inclusion in the aggregation and for distribution of the rewards. Tips received within the time frame are added to the initial tip. If no reports are submitted during the time frame, the time frame is restarted upon the next tip and the original tip is added to the new tip for that queryId.

### Cycle List

In order to maintain freshness, the system maintains a list of enshrined queries, a *cycle list*. Reporters continuously report for the next query in the list to ensure that tips do not need to be submitted in previous blocks to have a base level of reporting (thus avoiding wasting gas by validators who just want inflationary rewards). This signals reporters what to report so they act in unison and contribute as much aggregate power to a single report as is available. Reporters are never required to report for any queries including those in this list, but as long as inflationary rewards are enough to cover the gas costs of reporting, some query from the cycle list should be reported to consensus every block. Cycle list changes are voted on by governance.

To incentivize consistent reporting across **all** cycle list queries, TBR distribution uses a per-aggregate power share approach. Instead of distributing TBR immediately per aggregate, rewards are accumulated over a configurable period and distributed based on each reporter's power share within each aggregate.

### Disputing

There are some differences in disputes from legacy Tellor but what has not changed is that the entire dispute and resolution mechanism is done on chain with transparent slashing and with earning successful disputers earning the majority of the slash amount. This mechanism continues to incentivize everyone to run a disputable values monitor and to compete to be the first to dispute. Also, the user does not have to wait for resolution, instead if the value was the median the value is flagged and removed, and they can use the next available value. Similar to the old Tellor system too, is the idea that since you can censor a party by disputing, disputes can be seen as a wager on who is correct (the reporter or the accuser).

What is different is that reporter stakes are not tied to specific values, but rather to a given reporter. For instance, a reporter can submit ETH/USD once every second with their same stake. If they submitted a bad value 2 days ago[^2], they can still be subject to a slashing event. Any party can raise a dispute with free floating TRB, but unlike the old system, reporters and validators can use their stake (or part of it) to begin a dispute. Once initiated, the dispute fee and the potential slash amount (from the accused reporter) are put in escrow and removed from corresponding staking powers.

To initiate a dispute, the disputing party submits a dispute against a given reporter for one of three categories:

* Warning (dispute fee is 1% of stake) - jail[^3] with no minimum time lock, can call a function to be released from jail and begin reporting again
* Minor Infraction (dispute fee is 5% of stake) - jailed for 10 minutes and out when they call the release from jail function
* Major Infraction (dispute fee is 100% of stake) - jail until dispute over (since 100% of stake).

A release function has to be called after a warning or minor infraction to ensure the staker has looked at the dispute and implemented a fix as necessary. Infractions in these lower two tiers can generally be assumed to not be malicious.

After specifying the dispute category, the disputer submits an amount of TRB up to the minimum slashing amount before the dispute can initiate. If they don't have enough funds themselves, for up to one day, others can add to the pot until they hit the slashing amount (i.e. 1, 5, or 100 percent depending on the slashing category). Once the amount is hit (could be hit instantly upon proposing the dispute, or could take up to a day), the potential slashing amount will be taken from the disputed validator and placed into a locked stake.

For up to two days, stakeholders will vote on which side of the dispute they support. Tellor uses a different voting distribution[^4] from the legacy Tellor governance. Previously, voting power was evenly distributed among users, reporters, token holders and the team. However, because most TRB on Tellor is expected to be either staked or used for tips, the voting distribution is split among these three groups:

33.3% users (tips)

33.3% reporters

33.3% team

When reporters vote they vote with the backing of all the TRB that was delegated to them. However, the selectors (TRB holders that selected a reporter) can independently vote for the dispute and overwrite the reporter's vote for their voting power. Holders can help increase the security of Tellor by delegating to validators and selecting a reporter as this will allow them to participate on dispute votes.

Once the two days are over there is a one day period where the dispute can be reopened and the same two day voting round is repeated. However, if at any point a quorum of >50% total voting power votes in favor of one side of the dispute, the dispute is considered finalized and no new rounds can be opened.

Once the dispute is resolved, the stake from the losing party is transferred to the winning party(ies) as undelegated, staked TRB. Tokens disputed or used as fees in disputes are not released as free floating tokens so as disputes cannot be used as a way to exit staking faster, however if free floating tokens are used to pay the fee, they are returned as free floating tokens in the case of a successful dispute.

Note that each dispute round (even the initial one) takes 5% of the dispute fee. Of that 5%, half is burned and the other half is divided amongst voters in the system. The dispute fee then doubles each round **up to the slash amount** to further incentivize voting and to prevent spamming. Once quorum is reached on a dispute, further dispute rounds cannot be raised.

For usage purposes, values are not attested to if the disputed reporter was the official aggregated value (median contribution). Values that need to be flagged are also added to evidence when the dispute is initiated (an array of values). For this reason, users who rely on optimistic finality should be aware of dispute censoring attacks and the potential for values to take time to get through.

Tellor's on chain dispute mechanism, resolution and slashing allow it to be a preventive measure as well as a proactive one. Slashing helps deter attackers while also economically incentivizes anyone, including the user to be proactive in disputing before the data is ingested by a protocol. After the fact disputes are also allowed, however, the incentivized preventive and proactive approaches are preferred and properly incentivized since once the data is ingested, damage could be irreversible.

### Validator penalties

Validators have normal cometBFT liveness and double-signing penalties, which are handled automatically by the chain. Additionally, Tellor applies slashing for malicious attestations and malicious validator set update signatures. This is done by manually submitting evidence of these behaviors.

| Standard cometBFT penalties                     | Additional Tellor penalties                            |
| ----------------------------------------------- | ------------------------------------------------------ |
| Liveness (15 minutes of inactivity) slash is 1% | Malicious attestations are slashed 1% of stake         |
| Double-sign slash is 5%                         | Malicious validator set update attempts are slashed 5% |

### Tipping

All tips are done in TRB. Each query can be tipped directly and its tip will increase as more users tip it[^5]. Once a report is submitted and aggregated, 98% of the tip is split amongst reporters for that query in that given block. There is a 2% fee on the tips (to prevent vote farming/ spamming). This 2% fee is burned. Tips are distributed as locked TRB. Once locked, parties can run functions to claim the tip, in which the tips are unlocked and added to their stake or to tip balance ('MsgWithdrawTipToBalance') which will start the clock to unbound these in 21 days. This is to ensure that parties cannot bypass validator deposit limits through tipping, as well as to prevent farming vote power via the tipping mechanism.

Note that tipping consists of only one time tips. There is no built-in heartbeats or price thresholds because the complexity added is unnecessary and better handled off-chain (e.g. AI agents, or tip bots like the autoTipper and relayer handle this functionality already).

### Validator Set Dynamics

Chains using the tendermint consensus mechanism have a limited number of validators. By setting the number of validators, this allows for efficient interconnectedness between chains as well as faster throughput. The tradeoff that any chain must consider is that more validators leads to slower blocktimes and more expensive bridging costs. Tellor has started with a limit of 100 validators but will move to a larger set as technological advances or market conditions allow (e.g. if no one needs sub-2 second blocks).

The validator set can only change by a maximum of 5% per 12 hours including tip claims. This is for purposes of maintaining a stable validator set for bridging efficiency. Once the 5% change is hit, new validators will need to wait until the rolling percent change per 12 hours is under the cap. This 5% is a parameter that can be changed via governance.

### Dual Delegation - Reporting vs Validating

Tendermint uses a delegated proof-of-stake(dPoS) model where there is a set number of validators, but all token holders can delegate to validators to increase security and share in rewards. Tellor uses this delegation but adds a second delegation for reporting duties, which we refer to as **selecting**. Each token can be used as a stake for reporting and for validating. Parties can delegate both the reporting and validating to the same party, to different parties, or even to themselves. The same token is subject to slashing by either method (reporting data or failing to honestly validate the chain) and the stake balance for both delegations is reduced immediately upon either consequence, so great caution should be taken when delegating and/or selecting.

Figure B: Dual delegation

*Note: The delegated validator and the selected reporter can be different(A), the same(B), mix of yourself and others(C).*

The reason for this dual delegation is that validator sets are capped in tendermint based systems, however we need to remove that cap to enable smaller and more reporters to help decentralize the data provider set. Additionally, the cost of bridging is directly tied to the validator set size (verifying signatures for the light client bridges), so a large validator set such as Ethereum is unfeasible for our intended uses (the need for fast, cheap bridging of data).

## Tokenomics

TRB is the native currency of the chain and used for staking, tipping, dispute fee and voting. All tokenomics will remain the same (as it is hardcoded and cannot be changed). Four thousand tokens will continue to be the dev share to the team each month and an equivalent amount of tokens will be distributed to reporters and validators as inflationary rewards. Seventy-five percent of time based rewards go to reporters with the other twenty-five percent are given to validators.

Gas fees go to the block proposing validator (selected randomly by validator weight), while tips and inflationary rewards to reporters are distributed proportionally to the reports submissions based on weighted validator support. As an example, if a query is submitted for and gets 50% of the stake contributing to the aggregated value, this report gets some inflationary rewards, however if a more supported query gets submitted for with 100% of total stakes reporting for it, this gets 2x the rewards as the first value. There is no benefit being the only reporter for a query, unless of course there are tips that support that query over others. Additionally, to prevent tips on queries that only a handful of reporters support, time based rewards are only available on cycle list queries.

The goal is to get broad support among as many queries as possible without either incentivizing parties to report things that no one needs (e.g. report an obscure query that only one reporter supports) or disincentivizing reports of new queries. Tips are still, and should, be used as the primary incentive mechanism used to garner support for a given query.

## Bridging

### Updating the Validator Set

The bridge was initialized with a starting validator set. Whenever the Tellor validator set changes by 5%, all validators sign this new validator set checkpoint. This 5% threshold helps limit bridging costs as updating the validator set in the bridge contract costs gas. These signatures are used to update the bridge's record of the validator set, and any new data proofs do not pass the bridge's checks until the new validator set is relayed. Like data proofs, the bridge accepts a validator set update if at least ⅔ of the last known validator set signed off on it.

### Tellor Token Bridge

The Tellor token is interchangeable between the current ERC20 TRB contract on Ethereum and the base token TRB on Tellor. It is secured by a two way bridge, operated by Tellor itself via a light client bridge.

Bridging TRB from Ethereum to Tellor takes 13 hours. Once the deposit is made, Tellor reporters can report this information to Tellor for an hour (to allow for a high level of finality on Ethereum). Once that one hour window is closed, the deposit can be claimed 12 hours later on Tellor. A party bridging TRB to Tellor for the first time will not have TRB available on Tellor to pay the required gas fee to claim the deposit so deposits are automatically claimed after the waiting period (12 hours).

In order to prevent attacks, withdrawals from Tellor can only be done if unstaked from being a validator on Tellor (which requires 21 days). Once a withdrawal is initiated and attested to by validators, it can be retrieved on Ethereum 12 hours later. As an additional security measure, the bridge contract does not allow more than 20% of the bridge balance to be bridged to Tellor and 5% from Tellor to Ethereum within a 12 hour period (the function is locked). We have prioritized security over speed on the token bridge.

Staking is still growing on Tellor chain and the cost of capture increases as staking grows. To allow safe growth, anyone in the community that suspects Tellor chain has been compromised can propose a bridge pause by paying 10,000 TRB which will be burned if the pause is approved by the team's multisig(this permission can be removed). Once the chain is forked, the community can slash the malicious actor and compensate the pause proposer. The bridge can be unpaused after 21 days by anyone. It's worth noting that even if the token bridge is paused, data can still be produced by the chain as consensus and rewards happen on the chain.

### Data Bridge

Tellor can be used as a push or pull oracle and both implementations require validation of Tellor's validator set via light client bridge contract. A light client bridge is needed on each chain and parties relay the requested data and signatures as well as information related to validator set updates and chain upgrades. Anyone can deploy a light client bridge contract and **relaying** is a trustless and permissionless role, meaning that anyone can push validator signatures from Tellor to validate data on the data bridge contract. However, additional, access controls can be put in place at the chain or user contract level by the user.

#### Signing Prices

Once a value is aggregated (finalized in a given block), all validators sign the information. The resulting signatures allow users to access the value, timestamp, aggregate power (amount of reporter stake used in aggregation), previous report timestamp, and next report timestamp of a given query. The previous report timestamp and next report timestamp by queryID are included for proving various properties of a given report.

Where: *data = value, timestamp, aggregatePower, previousReportTimestamp, nextReportTimestamp*

Validators will: *sign( queryId, data, validatorCheckpoint, attestationTimestamp )*

Parties using Tellor can then grab the signatures and relay it to their chain.

Users can also request new signatures for data from previous blocks, (e.g. request(queryId, timestamp)) and the chain will return signatures on the older data, but with a newer attestationTimestamp. This is so parties can use values optimistically, by checking that the data has stayed on Tellor for a certain amount of time without disputes, as data that has been disputed will not be signed again.

#### Relayer

The relayer (pushing signed data from Tellor to user chains) can be done by **anyone**. We provide software for relaying values and tipper scripts for setting up recurring feeds. Many keeper services also could fill this role (Keepr, Gelato, etc.).

#### Relay fallback

If there are no updates to a given light client bridge for >21 days (the unbonding period on Tellor), then the bridge is considered stale, a situation where it needs a manual update of the validator set. To address this, the light client bridge includes a function for a guardian to be able to update the validator set manually after 21 days. Anyone can deploy the light client bridge and set themselves as the guardian or remove that capability. There can be multiple light client bridge contracts on a chain. For most use cases, missing data for more than 21 days would be a severe failure condition and should trigger the users to relay themselves (unless the users or the chain are dead or some other extreme event has occurred, in which case, the guardian becomes immaterial).

The Tellor team will deploy light client bridges with the team's address as a fallback that can update the validator set but users are not required to use these (these will act as a public good). If parties do not want it to fallback to the team, they can simply update the validator set before the 21days or deploy a light client bridge where it falls back to a different address (or remove that functionality).

####

#### Other cross-chain methods

We know that some parties already have existing bridge solutions that they prefer. Tellor data can be used via any of these solutions and we look forward to building and working with the teams to deliver the fastest and most secure solution for users. Some potential usage solutions include IBC, Hyperlane, Succinct and many more.

In the future, it is likely that native or zero-knowledge bridges will be used to verify signatures, consensus, as well as inclusion of values. Tellor will be leaning on other teams currently specializing in cryptography research, but we fully expect that all bridges will be cheaper and faster using this method and should be operational within the next cycle.

Figure C: Tellor process of aggregation, attestation, and relaying data to other chains.&#x20;

Note: Staked reporters, staked validators, users and relayers, and data monitors are all permissionless roles.

## Data Usage

Reporters are not required to provide data for all queries. This creates two types of data on-chain, *robust data* and *edge data*. Robust data is data that reaches consensus or support from ⅔ of the reporters and validators, while edge data can be any data that did not. While confidence on both types of data increases as time goes by (no disputes or forks in the case of robust data), they have to be used differently.

### Robust Data Usage

If ⅔ of Tellor reporters sign off on a value, it is considered robust (aka consensus data) and it can be consumed faster. A relayer will grab the desired data and signatures and push it to the consumer chain. Parties can then use the information in their protocol. There is no need to validate it any further, however waiting could be helpful, if only in extreme cases (e.g. large price moves), to check for forks, or widespread dispute conditions (e.g. a protocol or exchange failure/hack where api information may not properly reflect desired data specifications). In most cases however, this method will allow for updates as fast as the chain itself.

Robust data can be consumed instantly only if it is assumed that the Tellor validator set is not compromised (signed off on bad data to the bridge or in the chain). However unlikely it is that the validator set would be compromised we advise implementing some precautions when using the data immediately. Users can run or whitelist relayers on their contracts and/or run monitoring tools, not allow immediate withdrawals, system freezes, etc. as necessary. See the **Additional Self-Driven Security and Fallbacks** section for more information.

### Edge Data Usage

Similar to robust data usage, parties request signatures and relay data from Tellor. However, edge data (aka optimistic data) should be handled optimistically, meaning that the user should allow time for a dispute to be raised and before using the data validate that the timestamp returned is within the needed period of relevance (old enough to allow for disputes but fresh enough to use). They can either use an older value (similar to current Tellor), and/or verify that X% of validators signed off on it.

## Additional data security

### Dispute Monitoring

Dispute monitoring is beneficial for both robust and edge data. However, this is especially important when parties are using edge data; they must be cognizant that the system is only as secure as the monitoring for disputes. If, for instance, a party requests an obscure piece of data that only one validator reports for, and their stake is low, there will likely be few parties checking this query for disputes. This is why if using an edge value, adding extra security is essential[^6]. Running your own dispute monitor, educating more reporters to support it, or even more secure measures such as using only if the median is within x% of a given (e.g. their own team's) reporter.

Successful disputes earn the majority of the slashed amount of the disputed party so there is also an economic incentive for anyone to run a monitor[^7].

### Optimistic as Fallback

If consensus fails on certain values that are typically robust, parties have two choices: wait for consensus to return or handle the edge value, optimistically as specified above. This could be a great option for some parties using data where quality can quickly change. A price feed for example might not come to consensus in times of api failures or exchange manipulations (e.g. feeds go down). In this case, it might be best to pause the system, but they could also go with the optimistic approach if their protocol needs a faster (albeit still slower than consensus) price. Note that in most cases, an uncertain value would NOT be pushed to your protocol. Tellor is unique in that rather than forcing reporters/validators to sign off on an api or price feed, the addition of their value is optional. This means that if a reporter is not certain it's a valid value, they will likely just sit out that round(not risk their stake or part of it) and the value will not reach consensus; something that should be seen as a good thing in cases where ambiguity still exists (e.g. two exchanges differ wildly on price).

### Additional Self-Driven Security and Fallbacks

Although security is at the center of Tellor's design, consumers of Tellor data can add custom additional security. Manipulation attacks should always be considered by users. There are many examples where using the oracle value immediately has led to exploits or unintended consequences. **Data manipulation attacks are oracle agnostic** and have occurred even when the oracle was centralized. But users can implement user level controls to mitigate losses and even dissuade attackers. One of the bigger players[^8] in the crypto space includes pauses, delays throughout their system, a one hour delay before using the oracle value, debt ceilings and other governance delays. They are proof that you can become a big player and be responsible.

Monitors, delays and pauses are useful because if the oracle is compromised in any way it allows users to react: overwrite, update the databank address, get a governance vote in, etc... However unlikely the scenario, users can implement controls to protect themselves and their users if the data is manipulated directly or by compromising the data provider/node, validator or reporter set.

One way is to simply limit who can push prices/ state updates on the consumer chain. By adding validation at this level, chains could use either their own validators or stakers to push over the prices after validating them. This would be an excellent option for users with this level of ownership over their protocol.

An option for non-chains via the low latency model would be to add validation before a trusted party (e.g. the app's dao) pushes the data. It gives the trusted party an option to censor, but they would be unable to change what the price is, something that would work similarly to a multisig having pause authority/control over a protocol. Users can also do OEV limits this way (relayer is a known party or even auction off the right for OEV[^9] each day/month).

Another option to increase security is consumer side pauses and delays. Pausing the system could be similar to the Maker design, where token holders of their own system can freeze the system in the case of a bad value[^10] or trust a curator or committee (multisig) to do it for them. For delays, parties could just design a system where the oracle value is used after X amount of time or it costs X dollars (a large amount) to delay the use of a reported value. While delayed, they could initiate a dispute on the Tellor system to remove a reporter or evaluate the situation. This would work well for systems that can handle delays (e.g. a prediction market delaying payouts). Just note that this would be on a per-user basis and custom as the cost to dispute/pause is also the cost to censor if it freezes the system for certain protocols.

Users can also add disputes directly in their protocol similar to Tellor's disputing system, but can be handled by their governance. This would work well if coupled with custom staking requirements for reporters and could also be added as the "trusted" party that the Tellor value must match. A user side based dispute mechanism could also allow falling back to a more robust data feed such as going from a VWAP to TWAP before a governance vote. This works well if the protocol allows a grace period for their users to challenge data and they have a payout delay, since disputes are only useful before settlement.

For numeric data, implementing caps or thresholds on changes between the previous value and the incoming value can also help limit losses in an attack scenario or help trigger a payout delay or data challenge period. This types of volatility caps are on per user and data feed basis.

Users can use multiple oracle feeds and use the median of these similar to how Ampleforth architecture uses Tellor or as fallback similar to how Liquity V1uses a primary and Tello as a fallback oracle.

Multiple oracles, oracle fallbacks, data feed fallbacks, pauses, payout delays, oracle use delay, thresholds caps for changes, overwriting the oracle value[^11] or updating the oracle address are options that provide a high level of control and can be modularly implemented at the users' discretion. Many of these options are used and/or have been used by protocols. Determining what level of control is right for your protocol, if these should be controlled via governance, a curator, or mutlisig is up to you, the user (and always provide proper disclosures of these levels of controls to your users).

These options require a higher level of control and are optional. They add layers of security that is user driven based on their desired or required level of control and level of ownership over their protocol. Some of these controls are preventive while others allow users to be proactive in the event of a hack or manipulation event. Most of the blue chip crypto we see today was made possible because they grew in proportion with the industry. Bitcoin's and Ethereum's market caps were very low when they first launched and could have been easily captured and manipulated too. However, incentives to capture or hack a protocol will always exist when the cost of attack is lower than the gain. Newer protocols need an environment in which they can thrive and grow securely. They need to be treated differently than blue chip crypto assets. Blue chips are harder to manipulate and capture than low liquidity and emerging assets/protocols. Additionally, the user can choose to implement these guardrails temporarily or not(for most of these, removing the control could be as easy as throwing the controlling address or removing it automatically if a market cap, liquidity, stake amount threshold or a combination of these is surpassed).

## Fork Choice

Upgrades and forks to Tellor will likely happen. Upgrades in the form of better data aggregation techniques, changes to the consensus protocol(e.g. cosmos sdk updates for faster blocktimes), or even changes to the Tellor system to make it more secure. Hard forks on the other hand are security based and happen if the protocol is attacked, compromised, or broken in some way.

### Soft Upgrades

For each chain using the Tellor protocol, we can have a mapping of chainID to a valid contract address for the verification of the data/protocol. In order to change it, a new light client bridge contract with the updated code will be deployed on the EVM chain. Validators will then update the mapping, and propose a change on the consumer chain. Then after waiting 14 days (allows for users to exit if malicious), the address will be updated to the new validator contract.

### Hard Forks

For hard forks, you will also have a way to update this proxy address for verification of the consensus mechanism. The issue here is that time is of the essence. If the validator set is compromised or a bug is found, parties will want to very quickly switch off the oracle and upgrade. Unfortunately, the switch cannot happen quickly, but freezing should be possible.

## Plan for legacy Tellor contracts

Tellor currently has users on Ethereum, Polygon, Gnosis, Arbitrum, Mantle, zkEVM, zkSync, BOB and Optimism.

Tellor contracts are immutable, so users of the contracts can continue to use the contracts as they do currently. Users need to continue to incentivize reporters to stay on other chains posting data (tip) and should migrate over time as they upgrade their contracts or launch new systems.

The current TRB token contract remains the same, on Ethereum. But instead of minting the time based rewards to the oracle contract it sends these rewards to the bridge contract. The bridge contract has an oracle proxy that allows legacy Tellor users to read data from Tellor (the light client contract).

The reason the oracle tokens are given to the bridge is to allow a two way bridge since inflationary rewards happens on Tellor based on the bridged tokens.

## Conclusion

Tellor is an open network where anyone can validate, report data, request any data, dispute data, and help settle disputes via staking and fees. These properties uniquely position Tellor for no friction integrations by users or AI agents alike[^12]. Tellor is crypto-economically secure with measurable security and users can layer additional security controls. There is no one way to make protocols 100% immune to manipulation or capture but security can be layered to meet each users' needs.\
\
Tellor's architecture aims to remain permissionless and censorship resistant but applications using it can choose to embody the same properties or add controls on top of it. This is similar to how applications on Ethereum can implement higher levels of control over their system without compromising Ethereum's properties.

### Glossary

1. **Tellor and Tellor Layer:** A standalone Layer 1 (L1) blockchain built using the Cosmos SDK, designed for consensus on subjective data using tendermint and an optimistic approach.
2. **Cosmos SDK**: A software development kit for building blockchains in the Cosmos ecosystem.
3. **Tendermint/ Comet BFT:** A Byzantine Fault Tolerant (BFT) consensus algorithm used by blockchains in the Cosmos network.
4. **Validator:** An entity in the Tellor network that has locked a certain amount of TRB tokens to participate in block validation.
5. **Reporter:** An entity in the Tellor network responsible for submitting values for data requests (queryIDs). Reporters can be staked validators or other participants, depending on the network's rules. They provide data, incentivized through tips, subject to validation and potential disputes.
6. **Query:** A unique identifier for a data request (e.g., BTC/USD price) on the Tellor.
7. **TRB Token:** The native cryptocurrency of Tellor, used for staking, tipping, and governance.
8. **Cycle List:** A governance-controlled list of queryIDs to maintain data freshness and ensure continuous reporting.
9. **Consensus Threshold:** The minimum amount of agreement required among validators for a value to be considered valid.
10. **Disputing**: A process in Tellor where reporters' submissions can be challenged, potentially leading to slashing of their stake.
11. **Slashing Event:** A penalty where a portion of a validator or reporter's stake is removed due to submission of incorrect data or other violations.
12. **Tipping:** A system where users can tip reporters in TRB tokens for submitting data for specific queryIDs.
13. **Relayer:** An entity that transmits data from the Tellor to other blockchains, facilitating cross-chain data accessibility and usage
14. **Robust Data Usage:** A data verification method in Tellor where values agreed upon by a supermajority of reporters are instantly deemed reliable for real-time use.
15. **Edge Data Usage:** A method of using Tellor where submitted values are presumed correct if not disputed over a period of time, and/or X% of validators signed off.
16. **Light Client Bridge:** A mechanism for relaying Tellor data to other blockchains.
17. **Validator Nonce:** A unique number used once by validators to prevent replay attacks.

### Footnotes

[^1]: This is an ultimate test of decentralization. But team and community contributors help ensure protocols evolve with the times and improve as new technology becomes available.

[^2]: Because of the competitive forces in Tellor, validators, reporters, users, and disputable value monitors(many of which are other validators and reporters) a reporter and bad value would be disputed almost immediately. Users and monitors can observe data real time on-chain for Tellor and dispute before it has the chance to get to their mempool and be subject to MEV and OEV. Transparency helps prevent our users from ingesting bad data because it does not wait until after the fact for disputes and slashing and has direct bounty to incentivize watchdogs/monitors.

[^3]: "Jail" is a concept in the tendermint system where the validator (or reporter in this case) is locked out of participating for a certain period of time

[^4]: Checkout our ADR 1008 on voting power by group for more information on why validators are not part of it <https://github.com/tellor-io/layer/blob/main/adr/adr1008%20-%20voting%20power%20by%20group.md>

[^5]: Users that need the same data feeds can crowdsource tips. On-chain tips make costs transparent and AI agents can interact with Tellor easily as they can request support for new data without needing humans to sign a contract.

[^6]: More information on Tellor's security can be found here: <https://tellor.io/blog/layer-security-201/>

[^7]: An open-source disputable values monitor is available

[^8]: Sky (formerly MakerDAO) is one of the longest running DeFi apps and they still employ a one hour delay on their oracle updates. <https://developers.skyeco.com/security/security-measures/security-mechanisms/#oracle-price-delay>

[^9]: Oracle extractable value

[^10]: Depending on the type of data, this is a best practice for any system using an oracle

[^11]: Hyperliquid validators overwrote and delisted $JELLY when attacked last year. This works well for protocols with this level of ownership and fair disclosure to their users <https://rekt.news/hyperliquidate2>

[^12]: Unlike other oracles, the team does not have to approve new data feeds or whitelist users or data reporters, instead AI agents can handle submitting a data specification to the community and tip to start getting data without the team intervention.


# Bridging TRB

Lock your TRB on Ethereum, receive funds on tellor

### Prerequisites

* Ethereum wallet with [TRB](https://etherscan.io/token/0x88df592f8eb5d7bd38bfef7deb0fbc02cf3778a0?a=0x8cfc184c877154a8f9ffe0fe75649dbe5e2dbebf).
* A [recieving address](/tellor/running-tellor/manage-accounts) on Tellor layer.

### How to Deposit:

Navigate to [hub.tellor.io](https://hub.tellor.io/).

Click the "bridge" circle. Then click "Connect Wallet" and connect your Ethereum wallet. (screenshot below)

Fill out the "TRB" field with the amount that you want to bridge to Tellor. Fill in the "to address" field with your tellor prefix account and approve the transaction in your wallet extension pop-up.

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2Ffm0eAcelbp32ge7UzZbb%2FScreenshot%20From%202025-11-17%2011-10-47.png?alt=media&amp;token=e5c56e63-c29e-44d6-a1a0-9a5e58fdd3ca" alt=""><figcaption></figcaption></figure>

Click "Approve Deposit" and sign the proposed transaction with your ethereum wallet, then click "Bridge to Tellor" and do the same.

**After a 12 hour security delay, your balance of TRB will arrive in your tellor wallet automatically.** Congrats! This is a great time to pop into the [tellor discord ](https://discord.gg/tellor)and say hello!

### How to Withdraw (bridge back to Ethereum):

Navigate to [hub.tellor.io](https://hub.tellor.io/).

Click the "bridge" circle. Click "Connect Wallets" to connect your Ethereum wallet and your keplr wallet. (The keplr wallet must be the one that holds your funds on Tellor Layer.)\
\
Then also click "To Ethereum" as shown in the screenshot below.

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2FMPUOVSWudgMcNO5M4p6B%2FScreenshot%20From%202025-11-17%2011-21-04.png?alt=media&amp;token=3ff6176f-0da3-42d9-a3d1-9c3c66d455dd" alt=""><figcaption></figcaption></figure>

Fill in the fields with your ethereum address and the amount of TRB that you would like to withdraw Click "Request Withdrawal" and sign the transaction with keplr.\
\
Wait 12 hours.

After 12 hours have passed, connect your wallets again (if necessary) and you should see two buttons next to your withdrawal details in the Withdrawal Transactions table.

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2F62yBG81EeUXhZxuRQEeC%2FScreenshot%20From%202025-11-17%2011-16-51.png?alt=media&amp;token=168604e2-c591-448b-bb18-85ef93251f55" alt="" width="323"><figcaption></figcaption></figure>

Click "Request attestation" and sign the tx with your keplr wallet.\
Click "Claim Withdrawal" and sign the tx with your ethereum wallet. The funds should arrive immediately.

### Backup Method:

If the bridge page is ever unavailable, use etherscan.

{% content-ref url="/pages/smAR9b8NuurWSoRyYAbI" %}
[Etherscan Method (Deposits)](/tellor/bridging-trb/etherscan-method-deposits)
{% endcontent-ref %}

If you want to make a withdrawal request using the layerd CLI:

{% content-ref url="/pages/I1FkqDvOqZZlehQrce3p" %}
[Request a Withdrawal via CLI](/tellor/bridging-trb/request-a-withdrawal-via-cli)
{% endcontent-ref %}


# TRBBridge Contracts Reference

Record of Contract Addresses

#### **Mainnet**

* TRBBridge: [0x6ec401744008f4B018Ed9A36f76e6629799Ee50E](https://etherscan.io/address/0x6ec401744008f4B018Ed9A36f76e6629799Ee50E)
* TRB ERC20: [0x88df592f8eb5d7bd38bfef7deb0fbc02cf3778a0](https://etherscan.io/address/0x88df592f8eb5d7bd38bfef7deb0fbc02cf3778a0)

#### **Sepolia**

* TRBBridge: [0x55355157703A44f7516FBB831333317E98944e32](https://sepolia.etherscan.io/address/0x55355157703A44f7516FBB831333317E98944e32)
* TRB ERC20: [0x80fc34a2f9FfE86F41580F47368289C402DEc660](https://sepolia.etherscan.io/address/0x80fc34a2f9FfE86F41580F47368289C402DEc660)


# Etherscan Method (Deposits)

How to use Etherscan to "manually" bridge TRB to Tellor Layer.

***Bridge requests can usually be sent to Tellor via*** [***https://hub.tellor.io/***](https://hub.tellor.io/)***. A block explorer can be used as a secondary method using the steps shown below.***

### 1. Approve the bridge contract

Navigate to the TRB [contract](/tellor/bridging-trb/trbbridge-contracts-reference)'s contract tab. Click the button for "Write as Proxy" (image below)

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2FHar3ha6BhMQfVwi9o4wB%2FScreenshot%20From%202025-11-17%2012-15-14.png?alt=media&amp;token=63e4af33-3242-49af-9a3f-4a29c09d8dce" alt=""><figcaption></figcaption></figure>

On the Contracts tab, click on function `2. approve`\
Set spender to be the [bridge contract address](/tellor/bridging-trb/trbbridge-contracts-reference).

Set the `_amount` to be the amount that you want to bridge e.g. `25000000000000000000 (25 TRB with 18 decimals)`

Click "Write" and confirm the transaction in your wallet.

### 2. Make the bridge request (depositToLayer)

Navigate to the [TRBBridge contract](/tellor/bridging-trb/trbbridge-contracts-reference)'s contract tab. Click the button for "Write as Proxy".

Connect your wallet and click function `3. depositToLayer`.

Set the \_amount to the amount of TRBP that you want to bridge, e.g. 10000000000000000000 (10 TRBP + 18 decimals).

Set the `_tip` to 10000000000000000 (0.01 TRB). This is a tip that can be claimed by any validator or reporter over on layer who is willing to pay the gas to claim your bridge request for you!

Set `_layerRecipient` to your tellor prefix address on layer. If you don't have an address yet, see steps to Create an account on Layer [here](https://docs.tellor.io/tellor/running-tellor/manage-accounts).

<figure><img src="https://docs.tellor.io/~gitbook/image?url=https%3A%2F%2F2729899787-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252Fs90SVtIdiQ8dmMsqriIa%252Fuploads%252FTWQVieJBEBj2jfPXa887%252FScreenshot%25202025-02-06%2520at%252012.22.28%25E2%2580%25AFPM.png%3Falt%3Dmedia%26token%3D4c9762d2-d0fe-49fe-a9be-88c175e63614&#x26;width=768&#x26;dpr=4&#x26;quality=100&#x26;sign=92b3f40e&#x26;sv=2" alt=""><figcaption></figcaption></figure>

Click Write and confirm the transaction.

### 3. Wait 12 Hours

There's a 12 hour delay to secure deposits. While you're wait it's a great opportunity to join the [tellor discord ](https://discord.gg/tellor)and say hello! After 12 hours have passed, your tokens should arrive in your wallet automatically.


# Request a Withdrawal via CLI

How to use Etherscan to "manually" bridge TRB back to Ethereum.

#### 1. Request your withdrawal via cli.

The withdraw-tokens command is used to initiate a withdraw of "loose" TRB from tellor layer:

```sh
./layerd tx bridge withdraw-tokens [creator] [recipient] [amount] [flags]
```

\[creator]: Your tellor layer account's tellor1 prefix address.

\[recipient]: An ethereum address that you control. (Used to claim the tokens.)

\[amount]: The amount that you want to withdraw in loya (Note: 1 TRB = 1000000loya)

Full example requesting a withdrawal of 23 TRB:

{% code overflow="wrap" %}

```sh
./layerd tx bridge withdraw-tokens tellor1qw46ez58fjmp29f4r0a66278fyrhc4n4px9xyv 0xEcEFCC185418D7266E67C8a6374E580a187C0D1d 23000000loya --from ACCOUNT_NAME --fees 7loya --chain-id tellor-1 # or layertest-5 for testnet TRB
```

{% endcode %}


# Manual Generation of Bridge Query Data / IDs

Just in case

Navigate to [https://querybuilder.tellor.io](https://tellor.io/queryidstation/)[/](https://tellor.io/queryidstation/).

***This tool can be used to generate many different types of Query Data and Query Id for any Tellor data. Here's how to do it for Tellor bridge transactions.***

* Click on custom query.
* Enter `TRBBridge` for the type.
* add a `bool` parameter. Set it to true for requests "to layer". Set this to "false" for withdraw requests.
* add a uint256 parameter for the deposit Id.

See image below:

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2FoSg1ji15BlUmW1SeL6XK%2FScreenshot%20From%202025-04-01%2021-18-22.png?alt=media&amp;token=5c916d52-70cd-45be-bd19-992423690ae8" alt=""><figcaption><p>Great!</p></figcaption></figure>


# Getting Started

Instructions and guides for using tellor.

If you want to learn how to run a tellor node, validator, and/or reporter, you are in the right place!

{% content-ref url="/pages/zXXni5KIAX2Mt1fjzM6g" %}
[Bridging TRB](/tellor/bridging-trb)
{% endcontent-ref %}

{% content-ref url="/pages/l5Q2fEkXjbYFJctsJCF8" %}
[Node Setup Quick Start](/tellor/running-tellor/node-setup-quick-start)
{% endcontent-ref %}

{% content-ref url="/pages/VOfVkna3KL5XzWv8ZTjH" %}
[Node Setup Manual](/tellor/running-tellor/node-setup)
{% endcontent-ref %}

{% content-ref url="/pages/DAKZ2jUx9ZdDdE0GuHS0" %}
[Run a Tellor Validator](/tellor/running-tellor/run-a-layer-validator)
{% endcontent-ref %}

{% content-ref url="/pages/D2O8lp4TQCUIdVSSKyB0" %}
[Run a Data Reporter](/tellor/running-tellor/run-the-data-reporter)
{% endcontent-ref %}

{% hint style="success" %}
Taking the time to run a practice valiator on palmito testnet before running a mainnet validator is highly recommended!
{% endhint %}

{% hint style="success" %} <mark style="color:orange;">**Note:**</mark> *This is a guide for setting up a Tellor public testnet validator / reporter. Care is taken to provide info on the tools being used, but testers should be comfortable with running experimental code via command line interface. A beginner’s understanding of the cosmos SDK is highly recommended!*
{% endhint %}

{% hint style="info" %} <mark style="color:orange;">**Disclaimer:**</mark> participation as a Validator and / or Reporter involves using experimental software. If used in a mainnet context, the commands in this documentation WILL have consequences for real funds. Proceed with caution and ensure that you understand the responsibilities and risks associated with participation.
{% endhint %}


# Managing Accounts

Follow the steps to make and manage your \`tellor\` account.

{% hint style="info" %} <mark style="color:blue;">**Please Read Security Tips:**</mark>

* When you create a new account with the `layerd keys add` command, the output will include the mnemonic. If you want to save your mnemonic, this is the only opportunity to do so. Make sure you copy it to a secure location, because anyone who sees these words can use that wallet as their own!
* This guide uses the "test" backend for easy compatibility with the reporter daemon. More secure options are as documented in the cosmos SDK and [these are all compatible](https://docs.cosmos.network/v0.46/run-node/keyring.html) with tellor layer.
* Once you have your validator node set up, it is good practice to make a secure backup of your whole `.layer` directory just in case! A validator is difficult to recover without the node\_key, priv\_validator\_key, and priv\_validator\_state.
* **Never use the same address for running a validator on mainnet which has been used for running a validator on the testnet! If you do this you will be slashed when another validator submits your testnet signatures as evidence of bad behavior on mainnet.**
  {% endhint %}

If you do not yet have an account / mnemonic phrase, Generate a new key pair with the command:

```sh
./layerd keys add $ACCOUNT_NAME --keyring-backend test
```

{% hint style="warning" %}
Be sure to <mark style="color:orange;">**copy the entire output**</mark> with the mnemonic and keep it in a very safe place!
{% endhint %}

If you already have an account, you can Import it with the command:

{% code overflow="wrap" %}

```sh
./layerd keys add $ACCOUNT_NAME --recover=true
```

{% endcode %}

To print the "tellor" prefix address to the terminal:

```bash
./layerd keys show $ACCOUNT_NAME
```

Next, add the `--bech val` flag to get the "tellorvaloper" prefix address, which is used for validator commands:

```bash
./layerd keys show $ACCOUNT_NAME --bech val
```

It can be useful to add these addresses to your `.bashrc` or `.zshrc` file. Be sure to replace `your_tellor_prefix_address` and `your_tellorvaloper_prefix_address` in your command:

{% code overflow="wrap" %}

```bash
echo 'export TELLOR_ADDRESS=your_tellor_prefix_address' >> ~/.bashrc #.zshrc if mac
echo 'export TELLORVALOPER_ADDRESS=your_tellorvaloper_prefix_address' >> ~/.bashrc #.zshrc if mac
```

{% endcode %}

Restart your terminal, or use `source ~/.bashrc` before you continue. (if Linux)

Restart your terminal, or use `source ~/.zshrc` before you continue. (if mac)

{% hint style="info" %} <mark style="color:blue;">Check accounts any time with:</mark> `./layerd keys list`
{% endhint %}


# Node Setup Quick Start

Use the guided setup shell scripts!

### 1. Install Prerequisites:

{% tabs %}
{% tab title="Linux" %}
jq, yq, sed, curl, wget, make, and **Go** are required for running the various commands and config scripts and commands in this guide:

* **`jq` :** `sudo apt install jq`
* **`sed` :** `sudo apt install sed`
* **`curl`**: `sudo apt install curl`
* **`wget`** : `sudo apt install wget`
  {% endtab %}

{% tab title="MacOS" %}
jq, yq, sed, curl, wget, make, and **Go** are required for running the various commands and config scripts and commands in this guide:

* **`jq`:** `brew install jq`
* **`sed`:** `brew install sed`
* **`wget`**`: brew install wget`
  {% endtab %}
  {% endtabs %}

Download the latest binary:

{% tabs %}
{% tab title="Linux" %}

<pre class="language-sh" data-overflow="wrap"><code class="lang-sh"><strong>mkdir -p ~/layer/binaries &#x26;&#x26; cd ~/layer/binaries &#x26;&#x26; mkdir v6.1.7 &#x26;&#x26; cd v6.1.7 &#x26;&#x26; wget https://github.com/tellor-io/layer/releases/download/v6.1.7/layer_Linux_x86_64.tar.gz &#x26;&#x26; tar -xvzf layer_Linux_x86_64.tar.gz
</strong></code></pre>

{% endtab %}

{% tab title="MacOS" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.7 && cd v6.1.7 && wget https://github.com/tellor-io/layer/releases/download/v6.1.7/layer_Darwin_arm64.tar.gz && tar -xvzf layer_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

### 2. Download the script that matches your system:

Additional info about the scripts can be found [here](https://github.com/tellor-io/layer/tree/main/scripts/setup).

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
curl -O https://raw.githubusercontent.com/tellor-io/layer/refs/heads/main/scripts/setup/initial_config/configure_mainnet_linux.sh && chmod +x configure_mainnet_linux.sh
```

{% endcode %}
{% endtab %}

{% tab title="Mac" %}
{% code overflow="wrap" %}

```sh
curl -O https://raw.githubusercontent.com/tellor-io/layer/refs/heads/main/scripts/setup/initial_config/configure_mainnet_mac.sh && chmod +x configure_mainnet_mac.sh
```

{% endcode %}
{% endtab %}
{% endtabs %}

### 2.1. Edit the environment variables (optional)

If you'd like to use a custom home directory, custom peers or RPCs you can configure those at the top of the script. The defaults are:

```sh
# ...
export LAYER_NODE_URL=https://mainnet.tellorlayer.com/rpc/
export RPC_NODE_ID=cbb94e01df344fdfdee1fdf2f9bb481712e7ef8d
export KEYRING_BACKEND="test"
export PEERS="5a9db46eceb055c9238833aa54e15a2a32a09c9a@54.67.36.145:26656,f2644778a8a2ca3b55ec65f1b7799d32d4a7098e@54.149.160.93:26656,2904aa32501548e127d3198c8f5181fb4d67bbe6@18.116.23.104:26656"
export LAYER_HOME="/home/$(logname)/.layer"
export STATE_SYNC_RPC="https://mainnet.tellorlayer.com/rpc/"
export KEY_NAME="test"
# ...
```

Use your favorite text editor to change these before running the script if desired.

```sh
nano configure_mainnet_linux.sh # if linux
# --or--
nano configure_mainnet_mac.sh # if mac
```

### 3. Give the script permission to execute, and run it:

```sh
./configure_mainnet_linux.sh # if linux
# --or--
./configure_mainnet_mac.sh # if mac
```

The script should greet you and begin the guided setup!

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2FIE1XgMAOR8lkQ9eqMnjv%2FScreenshot%20From%202025-07-31%2009-41-00.png?alt=media&amp;token=e333a28b-a700-4307-a1fb-39128848ca37" alt=""><figcaption></figcaption></figure>

### Options:

* **Snapshot sync**: Download a snapshot from a server, extract it into your data folder, and start the node. The node will need time to catch up downloading blocks. At the time of writing this takes about 3 hours to complete.
* **State sync**: Sync up to the network using snapshots from peers and a good RPC. At the time of writing this takes about 9 hours to complete.

{% tabs %}
{% tab title="Snapshot Sync" %}

* ***If you want to sync from a snapshot, be sure to select option 2 when asked if you want to set up a state sync, and option 2 again when asked if you want to start the node:***

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2F1aT54W3ponrxQpdI1DZ3%2FScreenshot%20From%202025-08-06%2021-32-28.png?alt=media&amp;token=353d8644-afff-4319-beb0-81a792be3161" alt=""><figcaption></figcaption></figure>

* Visit [http://layer-node.com](https://layer-node.com/) and use the example commands shown there to download and extract the latest snapshot.
* Move the chain data into your \~/.layer folder:

{% code overflow="wrap" %}

```sh
# 
mv -f .layer_snapshot/data/application.db ~/.layer/data/application.db
mv -f .layer_snapshot/data/blockstore.db ~/.layer/data/blockstore.db
mv -f .layer_snapshot/data/cs.wal ~/.layer/data/cs.wal
mv -f .layer_snapshot/data/evidence.db ~/.layer/data/evidence.db
mv -f .layer_snapshot/data/snapshots ~/.layer/data/snapshots
mv -f .layer_snapshot/data/state.db ~/.layer/data/state.db
mv -f .layer_snapshot/data/tx_index.db ~/.layer/data/tx_index.db
rm -rf .layer_snapshot/
```

{% endcode %}

* Start the node!

{% code overflow="wrap" %}

```sh
./layerd start --home ~/.layer --keyring-backend test --key-name KEYNAME --api.enable --api.swagger
```

{% endcode %}
{% endtab %}

{% tab title="State sync" %}

* ***To perform a state sync, simply choose option 1 when prompted, and option 1 again when asked if you want to start the node:***

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2FdpCbDmADKk8zDyTaiIfg%2FScreenshot%20From%202025-08-06%2021-30-24.png?alt=media&amp;token=d5c3985e-a74e-4343-a7f1-191156f786be" alt=""><figcaption></figcaption></figure>

* Start the node!

{% code overflow="wrap" %}

```sh
./layerd start --home ~/.layer --keyring-backend test --key-name KEYNAME --api.enable --api.swagger
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Node Setup Manual

How to Operate Tellor Node.

## Recommended Hardware Specs

Operating a node for a personal RPC can be done usin most modern computers. Even modest hardware should be fine for this purpose.

Operating a **validator:**

* Modern cpu with at least 8 cores / threads
* ram: 32 gb + (16gb swap space recommended)
* storage: 1000gb+ @ NVME gen4
* network: 500mb/s DL, 100mb/s UL (the faster the better)

### Software Prerequisites

{% tabs %}
{% tab title="Linux" %}
jq, yq, sed, curl, wget, make, and **Go** are required for running the various commands and config scripts and commands in this guide:

```bash
sudo apt install jq yq sed curl wget build-essential
```

Install go if you want to build binaries from the layer repo:

* `Go version 1.22` : Use the default install instructions [here](https://go.dev/doc/install).
  {% endtab %}

{% tab title="MacOS" %}
jq, yq, sed, curl, wget, make, and **Go** are required for running the various commands and config scripts and commands in this guide:

```bash
brew install jq yq sed wget && xcode-select --install
```

* `Go ≥ 1.22` : Use the default install instructions [here](https://go.dev/doc/install).
  {% endtab %}
  {% endtabs %}

{% hint style="success" %}

* Commands shown should just work while logged in as a user (using root is not recommended).
* **I**f you are using an older Mac with an intel chip, the linux versions (amd64) in step 1 below may be used. (just remember to use the mac commands!)
* If on raspberry pi or similar, use the binary downloads for "**arm64**".
  {% endhint %}

## Sync Method

These instructions use **state sync**: your node downloads a recent chain state snapshot from peers. This is the fastest way to get online, but you will not be able to query block info (like transactions) for blocks produced before the day of your sync.

## 1. Download and Organize the `layerd` Binary

{% hint style="info" %}
**As you progress through the steps, be sure to select the tabs that work for your setup! You will get errors if you use the linux commands on mac and vice-versa.**
{% endhint %}

First, download the binary from the [Tellor Github](https://github.com/tellor-io/layer/tags).

{% tabs %}
{% tab title="Linux" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.7 && cd v6.1.7 && wget https://github.com/tellor-io/layer/releases/download/v6.1.7/layer_Linux_x86_64.tar.gz && tar -xvzf layer_Linux_x86_64.tar.gz
```

{% endtab %}

{% tab title="Linux ARM64" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.7 && cd v6.1.7 && wget https://github.com/tellor-io/layer/releases/download/v6.1.7/layer_Linux_arm64.tar.gz && tar -xvzf layer_Linux_arm64.tar.gz
```

{% endtab %}

{% tab title="MacOS" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.7 && cd v6.1.7 && wget https://github.com/tellor-io/layer/releases/download/v6.1.7/layer_Darwin_arm64.tar.gz && tar -xvzf layer_Darwin_arm64.tar.gz
```

{% endtab %}
{% endtabs %}

Initialize .layer folder in your home directory:

```sh
./layerd init layer --chain-id tellor-1
```

## 2. Set System Variables

A Layer node uses the following variables:

* TOKEN\_BRIDGE\_V2\_ADDRESS: the token bridge contract address.

Set the environment variables so that they are set in new terminal windows by default. Open your .bashrc or .zshrc file with a text editor like nano:

{% tabs %}
{% tab title="Linux" %}

```
nano ~/.bashrc
```

{% endtab %}

{% tab title="MacOS" %}

```
nano ~/.zshrc
```

{% endtab %}
{% endtabs %}

Add these lines to the bottom of the file. Remember to replace the example `ETH_RPC_URL` with your actual Ethereum RPC url, and if you're going to run a reporter, replace the `REPORTERS_VALIDATOR_ADDRESS` with your own as well.

```bash
export TOKEN_BRIDGE_V2_ADDRESS="0x6ec401744008f4B018Ed9A36f76e6629799Ee50E"
```

Exit nano with `ctrl^x` then enter `y` to save the changes.

Load the new variables:

{% tabs %}
{% tab title="Linux" %}

```
source ~/.bashrc
```

{% endtab %}

{% tab title="MacOS" %}

```
source ~/.zshrc
```

{% endtab %}
{% endtabs %}

## 3. Edit Chain Configuration for Tellor.

We need to open up the tellor layer config files and change some variables. You can use any local text editor like code, vim, or nano.

***Note: All other variables can be safely left as is.***

In `~/.layer/config/app.toml`:

```sh
# The minimum gas prices a validator is willing to accept for processing a
# transaction. A transaction's fees must meet the minimum of any denomination
# specified in this config (e.g. 0.25token1,0.0001token2).
minimum-gas-prices = "0loya"
# ...
# Address defines the API server to listen on.
address = "tcp://0.0.0.0:1317"
#...
```

In `~/.layer/config/client.toml`:

```sh
#...
# The network chain ID
chain-id = "tellor-1"
# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory)
keyring-backend = "test"
#...
```

In `~/.layer/config/config.toml`:

```sh
#...
# TCP or UNIX socket address for the RPC server to listen on (optional)
laddr = "tcp://0.0.0.0:26657"
#...
# Use '["*"]' to allow any origin
cors_allowed_origins = ["*"]
#...
# Comma separated list of nodes to keep persistent connections to
persistent_peers = "5a9db46eceb055c9238833aa54e15a2a32a09c9a@54.67.36.145:26656,f2644778a8a2ca3b55ec65f1b7799d32d4a7098e@54.149.160.93:26656,2904aa32501548e127d3198c8f5181fb4d67bbe6@18.116.23.104:26656,7fd4d34f3b19c41218027d3b91c90d073ab2ba66@54.221.149.61:26656,2b8af463a1f0e84aec6e4dbf3126edf3225df85e@13.52.231.70:26656,9358c72aa8be31ce151ef591e6ecf08d25812993@18.143.181.83:26656,cbb94e01df344fdfdee1fdf2f9bb481712e7ef8d@34.228.44.252:26656"
#...
# How long we wait after committing a block, before starting on the new
# height (this gives us a chance to receive some more precommits, even
# though we already have +2/3).
timeout_commit = "1s"
#...
```

### 4. Sync the Node

*<mark style="color:green;">**Before starting your node**</mark><mark style="color:green;">,</mark> it's a good idea to think about how you want to run it so that the process does not get killed accidentally. This is not obvious for beginners. Try* [*GNU screen*](https://tellor.io/blog/how-to-manage-cli-applications-on-hosted-vms-with-screen/) *or tmux. More advanced setups can be achieved using*[ *systemd services*](/tellor/running-tellor/node-setup/example-.service-files)*.*

**We need to make a few more config edits to make sure your state sync goes smoothly.**

1. To find a good **trusted height** to use for a snapshot sync, we need to find the height of a snapshot available from `https://mainnet.tellorlayer.com/rpc/` . Copy and paste this entire block of commands into a terminal and hit enter:

```sh
export LATEST_HEIGHT=$(curl -s https://mainnet.tellorlayer.com/rpc/block | jq -r .result.block.header.height); \
export TRUSTED_HEIGHT=$((LATEST_HEIGHT - 35000)); \
export TRUSTED_HASH=$(curl -s "https://mainnet.tellorlayer.com/rpc/block?height=$TRUSTED_HEIGHT" | jq -r .result.block_id.hash); \
echo $TRUSTED_HEIGHT $TRUSTED_HASH

```

The output should be something like:

```sh
trusted height: 3785000
Trusted hash: DD27874AB1F5F4DFC5D7818E7CFBF8A8ECEDA745FFA78DF24D799B2B201418B9
```

2. Edit config.toml:

Open your config file:

```sh
nano ~/.layer/config/config.toml
```

Scroll or search (`ctrl^w`) the file and edit the state sync variables shown here to match the trusted height and trusted hash you found above:

```toml
# [statesync]
# ...
enable = true
#...
rpc_servers = "https://mainnet.tellorlayer.com/rpc/,https://mainnet.tellorlayer.com/rpc/"
trust_height = 3785000
trust_hash = "DD27874AB1F5F4DFC5D7818E7CFBF8A8ECEDA745FFA78DF24D799B2B201418B9"
trust_period = "168h0m0s"
```

Be sure to replace the `trust_height` and `trust_hash` with the block number and hash from the curl command above.

Exit nano with `ctrl^x` then enter `y` to save the changes.

3. Start your node:

{% code overflow="wrap" %}

```bash
./layerd start --home ~/.layer --key-name ACCOUNT_NAME --keyring-backend test --api.enable --api.swagger
```

{% endcode %}

The node should start up quickly and begin downloading a state snapshot from peers.

{% hint style="info" %}
Some errors related to peer connections can be expected even if the snapshot sync is working properly. (e.g. "we need more peers", or "Failed to reconnect")
{% endhint %}

To check if the node is fully synced, open a separate terminal window and run:

```sh
./layerd status
```

You should see a JSON formatted list of information about your running node. If you see `catching_up":false` that means that you're node is fully synced and ready to use!


# Peers List & Public RPCs

The following peers list can be used for syncing tellor mainnet

{% hint style="info" %}
If you followed the Node Setup section of these docs, you already have the latest peers list.
{% endhint %}

In your `~/.layerd/config/config.toml` file:

{% code overflow="wrap" %}

```json
# Comma separated list of nodes to keep persistent connections to
persistent_peers = "5a9db46eceb055c9238833aa54e15a2a32a09c9a@54.67.36.145:26656,f2644778a8a2ca3b55ec65f1b7799d32d4a7098e@54.149.160.93:26656,2904aa32501548e127d3198c8f5181fb4d67bbe6@18.116.23.104:26656,7fd4d34f3b19c41218027d3b91c90d073ab2ba66@54.221.149.61:26656,2b8af463a1f0e84aec6e4dbf3126edf3225df85e@13.52.231.70:26656,cbb94e01df344fdfdee1fdf2f9bb481712e7ef8d@54.234.103.186:26656"

```

{% endcode %}

RPC

* [https://mainnet.tellorlayer.com/rpc/<br>](https://mainnet.tellorlayer.com/rpc/https://mainnet.tellorlayer.com)

API:

* [https://mainnet.tellorlayer.com/](https://mainnet.tellorlayer.com/rpc/https://mainnet.tellorlayer.com)


# Cosmovisor Sync

Cosmovisor is a binary manager that can perform upgrades automatically.

## Prerequisites:

A Tellor node machine configured like [this](broken://pages/OzHKVqI8SaLRc9qfBb3m) is not required, but different setups may require different commands from the ones shown below.

## Build and configure Cosmovisor

1. **Clone the** cosmos repo somewhere on your node machine and change directory to `cosmos-sdk`

```sh
git clone https://github.com/cosmos/cosmos-sdk && cd cosmos-sdk/tools/cosmovisor
```

2. Build cosmovisor:

```sh
go build ./cmd/cosmovisor
```

3. Add the following to the end of your `~/.bashrc` or `~/.zshrc` file:

```
# cosmovisor
export DAEMON_NAME=layerd
export DAEMON_HOME=$HOME/.layer
export DAEMON_RESTART_AFTER_UPGRADE=true
export DAEMON_ALLOW_DOWNLOAD_BINARIES=false
export DAEMON_POLL_INTERVAL=300ms
export UNSAFE_SKIP_BACKUP=true
export DAEMON_PREUPGRADE_MAX_RETRIES=0
```

Use `source ~/.bashrc` or `source ~/.zshrc` to load the variables.

4. Initialize cosmovisor and add all the of the upgrades that you downloaded during [node setup](broken://pages/OzHKVqI8SaLRc9qfBb3m). Change the file paths in the command to match the correct folder path to each binary:

```shell
# set up cosmovisor. Each command is done seperatly.
./cosmovisor init ~/layer/binaries/v4.0.3/layerd
./cosmovisor add-upgrade v5.0.0 ~/layer/binaries/v5.0.0/layerd
./cosmovisor add-upgrade v5.1.0 ~/layer/binaries/v5.1.0/layerd
./cosmovisor add-upgrade v5.1.1 ~/layer/binaries/v5.1.1/layerd
./cosmovisor add-upgrade v5.1.2 ~/layer/binaries/v5.1.2/layerd
./cosmovisor add-upgrade v6.0.0 ~/layer/binaries/v6.0.0/layerd
./cosmovisor add-upgrade v6.1.0 ~/layer/binaries/v6.1.0-fix/layerd
./cosmovisor add-upgrade v6.1.1 ~/layer/binaries/v6.1.1/layerd
```

5. To start your node with cosmovisor managing upgrades:

{% code overflow="wrap" %}

```sh
./cosmovisor run start --home ~/.layer --keyring-backend test --key-name YOUR_ACCOUNT_NAME --api.enable --api.swagger
```

{% endcode %}

When a new upgrade is announced, follow the [Binary Upgrades](/tellor/running-tellor/node-setup/binary-upgrades#upgrading-with-cosmovisor) page to download the binary and run `add-upgrade` before the upgrade height.


# Binary Upgrades

Example commands for upgrading the layerd binary.

Use these steps when Tellor reaches a planned chain upgrade and your node stops at the upgrade height.

There are two upgrade paths depending on how you run your node:

* **Cosmovisor** — Download the new binary and register it with cosmovisor before the upgrade height. Cosmovisor swaps binaries and restarts the node automatically. See [Upgrading with Cosmovisor](#upgrading-with-cosmovisor) below.
* **Manual or systemd** — Download the new binary, optionally install it to your PATH, and restart the node yourself. Follow sections 1–3 below.

If you have not set up cosmovisor yet, see [Cosmovisor Sync](/tellor/running-tellor/node-setup/cosmovisor-sync).

## 1. Download the new binary

The new `layerd` binary version is `v6.1.8`. Choose the command for your machine:

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.8 && cd v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_x86_64.tar.gz && tar -xvzf layer_Linux_x86_64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Linux ARM64" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.8 && cd v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_arm64.tar.gz && tar -xvzf layer_Linux_arm64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="MacOS" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.8 && cd v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Darwin_arm64.tar.gz && tar -xvzf layer_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

Confirm the version:

```sh
~/layer/binaries/v6.1.8/layerd version
```

## 2. (optional) Install it in `~/go/bin/layerd`

Copy the new binary into `~/go/bin`:

```sh
mkdir -p ~/go/bin
cp ~/layer/binaries/v6.1.8/layerd ~/go/bin/layerd
chmod +x ~/go/bin/layerd
```

Make sure `~/go/bin` is in your shell `PATH` so new terminal sessions can find `layerd`. Edit with nano or use the commands below to add `export PATH="$HOME/go/bin:$PATH"` in your `.bashrc` or `.zshrc`

{% tabs %}
{% tab title="bash" %}

```sh
echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
```

{% endtab %}

{% tab title="zsh" %}

```sh
echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```

{% endtab %}
{% endtabs %}

Check that your shell is using the new binary:

```sh
which layerd
layerd version
```

## 3. Restart at the upgrade height

The node will stop and wait for the upgraded binary when the upgrade height is reached. When this happens, stop your node process. If you start the node manually, restart it with the new binary:

{% code overflow="wrap" %}

```sh
~/layer/binaries/v6.1.8/layerd start --home ~/.layer --key-name ACCOUNT_NAME --keyring-backend test --api.enable --api.swagger
```

{% endcode %}

If you run your node with systemd, update the `ExecStart` line in your `.service` file to point at the new binary. Use an absolute path instead of `~`:

{% code overflow="wrap" %}

```sh
ExecStart=/home/USERNAME/layer/binaries/v6.1.8/layerd start --home /home/USERNAME/.layer --keyring-backend="test" --key-name=ACCOUNT_NAME --api.enable --api.swagger
```

{% endcode %}

Then reload systemd and restart your service:

```sh
sudo systemctl daemon-reload
sudo systemctl restart layerd
sudo journalctl -u layerd -f
```

Replace `layerd` with the actual name of your service if it is different.

{% hint style="info" %}
Keep the old versioned binary directory until you are sure the node is running correctly after the upgrade.
{% endhint %}

## Upgrading with Cosmovisor

If you run your node with cosmovisor (see [Cosmovisor Sync](/tellor/running-tellor/node-setup/cosmovisor-sync)), register the new binary before the upgrade height. Cosmovisor handles the swap and restart automatically — you do not need to update systemd or restart the process yourself.

The new `layerd` binary version is `v6.1.8`. Choose the command for your machine:

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/v6.1.8 && cd ~/layer/binaries/v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_x86_64.tar.gz && tar -xvzf layer_Linux_x86_64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Linux ARM64" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/v6.1.8 && cd ~/layer/binaries/v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_arm64.tar.gz && tar -xvzf layer_Linux_arm64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="MacOS" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/v6.1.8 && cd ~/layer/binaries/v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Darwin_arm64.tar.gz && tar -xvzf layer_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

Confirm the version:

```sh
~/layer/binaries/v6.1.8/layerd version
```

Then register the upgrade with cosmovisor:

```sh
./cosmovisor add-upgrade v6.1.8 ~/layer/binaries/v6.1.8/layerd
```

{% hint style="info" %}
Run `add-upgrade` before the chain reaches the upgrade height. Keep the old versioned binary directory until you are sure the node is running correctly after the upgrade.
{% endhint %}


# State Sync Troubleshooting / Resetting Chain Data

Steps for resetting / re-syncing a state synced node (or recovering from a failed state sync).

## State Sync Failed!?

There are three main reasons why a state sync will fail:

* RPC connection fails, or is rate limited
* Not enough healthy peers / seeds configured
* Incorrect trusted height / trusted hash

### Steps to reset chain data without losing your accounts:

1\) Stop the node process with `ctrl^c` (or `sudo systemctl stop layer` if it's a service)

2\) Remove the chain data from `~/.layer/data/`, being careful to NOT delete the `priv_validator_state.json` file:

```sh
# Delete the binaries
# This is useful if you're not sure that you downloaded the right binaries:
rm -rf ~/layer/binaries

# deletes chain data
# This is useful if state sync fails and you need to try a different config
rm -rf ~/.layer/data/application.db; \
rm -rf ~/.layer/data/blockstore.db; \
rm -rf ~/.layer/data/cs.wal; \
rm -rf ~/.layer/data/evidence.db; \
rm -rf ~/.layer/data/snapshots; \
rm -rf ~/.layer/data/state.db; \
rm -rf ~/.layer/data/tx_index.db
```

Next, open up your configs.

```sh
nano ~/.layer/config/config.toml
```

Use `ctrl^w` to search, or scroll down to the `[p2p]` section.

```toml
#######################################################
###           P2P Configuration Options             ###
#######################################################
[p2p]

# Address to listen for incoming connections
laddr = "tcp://0.0.0.0:26656"

# Address to advertise to peers for them to dial. If empty, will use the same
# port as the laddr, and will introspect on the listener to figure out the
# address. IP and port are required. Example: 159.89.10.97:26656
external_address = ""

# Comma separated list of seed nodes to connect to
seeds = "f4786bc2a40172e29784b9f8d..."

# Comma separated list of nodes to keep persistent connections to
persistent_peers = "f4786bc2a40172e29784b9f8d69567c474d..."

# Path to address book
addr_book_file = "config/addrbook.json"

# Set true for strict address routability rules
# Set false for private or local networks
addr_book_strict = false

```

Try manually editing the seeds and persistent\_peers to match [those shown here](broken://pages/6obmvOkNkczgoNDiiU4c).

In most cases `addr_book_strict` can be safely changed to `true`.

Find the `[statesync]` section.

```toml
#######################################################
###         State Sync Configuration Options        ###
#######################################################
[statesync]
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in
# the network to take and serve state machine snapshots. State sync is not attempted if the node
# has any local state (LastBlockHeight > 0). The node will have a truncated block history,
# starting from the height of the snapshot.
enable = true

# RPC servers (comma-separated) for light client verification of the synced state machine and
# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding
# header hash obtained from a trusted source, and a period during which validators can be trusted.
#
# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2
# weeks) during which they can be financially punished (slashed) for misbehavior.
rpc_servers = "https://mainnet.tellorlayer.com/rpc/,https://mainnet.tellorlayer.com/rpc/"
trust_height = 217310
trust_hash = "F526C5B5C79DECDC27F555A96A7B3F33444DE060AD5C9A02A7F5D15C5DBE85"
trust_period = "168h0m0s"

```

***Take a moment to check that\*\*\*\*****&#x20;****`enable = true`****&#x20;****, and check that your\*\*\*\* ****`rpc_servers`****,****&#x20;****`trust_height`****&#x20;****, and\*\*\*\*****&#x20;****`trust_hash`****&#x20;****\*\*\*\*are configured using the steps shown in***[ ***Node Setup***](broken://pages/OzHKVqI8SaLRc9qfBb3m)***. (be careful to choose the tabs that match your system)***

The `trust_period` should be left alone, and the `discovery_time` can be safely increased to "30s".

### Start your Node

{% code overflow="wrap" %}

```sh
./layerd start --price-daemon-enabled=false --home ~/.layer --keyring-backend test --key-name YOUR_ACCOUNT_NAME
```

{% endcode %}

If the sync is working, you will see your node quickly finding, downloading, and applying snapshots.

{% hint style="success" %}
***Notes:***\
***- "We need more peers..." messages are normal and can be ignored.***\
***- A statesync with good RPCs and Peers can still take an hour or more to finish downloading the state snapshot.***
{% endhint %}


# Example .service Files

Templates for systemd service files that work with Tellor

Tellor requires two separate services that use two different binaries: `layerd` and `reporterd`.

For running the layer node client (`layerd`):

```sh
[Unit]
Description=Layer Node Client
After=network-online.target

[Service]
User=USERNAME
Group=USERNAME
WorkingDirectory=/home/USERNAME/path/to/layer
ExecStart=/home/USERNAME/path/to/layerd start --home /home/USERNAME/.layer --keyring-backend="test" --key-name=ACCOUNT_NAME  --api.enable --api.swagger
Restart=always
RestartSec=10
Environment="TOKEN_BRIDGE_V2_ADDRESS=0x6ec401744008f4B018Ed9A36f76e6629799Ee50E"

[Install]
WantedBy=multi-user.target
```

For running the reporter daemon (`reporterd`):

```sh
[Unit]
Description=Layer Reporter
After=network-online.target

[Service]
User=USERNAME
Group=USERNAME
WorkingDirectory=/home/USERNAME/layer/binaries/reporter
ExecStart=/home/USERNAME/layer/binaries/reporter/reporterd
Restart=always
RestartSec=10
# Reporter identity
Environment="LAYER_HOME=/home/USERNAME/.layer"
Environment="FROM=ACCOUNT_NAME"
Environment="KEYRING_BACKEND=test"
# Environment="KEYRING_PASSWORD_FILE=/etc/layer-daemons/reporter-keyring-password"  # required when KEYRING_BACKEND=file
Environment="RPC_NODES=tcp://127.0.0.1:26657"
Environment="GRPC_NODES=127.0.0.1:9090"
Environment="BRIDGE_CHAIN_RPC_NODES=https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY,https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY"
Environment="ETH_MAINNET_RPC_NODES=https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY,https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY"
Environment="REPORTERS_VALIDATOR_ADDRESS=tellorvaloper1_your_address"
Environment="WITHDRAW_FREQUENCY=43200"
Environment="CMC_PRO_API_KEY=YOUR_COINMARKETCAP_API_KEY"
Environment="CGPRO_API_KEY=YOUR_COINGECKO_PRO_API_KEY"
Environment="SUBGRAPH_API_KEY=YOUR_GRAPH_API_KEY"
Environment="INFURA_API_KEY=YOUR_INFURA_API_KEY"
Environment="ALCHEMY_API_KEY=YOUR_ALCHEMY_API_KEY"
# Optional settings:
# Environment="REMOTE_SIGNER_ADDR=127.0.0.1:9191"
# Environment="REMOTE_SIGNER_CA_CERT=/etc/layer-daemons/remote-signer-ca.pem"
# Environment="REMOTE_SIGNER_CLIENT_CERT=/etc/layer-daemons/remote-signer-client.pem"
# Environment="REMOTE_SIGNER_CLIENT_KEY=/etc/layer-daemons/remote-signer-client-key.pem"
# Environment="DISPUTE_MONITOR_ENABLED=false"
# Environment="API_URLS=http://localhost:1317"
# Environment="CUSTOM_QUERY_CACHE_TTL=3s"

[Install]
WantedBy=multi-user.target
```

When using `KEYRING_BACKEND=file`, also set `KEYRING_PASSWORD_FILE` to a password file readable only by the service user. See the [layer-daemons README](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/README.md#keyring-password-file) for setup details.

Alternatively, you can load all reporter settings from a file:

```sh
EnvironmentFile=/home/USERNAME/layer/binaries/reporter/.env
```

For running a layer validator with cosmovisor:

{% code overflow="wrap" %}

```shell
[Unit]
Description=Cosmovisor Validator Start
After=network-online.target

[Service]
User=USERNAME
Group=USERNAME
WorkingDirectory=/home/USERNAME/layer
ExecStart=/home/USERNAME/cosmovisor run start --home /home/USERNAME/.layer --keyring-backend="test" --key-name="ACCOUNT_NAME" --api.enable --api.swagger
Restart=always
RestartSec=10
MemoryMax=25G
Environment="DAEMON_NAME=layerd"
Environment="DAEMON_HOME=/home/USERNAME/.layer"
Environment="DAEMON_RESTART_AFTER_UPGRADE=true"
Environment="DAEMON_ALLOW_DOWNLOAD_BINARIES=false"
Environment="DAEMON_POLL_INTERVAL=300ms"
Environment="UNSAFE_SKIP_BACKUP=true"
Environment="DAEMON_PREUPGRADE_MAX_RETRIES=0"
Environment="TOKEN_BRIDGE_V2_ADDRESS=0x6ec401744008f4B018Ed9A36f76e6629799Ee50E"


[Install]
WantedBy=multi-user.target
```

{% endcode %}


# Run a Tellor Validator

Follow the steps to become a tellor validator.

## Prerequisites

You will need a [node that's fully synced](/tellor/running-tellor/node-setup) and [an account that has a balance](/tellor/running-tellor/manage-accounts) (loya).

## Creating your Validator

1\) Change directory to `~/layer/binaries/v6.1.7` and check if your address has funds. You will need to have at least 1 TRB to stake a validator on tellor layer:

{% code overflow="wrap" %}

```bash
cd ~/layer/binaries/v6.1.7 && ./layerd query bank balance YOUR_ACCOUNT_NAME loya
```

{% endcode %}

This outputs something like:

```bash
balance:
  amount: "123456"
  denom: loya
```

2\) Retrieve your Node's Pubkey

This is a unique identifier for a node running on your computer:

<pre class="language-bash"><code class="lang-bash"><strong>./layerd comet show-validator
</strong></code></pre>

This returns your validator pubkey. It should look like this:

```bash
{"@type":"/cosmos.crypto.ed25519.PubKey","key":"FX9cKNl+QmxtLcL926P5yJqZw7YyuSX3HQAZboz3TjM="}
```

Copy this output for the next step.

#### **3) Edit the Validator Configuration File**

Create (or edit) the validator.json file:

```bash
nano validator.json
```

Edit or add the following code:

```json
{
    "pubkey": {"@type":"/cosmos.crypto.ed25519.PubKey","key":"c+EuycPpudgiyVl6guYG9oyPSImHHJz1z0Pg4ODKveo="},
    "amount": "69666420loya",
    "moniker": "yourmoniker",
    "identity": "optional identity signature (ex. UPort or Keybase)",
    "website": "validator's (optional) website",
    "security": "validator's (optional) security contact email",
    "details": "validator's (optional) details",
    "commission-rate": "0.1",
    "commission-max-rate": "0.2",
    "commission-max-change-rate": "0.01",
    "min-self-delegation": "1"
}
```

* Edit `"pubkey"` to match yours from step 4.
* Edit `"amount"` to be the amount of testnet TRB that you would like to stake with 6 decimals and the "loya" denom. (For example: if you want to stake 99 TRB use `"amount": "99000000loya"`)
* Edit `"moniker"` with a name you choose for your validator node.
* Edit identity, website, security, and details with your identifying information. (optional)
* Edit `commission-rate`, `commission-max-rate`, `commission-max-change-rate`, and `min-self-delegation` if desired. (these can be changed later using the `edit-validator` command).

{% hint style="success" %} <mark style="color:blue;">**Important Considerations for your Validator:**</mark>

* <mark style="color:blue;">When creating your validator, be sure that you are NOT choosing an "amount" that is larger than your balance of test-net TRB.</mark>
* <mark style="color:blue;">TRB has 6 decimals: 1 loya is 0.000001 TRB</mark>
* <mark style="color:blue;">Note: TRB tokens are used for gas on the layer network. As a validator / reporter you will need to make transactions to send tokens, become a reporter, unjail, etc. When choosing the amount to stake, it is important to reserve some TRB for gas.</mark>
* <mark style="color:blue;">**Staking on layer is limited to 5% of the total staked tokens per 12 hours. You can check the current amount that's allowed to stake**</mark> [<mark style="color:blue;">**here**</mark>](https://explorer.tellor.io)<mark style="color:blue;">**.**</mark>
  {% endhint %}

#### **4) Create your validator.**

Run the following command to create-validator:

{% code overflow="wrap" %}

```bash
./layerd tx staking create-validator ./validator.json --chain-id tellor-1 --from YOUR_ACCOUNT_NAME --gas 300000 --fees 8loya --yes
```

{% endcode %}

**5) Verify that creation was successful.**

Use the command:

{% code overflow="wrap" %}

```bash
./layerd query staking validator YOUR_ACCOUNT_NAME
```

{% endcode %}

If `status: 3,`you are staked and validating!

{% hint style="info" %}
If `status` is `1`, It means that you are not bonded. This can happen If you accidentally made your "amount" in step 4 too small. Check that you are staking at least 1 TRB (1000000loya).\
\
If `status` is `2`, It means that your validator is jailed. If this happens, check if the node process is running on your host machine.
{% endhint %}

You can unjail with steps shown in the [next section.](/tellor/running-tellor/run-the-data-reporter)


# Slashing Rules for Validators

### Context

*Tellor inherits validator slashing mechanisms from CometBFT. A detailed understanding can be found in the* [*cosmos SDK documentation*](https://docs.cosmos.network/main/build/modules/slashing)*.*

## Slashing, Jailing, and Tombstoneing

There are two basic reasons that a validator may be automatically slashed, jailed or tombstoned: <mark style="color:yellow;">**liveness**</mark> and <mark style="color:red;">double signing</mark>.

### **Liveness (inactivity):**

If your validator fails to sign for 500 blocks (e.g. the validator node is down for 500 blocks), the validator will be automatically jailed. **At the time of writing tellor has a 1.52s average block time, so it takes approximately 12.6 minutes of inactivity before a validator is jailed.**

The penalty for inactivity is 1% of bonded tokens. Liveness slashes do not lead to a tombstombing.

If your node is Jailed for inactivity, you can simply "**unjail**" it via cli on the host machine:

**Double Signing:**

Unjustified pre-commits (double signs) are rare, and the penalty is severe. If a double sign is detected the validator is automatically slashed up to 50% and tomestoned, while their delegators are forced to unbond or redelegate their token voting power.\
\
A “tombstoned" validator key can never be used again. The validator may rejoin the network using another node key, but they will have to earn back the trust of any delegators they previously had.

{% hint style="danger" %}
Warning: It is possible to double sign blocks accidentally during complex operations like migrating a validator node to a different machine. Always be 100% sure that the layer node process on the old machine is dead before starting it up on the new machine!

Warning: Never use any account that was used on tellor testnet to run a validator on tellor mainnet!
{% endhint %}

## Check Your Validator's Status

You can check your validator's status on the[ block explorer ](https://explorer.tellor.io/validators)or via cli:

```sh
./layerd query staking validator ACCOUNT_NAME
```

"status: 2" means that you are jailed.

## How to Unjail

Unjail your validator with the command:

{% code overflow="wrap" %}

```bash
./layerd tx slashing unjail --from YOUR_ACCOUNT_NAME --chain-id tellor-1 --fees 5loya --yes
```

{% endcode %}


# Run a Data Reporter

Operate a Data Reporter!

## Staking

To create a reporter on Tellor Layer, you must first "stake" your address one of two ways. You must either create a validator -OR- delegate to a validator to bond your tokens.

* Create a Validator: Your account is the KEYNAME account used for your [validator](/tellor/running-tellor/run-a-layer-validator).
* Delegate to a Validator: If your reporter account is not a validator account, you must [bond your address to a validator ](/tellor/command-line-usage/leveraging-layerd/delegate-to-a-validator)before you may create your reporter.

#### 1) Configure a Reporter on Tellor

Use the `layerd` cli register and initialize your reporter configuration. Commission-rate and min-tokens-required are shown at safe values, but can be adjusted (now or later) for personal preference:

{% code overflow="wrap" %}

```bash
# create-reporter [commission-rate] [min-tokens-required] [moniker] [flags]
./layerd tx reporter create-reporter 0.05 1000000 REPORTER_MONIKER --from YOUR_ACCOUNT_NAME --chain-id tellor-1 --fees 10loya --yes
```

{% endcode %}

Parameters:

* A (example) `commision-rate` of `0.05` means that you get 5% of rewards from your selectors.
* A (example) `min-tokens-required` value of `1000000` prevents spam by requiring that selectors have at least 1 TRB in their wallet. This can be changed later.
* Choose a `REPORTER_MONIKER` that you love! (It does not need to be the same as your validator moniker.)

#### 2) Check if your reporter was created successfully:

```sh
./layerd query reporter reporters | grep -A 7 YOUR_TELLOR_ADDRESS
```

If your reporter was created successfully, this will output your reporter information.

#### 3) Download the latest `reporterd` binary:

Download [reporterd v0.2.8](https://github.com/tellor-io/layer-daemons/releases/tag/v0.2.8):

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/reporter && cd ~/layer/binaries/reporter && wget https://github.com/tellor-io/layer-daemons/releases/download/v0.2.8/reporterd_Linux_x86_64.tar.gz && tar -xvzf reporterd_Linux_x86_64.tar.gz && rm reporterd_Linux_x86_64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Mac" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/reporter && cd ~/layer/binaries/reporter && wget https://github.com/tellor-io/layer-daemons/releases/download/v0.2.8/reporterd_Darwin_arm64.tar.gz && tar -xvzf reporterd_Darwin_arm64.tar.gz && rm reporterd_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### 4) Create `.env`

`reporterd` loads environment variables from a `.env` file in the current working directory (or from `../.env` when run from a subdirectory). You can also set these in a [systemd service file](/tellor/running-tellor/node-setup/example-.service-files) instead.

Copy [`env.example`](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/env.example) from layer-daemons and edit the values for your setup:

{% code overflow="wrap" %}

```sh
cd ~/layer/binaries/reporter
wget https://raw.githubusercontent.com/tellor-io/layer-daemons/v0.2.8/env.example
cp env.example .env
```

{% endcode %}

At minimum, set `LAYER_HOME`, `FROM`, `KEYRING_BACKEND`, `RPC_NODES`, `GRPC_NODES`, `BRIDGE_CHAIN_RPC_NODES`, and your custom query API keys. `RPC_NODES`, `GRPC_NODES`, `BRIDGE_CHAIN_RPC_NODES`, and `ETH_MAINNET_RPC_NODES` accept comma-separated endpoint lists, with the first endpoint used as the primary and later endpoints used as ordered fallbacks.

Most CLI flags can be provided as environment variables by uppercasing the flag name and replacing `-` or `.` with `_` (for example, `--keyring-backend` becomes `KEYRING_BACKEND`). Use `LAYER_HOME` for the Layer home directory instead of relying on the shell's `HOME`. When using `KEYRING_BACKEND=file`, set `KEYRING_PASSWORD_FILE` to a file that contains the keyring password and is readable only by the service user.

Set `ETH_MAINNET_RPC_NODES` when your bridge chain RPC endpoints are not Ethereum mainnet, or when you want to provide explicit Ethereum mainnet fallbacks for custom query contract reads. The built-in custom query templates also use `CMC_PRO_API_KEY`, `CGPRO_API_KEY`, `SUBGRAPH_API_KEY`, and, when `ETH_MAINNET_RPC_NODES` is unset, `INFURA_API_KEY` and `ALCHEMY_API_KEY`.

{% hint style="info" %}
See the [layer-daemons README](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/README.md) and [`env.example`](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/env.example) for all available options, including remote signer, dispute monitor, custom query cache, auto-unbonding, price guard, and auto balance-to-keep bridge settings.
{% endhint %}

#### 5) Start the reporter:

From the directory containing your `.env` file:

{% code overflow="wrap" %}

```bash
cd ~/layer/binaries/reporter && ./reporterd
```

{% endcode %}

If you prefer CLI flags instead of `.env`, you can still pass them explicitly. Environment variables take precedence over matching flags when both are set:

{% code overflow="wrap" %}

```bash
./reporterd --grpc 127.0.0.1:9090 --node tcp://127.0.0.1:26657 --from ACCOUNT_NAME --home ~/.layer --keyring-backend test
```

{% endcode %}

Here is an example start command for a reporter who wants to automatically unbond 2.999 TRB (2999999 loya) per day with a maximum set to 1% of their total stake:

{% code overflow="wrap" %}

```bash
./reporterd --auto-unbonding-frequency 1 --auto-unbonding-amount 2999999 --auto-unbonding-max-stake-percentage 0.01
```

{% endcode %}

The same auto-unbonding settings can be set in `.env`:

```sh
AUTO_UNBONDING_FREQUENCY=1
AUTO_UNBONDING_AMOUNT=2999999
AUTO_UNBONDING_MAX_STAKE_PERCENTAGE=0.01
```

{% hint style="success" %}
You can set up a grafana dashboard using [this\_guide](/tellor/setting-up-a-grafana-dashboard-for-your-layer-node) to monitor things in Layer such as average gas price for submitting a report, block times, total bonded tokens, etc.
{% endhint %}

Congratulations on becoming a Tellor Reporter! 🎉


# Updating reporterd

Steps for updating your reporter daemon.

{% hint style="success" %}
It's important to keep your Tellor reporter software up-to-date with all the latest feeds so that you can maximize rewards. This is done separately from chain (layerd) upgrades
{% endhint %}

### 1. Stop your reporter.

### 2. Remove the old `reporterd` binary and Configs:

*Your file paths may be different. Remember to adjust as needed to remove the files:*

{% code overflow="wrap" %}

```sh
rm -rf ~/layer/binaries/reporter/reporterd
rm -rf ~/layer/binaries/reporter/README.md
rm ~/.layer/config/market_params.toml
rm ~/.layer/config/custom_query_config.toml
rm ~/.layer/config/pricefeed_exchange_config.toml
```

{% endcode %}

### 3. Update your `.env` or service file

Compare your `.env` against the [layer-daemons `env.example`](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/env.example) for the current variable names and defaults.

Compare your `.service` file against the [example reporterd service file](/tellor/running-tellor/node-setup/example-.service-files) and update your `Environment` settings to match the current variable names and defaults.

### 4. Download the latest `reporterd` release

Download [reporterd v0.2.8](https://github.com/tellor-io/layer-daemons/releases/tag/v0.2.8):

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
cd ~/layer/binaries/reporter && wget https://github.com/tellor-io/layer-daemons/releases/download/v0.2.8/reporterd_Linux_x86_64.tar.gz && tar -xvzf reporterd_Linux_x86_64.tar.gz && rm reporterd_Linux_x86_64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Mac" %}
{% code overflow="wrap" %}

```sh
cd ~/layer/binaries/reporter && wget https://github.com/tellor-io/layer-daemons/releases/download/v0.2.8/reporterd_Darwin_arm64.tar.gz && tar -xvzf reporterd_Darwin_arm64.tar.gz && rm reporterd_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

### 5. Restart your reporter

Note: The `--chain-id` flag has been removed. All other CLI flags are optional when configuration is provided via your `.env` or service file.

{% code overflow="wrap" %}

```sh
cd ~/layer/binaries/reporter && ./reporterd
```

{% endcode %}


# Unjail Your Reporter

Example command to unjail your reporter:

In the event of a dispute, your reporter will be jailed.

If the dispute is just a warning, you can unjail right away. The command to do this is:

{% code overflow="wrap" %}

```sh
# layerd tx reporter unjail-reporter [flags]
./layerd tx reporter unjail-reporter --from ACCOUNT_NAME --fees 5loya --chain-id tellor-1
```

{% endcode %}


# Switch Reporter or Selector

Steps for changing your reporter selection.

The following command can be used to change your reporter selection:

{% code overflow="wrap" %}

```sh
./layerd tx reporter switch-reporter NEW_REPORTER_ADDRESS --from OLD_REPORTER_ADDRESS --fees 5loya --chain-id tellor-1
```

{% endcode %}

Note: To prevent bridge manipulation, reporters are not allowed to do `switch-reporter` for reporter addresses that have reported data in the past 21 days.


# Production Spot Price List

A list of used spot price feeds.

{% hint style="info" %}
Note: These feeds are configured automatically on first run by [reporterd](/tellor/running-tellor/run-the-data-reporter). If you find that you are not able to report any of these prices, please [update your data reporter!](/tellor/running-tellor/run-the-data-reporter/updating-reporterd)
{% endhint %}

There are two different methods for calculating prices: "Market", and "Fundamental".

**Market**: A median of market prices from exchange APIs.

**Fundamental**: (conversion rate from the token contract) \* (market price of the collateral asset). These feeds require EVM RPC calls to calculate.

1. BTC/USD: Market
2. ETH/USD: Market
3. TRB/USD: Market
4. USDC/USD: Market
5. USDT/USD: Market
6. tBTC/USD: Market
7. wstETH/USD: Fundamental
8. rETH/USD: Fundamental
9. sfrxUSD/USD: Fundamental
10. sUSDe/USD: Fundamental


# Disputes and Reporter Governance

cli commands and additional context for understanding Tellor reporter slashing and dispute governance

### Overview:

Tellor reporters are subject to novel dispute mechanisms designed to ensure data integrity. If questionable data is identified or a reporter is suspected of acting maliciously, any participant holding TRB on the network can initiate a dispute. This open and transparent process empowers the community to govern reporters collectively.

Here's how it works:

The disputer must pay a dispute fee that is based on the severity of the offense and the size of the offending reporter's stake. If they can't afford the dispute fee, they can alert the community and ask for help funding the dispute.

Once the fee is paid, the governance process begins, and the offending reporter is jailed. They are also temporarily slashed an amount equal to the dispute fee.

There are three dispute categories: **warning**, **minor**, and **major**. This gives some flexibility to the ways dispute governance can be used to ensure smooth operation of the oracle.

Dispute information can be queried using the following cli commands:

```sh
./layerd query dispute disputes
```

### Dispute Categories:

* <mark style="color:yellow;">**Warning**</mark>: The dispute fee / slashing amount is set at 1% of the reporter's bonded tokens. This is similar to the penalty for simple inactivity as a validator. The reporter will be jailed, but they may call \`unjail\` immediately to start reporting again with slightly reduced power while the dispute is settled.
* <mark style="color:orange;">**Minor**</mark>: The dispute fee / slashing amount is set a 5% of the reporter's bonded tokens. The reporter is jailed for 10 minutes.
* <mark style="color:red;">**Major**</mark>: The dispute fee / slashing amount is set equal to the amount bonded by the reporter. The reporter will be jailed forever unless the vote result is `against`.

## How to Propose a Dispute

The propose-dispute command has 6 arguments:

{% code overflow="wrap" %}

```sh
layerd tx dispute propose-dispute [disputed-reporter] [report-meta-id] [report-query-id] [dispute-category] [fee] [pay-from-bond] [flags]
```

{% endcode %}

**\[disputed-reporter]**: the "tellor" prefix address of the bad reporter

**\[report-meta-id]**: The bad report's meta id

**\[report-query-id]**: The bad report's query id

**\[dispute-category]**: (see above)

**\[fee]**: The amount of the dispute fee that you would like to pay while proposing the dispute. The minimum is 1 TRB (1000000loya) to prevent spam.\
\
Setting the fee to any value that is larger than the required dispute fee will only remove the exact fee amount from your wallet or bond. for example, if the dispute fee is 12345loya and fee=999999999999loya, the amount taken to pay the dispute fee will be 12345loya.

**\[pay-from-bond]**: set this to True if you want to use bonded tokens to pay the dispute fee. You might want to do this if you don't have enough free balance to pay the fee. Set this to "False" to use free balance only.

Full example:

{% code overflow="wrap" %}

```sh
./layerd tx dispute propose-dispute tellor17gc67q05d5rsz9caznm0s7s5eazg2e3fkk8e 109136 0x0d12ad49193163bbbeff4e6db8294ced23ff8605359fd66799d4e25a3a0e3a warning 1000000loya false --from ACCOUNT_NAME --gas 500000 --fees 15loya  --chain-id tellor-1 --yes
```

{% endcode %}

{% hint style="warning" %}
*<mark style="color:blue;">**There is a 48 hour voting period followed by a 24 hour Challenge period after a dispute.**</mark>*

*<mark style="color:blue;">**After 72 hours, the dispute is settled and the parties involved can call withdraw-fee-refund to claim any tokens that were awarded from the dispute. Also, all the reporters who voted on the dispute can call claim-reward to receive their share of 2.5% of the dispute fee!**</mark>*
{% endhint %}

### Adding Funds to the Dispute Fee

In the event that a disputer is unable to pay the entire dispute fee, anyone who wants to support the dispute financially can call `add-fee-to-dispute` . All fee payers earn a proportionate amount of the reward funds from the dispute if the rest of the community votes to support it. Likewise, if the community votes "against", the entire fee is forfeited to the accused reporter. Example:

<pre class="language-sh" data-overflow="wrap"><code class="lang-sh"><strong># layerd tx dispute add-fee-to-dispute [dispute-id] [amount] [pay-from-bond] [flags]
</strong>/layerd tx dispute add-fee-to-dispute 2 2023500loya false --from ACCOUNT_NAME --fees 5loya --chain-id tellor-1
</code></pre>

### What Happens if the Dispute Fee is Not Paid?

If the dispute fee is not paid in full while the dispute is active, the dispute will automatically settle "invalid". Anyone who paid a partial dispute fee can call `withdraw-fee-refund` to get those funds back. Example:

{% code overflow="wrap" %}

```sh
# layerd tx dispute withdraw-fee-refund [payer-address] [id] [flags]
./layerd tx dispute withdraw-fee-refund tellor1vw2yy9nf3wz7hey89tpw5hn0yr3hkrzt889x47 3 --from ACCOUNT_NAME --fees 5loya --chain-id tellor-1 --yes
```

{% endcode %}

## Voting

There are three different choices when voting on a dispute:

`vote-support:` You support the disputer and believe that the reporter should be slashed. The disputer receives all of the reporter's tokens, and they are refunded the dispute fee minus 2.5% that was taken out for voter rewards.

`vote-against:` You support the reporter, and believe the disputer should lose their dispute fee as punishment for opening an unnecessary dispute. The reporter gets their tokens back minus 2.5% that was taken out for voter rewards.

`vote-invalid:` It is not clear or not important if the reporter was wrong or malicious. The reporter gets all of their tokens back, and the disputer gets back the fee minus 2.5% that was taken out for voter rewards.

{% code overflow="wrap" %}

```sh
# layerd tx dispute vote [id] [vote-choice] [flags]
# full example:
./layerd tx dispute vote 3 vote-invalid --from ACCOUNT_NAME --fees 5loya --chain-id tellor-1
```

{% endcode %}

## Settling the Dispute

After 72 hours, the winning party (or parties if invalid) in the dispute can call withdraw-fee-refund to receive the tokens paid by the counter-party in the dispute:

{% code overflow="wrap" %}

```sh
./layerd tx dispute withdraw-fee-refund 2 --from ACCOUNT_NAME --fees 5loya --chain-id tellor-1
```

{% endcode %}

Any accounts that voted may call claim-reward to receive a small reward for voting. The amount that you get for voting is a token-weighted share of 2.5% of the dispute fee.

{% code overflow="wrap" %}

```sh
# layerd tx dispute claim-reward [dispute_id] [flags]
./layerd tx dispute claim-reward 2 --from ACCOUNT_NAME --fees 5loya --chain-id tellor-1
```

{% endcode %}


# Getting Started (testnet)

Instructions and guides for using tellor.

If you want to learn how to run a tellor node, validator, and/or reporter, you are in the right place!

## Welcome to the Guide

{% content-ref url="/pages/cOkNIKPxjt40QwAjU0qK" %}
[Node Quick Start (testnet)](/tellor/running-palmito-testnet/node-quick-start-testnet)
{% endcontent-ref %}

{% content-ref url="/pages/I1OHsMJvgAquWIy8MZFs" %}
[Quick Start New (faster!)](/tellor/running-palmito-testnet/quick-start-new-faster)
{% endcontent-ref %}

{% content-ref url="/pages/IFvT4U2EiMKNhiTpdFcx" %}
[Node Setup Manual (testnet)](/tellor/running-palmito-testnet/node-setup)
{% endcontent-ref %}

{% content-ref url="/pages/8SyLNotC1s8zvr8TNjoJ" %}
[Run a Layer Validator (testnet)](/tellor/running-palmito-testnet/run-a-layer-validator)
{% endcontent-ref %}

{% content-ref url="/pages/uYVu7gxMuYtS3gACbDvV" %}
[Run a Data Reporter (testnet)](/tellor/running-palmito-testnet/run-the-data-reporter)
{% endcontent-ref %}

{% hint style="success" %}
Please take the time to <mark style="color:green;">**review all information**</mark> in this guide and acclimate yourself before beginning.
{% endhint %}

{% hint style="success" %} <mark style="color:orange;">**Note:**</mark> *This is a guide for setting up a Tellor public testnet validator / reporter. Care is taken to provide info on the tools being used, but testers should be comfortable with running experimental code via command line interface. A beginner’s understanding of the cosmos SDK is highly recommended!*
{% endhint %}

{% hint style="info" %} <mark style="color:orange;">**Disclaimer:**</mark> participation in the Tellor public testnet involves using experimental software. If used in a mainnet context, the commands in this documentation WILL have consequences for real funds. Proceed with caution and ensure that you understand the responsibilities and risks associated with participation.
{% endhint %}


# Node Quick Start (testnet)

Use the guided setup shell scripts!

#### 1. Install Prerequisites:

```shellscript
# Debian / Ubuntu:
sudo apt install jq sed curl wget

# Arch (btw):
sudo pacman -S jq sed curl wget

# MACOS:
brew install jq sed curl wget
```

Download the latest binary:

{% tabs %}
{% tab title="Linux" %}

<pre class="language-sh" data-overflow="wrap"><code class="lang-sh"><strong>mkdir -p ~/layer/binaries &#x26;&#x26; cd ~/layer/binaries &#x26;&#x26; mkdir v6.1.8 &#x26;&#x26; cd v6.1.8 &#x26;&#x26; wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_x86_64.tar.gz &#x26;&#x26; tar -xvzf layer_Linux_x86_64.tar.gz
</strong></code></pre>

{% endtab %}

{% tab title="MacOS" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.8 && cd v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Darwin_arm64.tar.gz && tar -xvzf layer_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Rasp.Pi / ARM64" %}
{% code overflow="wrap" %}

```shellscript
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.8 && cd v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_arm64.tar.gz && tar -xvzf layer_Linux_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

### 2. Download the script that matches your system:

Additional info about the scripts can be found [here](https://github.com/tellor-io/layer/tree/main/scripts/setup). We will give the script permission to execute in the same command.

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
curl -O https://raw.githubusercontent.com/tellor-io/layer/refs/heads/main/scripts/setup/initial_config/configure_palmito_linux.sh && chmod +x configure_palmito_linux.sh
```

{% endcode %}
{% endtab %}

{% tab title="Mac" %}
{% code overflow="wrap" %}

```sh
curl -O  https://raw.githubusercontent.com/tellor-io/layer/refs/heads/main/scripts/setup/initial_config/configure_palmito_mac.sh && chmod +x configure_palmito_mac.sh
```

{% endcode %}
{% endtab %}
{% endtabs %}

### <mark style="color:blue;">2.1 (optional) Edit the environment variables</mark>

If you'd like to use a custom home directory, custom peers or RPCs you can configure those at the top of the script. The defaults are:

```sh
# ...
export LAYER_NODE_URL=https://node-palmito.tellorlayer.com/rpc/
export RPC_NODE_ID=ac7c10dc3de67c4394271c564671eeed4ac6f0e0
export KEYRING_BACKEND="test"
export PEERS="8d19cdf430e491d6d6106863c4c466b75a17088a@54.153.125.203:26656,c7b175a5bafb35176cdcba3027e764a0dbd0811c@34.219.95.82:26656,05105e8bb28e8c5ace1cecacefb8d4efb0338ec6@18.218.114.74:26656,705f6154c6c6aeb0ba36c8b53639a5daa1b186f6@3.80.39.230:26656,1f6522a346209ee99ecb4d3e897d9d97633ae146@3.101.138.30:26656"
export LAYER_HOME="/home/$(logname)/.layer"
export STATE_SYNC_RPC="https://node-palmito.tellorlayer.com/rpc/"
export KEY_NAME="test"
# ...
```

Use your favorite text editor to change these before running the script if desired.

```sh
nano configure_palmito_linux.sh # if linux
# --or--
nano configure_palmito_mac.sh # if mac
```

### 3. Give the script permission to execute, and run it:

<pre class="language-sh"><code class="lang-sh"><strong>./configure_palmito_linux.sh # if linux
</strong># --or--
./configure_palmito_mac.sh # if mac
</code></pre>

The script should greet you and begin the guided setup!

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2F5qTFI9wU71eGoHXlkfhu%2FScreenshot%20From%202025-07-31%2010-05-08.png?alt=media&amp;token=d7631dae-02aa-4b81-9bde-e1d0afe0f1fe" alt=""><figcaption></figcaption></figure>

### Options:

* **Snapshot sync**: Download a snapshot from a server, extract it into your data folder, and start the node. The node will need time to catch up downloading blocks. At the time of writing this takes about 6 hours to complete.
* **State sync**: Sync up to the network using snapshots from peers and a good RPC. At the time of writing this takes 12-24 hours to finish.

{% tabs %}
{% tab title="Snapshot Sync" %}

* ***If you want to sync from a snapshot, be sure to select option 2 when asked if you want to set up a state sync, and option 2 again when asked if you want to start the node:***

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2F1aT54W3ponrxQpdI1DZ3%2FScreenshot%20From%202025-08-06%2021-32-28.png?alt=media&amp;token=353d8644-afff-4319-beb0-81a792be3161" alt=""><figcaption></figcaption></figure>

* Visit [http://layer-node.com](https://layer-node.com/) and use the example commands shown there to download and extract the latest snapshot.
* Move the chain data into your \~/.layer folder:

{% code overflow="wrap" %}

```sh
# 
mv -f .layer_snapshot/data/application.db ~/.layer/data/application.db
mv -f .layer_snapshot/data/blockstore.db ~/.layer/data/blockstore.db
mv -f .layer_snapshot/data/cs.wal ~/.layer/data/cs.wal
mv -f .layer_snapshot/data/evidence.db ~/.layer/data/evidence.db
mv -f .layer_snapshot/data/snapshots ~/.layer/data/snapshots
mv -f .layer_snapshot/data/state.db ~/.layer/data/state.db
mv -f .layer_snapshot/data/tx_index.db ~/.layer/data/tx_index.db
rm -rf .layer_snapshot/
```

{% endcode %}

* Start the node!

{% code overflow="wrap" %}

```sh
./layerd start --home ~/.layer --keyring-backend test --key-name KEYNAME --api.enable --api.swagger
```

{% endcode %}
{% endtab %}

{% tab title="State sync" %}

* ***To perform a state sync, simply choose option 1 when prompted, and option 1 again when asked if you want to start the node:***

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2FdpCbDmADKk8zDyTaiIfg%2FScreenshot%20From%202025-08-06%2021-30-24.png?alt=media&amp;token=d5c3985e-a74e-4343-a7f1-191156f786be" alt=""><figcaption></figcaption></figure>

* Start the node!

{% code overflow="wrap" %}

```sh
./layerd start --home ~/.layer --keyring-backend test --key-name KEYNAME --api.enable --api.swagger
```

{% endcode %}
{% endtab %}
{% endtabs %}


# Quick Start New (faster!)

Using the Tellor layer node installation script!

{% hint style="info" %}
These commands will work on linux only. You will need to adjust the individual commands yourself for use on macOS.
{% endhint %}

### 1. Install Prerequisites:

{% tabs %}
{% tab title="Debian / ubuntu" %}
jq, yq, sed, curl, wget, make, and **Go** are required for running the various commands and config scripts and commands in this guide:

```bash
sudo apt install jq curl wget sed
```

{% endtab %}
{% endtabs %}

### 2. Download Layer installation script:

{% tabs %}
{% tab title="Linux" %}
Download the layer node installation script and give it permission to execute:

{% code overflow="wrap" %}

```sh
wget https://raw.githubusercontent.com/tellor-io/layer/refs/heads/main/scripts/setup/install_layer.sh && chmod +x install_layer.sh
```

{% endcode %}
{% endtab %}
{% endtabs %}

### 3. Run the Layer Node Installation Script

The script has two arguments `[NETWORK]` and `ACCOUNT_NAME` :

* "NETWORK": (required) `palmito` for `layertest-5` -OR- `mainnet` for `tellor-1`
* "ACCOUNT\_NAME": (optional) Set to any name you would like for your initial layer node account.

Run the script with the following command:

<pre class="language-sh"><code class="lang-sh"><strong>./install_layer.sh palmito [account_name]
</strong></code></pre>


# Managing Accounts

Follow the steps to make a layer account that can be used to receive funds from the bridge for transacting on Tellor.

{% hint style="info" %} <mark style="color:blue;">**Security Tips:**</mark>

* When you create a new account with the `layerd keys add` command, the output will include the mnemonic key. It is important to copy this key securely because it is the only time that mnemonic will be shown otherwise!
* This guide uses the "test" backend for easy compatibility with the reporter daemon. For information about the different (more secure) options, check out these docs.
* Always keep a secure backup of your initial configurations (including the Node key) just in case! A validator is difficult to recover without the node\_key, priv\_validator\_key, and priv\_validator\_state.
* Never use an address that holds real funds for testing.
  {% endhint %}

If you do not yet have an account / mnemonic phrase, Generate a new key pair with the command:

```sh
./layerd keys add $ACCOUNT_NAME --keyring-backend test
```

{% hint style="warning" %}
Be sure to <mark style="color:orange;">**copy the output**</mark> with the mnemonic and keep it in a very safe place!
{% endhint %}

If you already have an account, you can Import it with the command:

{% code overflow="wrap" %}

```sh
./layerd keys add $ACCOUNT_NAME --recover=true
```

{% endcode %}

To print the "tellor" prefix address to the terminal:

```bash
./layerd keys show $ACCOUNT_NAME
```

Next, add the `--bech val` flag to get the "tellorvaloper" prefix address, which is used for validator commands:

```bash
./layerd keys show $ACCOUNT_NAME --bech val
```

It can be useful to add these addresses to your `.bashrc` or `.zshrc` file. Be sure to replace `your_tellor_prefix_address` and `your_tellorvaloper_prefix_address` in your command:

{% code overflow="wrap" %}

```bash
echo 'export TELLOR_ADDRESS=your_tellor_prefix_address' >> ~/.bashrc #.zshrc if mac
echo 'export TELLORVALOPER_ADDRESS=your_tellorvaloper_prefix_address' >> ~/.bashrc #.zshrc if mac
```

{% endcode %}

Restart your terminal, or use `source ~/.bashrc` before you continue. (if Linux)

Restart your terminal, or use `source ~/.zshrc` before you continue. (if mac)

{% hint style="info" %} <mark style="color:blue;">Check accounts any time with:</mark> `./layerd keys list`
{% endhint %}


# Node Setup Manual (testnet)

How to Operate Tellor Layer Node.

## Recommended Hardware Specs

Operating a node for a personal RPC can be done using most modern computers.

For running a validator, *more power* is recommended:

* Modern cpu with at least 8 cores / threads
* ram: 32 gb + (16gb swap space recommended)
* storage: 1000gb+ @ NVME gen4
* network: 500mb/s DL, 100mb/s UL (the faster the better)

### Software Prerequisites

{% tabs %}
{% tab title="Linux" %}
jq, yq, sed, curl, wget, make, and **Go** are required for running the various config scripts and commands in this guide:

```bash
sudo apt install jq yq sed curl wget build-essential
```

Install go if you want to build binaries from the layer repo:

* `Go version 1.22` : Use the default install instructions [here](https://go.dev/doc/install).
  {% endtab %}

{% tab title="MacOS" %}
jq, yq, sed, and wget are required for running the various commands and config scripts in this guide:

```bash
brew install jq yq sed wget && xcode-select --install
```

* `Go ≥ 1.22` : Use the default install instructions [here](https://go.dev/doc/install).
  {% endtab %}
  {% endtabs %}

{% hint style="success" %}

* Commands shown should just work while logged in as a user (not root).
* If you are using an older Mac with an intel chip, the linux versions (amd64) in step 1 below may be used. (just remember to use the mac commands!)
* If on raspberry pi or similar, use the binary downloads for "**arm64**".
  {% endhint %}

## Sync Method

These instructions use **state sync**: your node downloads a recent chain state snapshot from peers. This is the fastest way to get online, but you will not be able to query block info (like transactions) for blocks produced before the day of your sync.

## 1. Download and Organize the `layerd` Binary

{% hint style="warning" %}
**Be sure to select the tabs that work for your setup! You will get errors if you use the linux commands on mac and vice-versa.**
{% endhint %}

First, download the binary from the [Tellor Github](https://github.com/tellor-io/layer/tags).

{% tabs %}
{% tab title="Linux" %}

<pre class="language-sh" data-overflow="wrap"><code class="lang-sh"><strong>mkdir -p ~/layer/binaries &#x26;&#x26; cd ~/layer/binaries &#x26;&#x26; mkdir v6.1.8 &#x26;&#x26; cd v6.1.8 &#x26;&#x26; wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_x86_64.tar.gz &#x26;&#x26; tar -xvzf layer_Linux_x86_64.tar.gz
</strong></code></pre>

{% endtab %}

{% tab title="MacOS" %}

<pre class="language-sh" data-overflow="wrap"><code class="lang-sh"><strong>mkdir -p ~/layer/binaries &#x26;&#x26; cd ~/layer/binaries &#x26;&#x26; mkdir v6.1.8 &#x26;&#x26; cd v6.1.8 &#x26;&#x26; wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Darwin_arm64.tar.gz &#x26;&#x26; tar -xvzf layer_Darwin_arm64.tar.gz
</strong></code></pre>

{% endtab %}

{% tab title="Linux ARM64" %}

<pre class="language-sh" data-overflow="wrap"><code class="lang-sh"><strong>mkdir -p ~/layer/binaries &#x26;&#x26; cd ~/layer/binaries &#x26;&#x26; mkdir v6.1.8 &#x26;&#x26; cd v6.1.8 &#x26;&#x26; wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_arm64.tar.gz &#x26;&#x26; tar -xvzf layer_Linux_arm64.tar.gz
</strong></code></pre>

{% endtab %}
{% endtabs %}

Initialize .layer folder in your home directory: `layerd init [moniker] [flags]`

```sh
./layerd init layer --chain-id layertest-5
```

## 2. Set System Variables for Layerd

A Layer node uses the following variables:

* TOKEN\_BRIDGE\_V2\_ADDRESS: the token bridge contract address.

Edit .bashrc or .zshrc file with a text editor like nano:

{% tabs %}
{% tab title="Linux" %}

```
nano ~/.bashrc
```

{% endtab %}

{% tab title="MacOS" %}

```
nano ~/.zshrc
```

{% endtab %}
{% endtabs %}

Add this line to the bottom of the file.

```bash
export TOKEN_BRIDGE_V2_ADDRESS="0x55355157703A44f7516FBB831333317E98944e32"
```

Exit nano with `ctrl^x` then enter `y` to save the changes.

Load the new variables:

{% tabs %}
{% tab title="Linux" %}

```
source ~/.bashrc
```

{% endtab %}

{% tab title="MacOS" %}

```
source ~/.zshrc
```

{% endtab %}
{% endtabs %}

## 3. Edit Chain Configuration for Tellor.

We need to open up the tellor layer config files and change some variables. You can use any local text editor like code, vim, or nano.

***Note: All variables not shown can be safely left as is.***

To open the API up to the local network or set a custom port: In `~/.layer/config/app.toml`:

```sh
# Address defines the API server to listen on.
address = "tcp://0.0.0.0:1317"
#...
```

In `~/.layer/config/client.toml`:

```sh
#...
# The network chain ID
chain-id = "layertest-5"
# Set your chosen keyring backend (optional).
keyring-backend = "test"
```

In `~/.layer/config/config.toml`:

```sh
#...
# TCP or UNIX socket address for the RPC server to listen on (optional)
laddr = "tcp://0.0.0.0:26657"
#...
# Use '["*"]' to allow any origin
cors_allowed_origins = ["*"]
#...
# Comma separated list of nodes to keep persistent connections to
persistent_peers = "ac7c10dc3de67c4394271c564671eeed4ac6f0e0@34.229.148.107:26656,8d19cdf430e491d6d6106863c4c466b75a17088a@54.153.125.203:26656,c7b175a5bafb35176cdcba3027e764a0dbd0811c@34.219.95.82:26656,05105e8bb28e8c5ace1cecacefb8d4efb0338ec6@18.218.114.74:26656,705f6154c6c6aeb0ba36c8b53639a5daa1b186f6@3.80.39.230:26656,1f6522a346209ee99ecb4d3e897d9d97633ae146@3.101.138.30:26656,3822fa2eb0052b36360a7a6e285c18cc92e26215@175.41.188.192:26656"
#...
# How long we wait after committing a block, before starting on the new
# height (this gives us a chance to receive some more precommits, even
# though we already have +2/3).
timeout_commit = "1s"
#...
```

Note: Peer connection errors can be normal for a few minutes after start.

## 4. Sync the Node

*<mark style="color:green;">**Before starting your node**</mark><mark style="color:green;">,</mark> it's a good idea to think about how you want to run it so that the process does not get killed accidentally. This is not obvious for beginners. Try* [*GNU screen*](https://tellor.io/blog/how-to-manage-cli-applications-on-hosted-vms-with-screen/) *or tmux. More advanced setups can be achieved using systemd services.*

**We need to make a few more config edits to make sure your state sync goes smoothly.**

1. To find a good **trusted height** to use for a snapshot sync, we need to find the height of a snapshot available from `https://node-palmito.tellorlayer.com/rpc/` . Copy and paste this entire block of commands into a terminal and hit enter:

<pre class="language-sh"><code class="lang-sh"><strong>export LATEST_HEIGHT=$(curl -s https://node-palmito.tellorlayer.com/rpc/block | jq -r .result.block.header.height); \
</strong>export TRUSTED_HEIGHT=$((LATEST_HEIGHT - 17500)); \
export TRUSTED_HASH=$(curl -s "https://node-palmito.tellorlayer.com/rpc/block?height=$TRUSTED_HEIGHT" | jq -r .result.block_id.hash); \
echo $TRUSTED_HEIGHT $TRUSTED_HASH

</code></pre>

The output should be something like:

```sh
trusted_height: 3785000
Trusted_hash: DD27874AB1F5F4DFC5D7818E7CFBF8A8ECEDA745FFA78DF24D799B2B201418B9
```

2. Edit config.toml:

Open your config file:

```sh
nano ~/.layer/config/config.toml
```

Scroll or search (`ctrl^w`) the file and edit the state sync variables shown here to match the trusted height and trusted hash you found above:

```toml
# [statesync]
# ...
enable = true
#...
rpc_servers = "https://node-palmito.tellorlayer.com/rpc/,https://node-palmito.tellorlayer.com/rpc/"
trust_height = 3785000
trust_hash = "DD27874AB1F5F4DFC5D7818E7CFBF8A8ECEDA745FFA78DF24D799B2B201418B9"
trust_period = "168h0m0s"
```

Be sure to replace the `trust_height` and `trust_hash` with the block number and hash from the curl command above.

Exit nano with `ctrl^x` then enter `y` to save the changes.

3. Start your node:

{% code overflow="wrap" %}

```bash
./layerd start --home ~/.layer --key-name ACCOUNT_NAME --keyring-backend test --api.enable --api.swagger
```

{% endcode %}

The node should start up quickly and begin downloading snapshots from peers.

{% hint style="info" %}
Some errors related to peer connections can be expected even if the snapshot sync is working properly. (e.g. "we need more peers", or "Failed to reconnect")
{% endhint %}


# Peers List & Public RPCs

The following peers list can be used for syncing \`layertest-5\`

{% hint style="info" %}
If you followed the Node Setup section of these docs, you already have the latest peers list.
{% endhint %}

In your `~/.layer/config/config.toml` file:

{% code overflow="wrap" %}

```json
# Comma separated list of nodes to keep persistent connections to
persistent_peers = "8d19cdf430e491d6d6106863c4c466b75a17088a@52.53.241.143:26656,c7b175a5bafb35176cdcba3027e764a0dbd0811c@34.222.24.182:26956,05105e8bb28e8c5ace1cecacefb8d4efb0338ec6@18.218.114.74:26656,1f6522a346209ee99ecb4d3e897d9d97633ae146@3.101.138.30:26656,705f6154c6c6aeb0ba36c8b53639a5daa1b186f6@3.80.39.230:26656"

```

{% endcode %}

RPC

* <https://node-palmito.tellorlayer.com/rpc/>

API:

* <https://node-palmito.tellorlayer.com/>


# Cosmovisor Sync

Setup steps for cosmovisor gang.

Cosmovisor is a binary manager that can perform upgrades automatically. It can be configured to automatically download binaries, but this is not recommended!

## Download and configure Cosmovisor

1. Download the latest cosmovisor binary [cosmovisor v1.5.0](https://github.com/cosmos/cosmos-sdk/releases/tag/cosmovisor%2Fv1.5.0) binary:

{% tabs %}
{% tab title="Linux" %}

```sh
wget https://github.com/cosmos/cosmos-sdk/releases/download/cosmovisor%2Fv1.5.0/cosmovisor-v1.5.0-linux-amd64.tar.gz && tar -xvzf cosmovisor-v1.5.0-linux-amd64.tar.gz
```

{% endtab %}

{% tab title="MacOS" %}

```sh
wget https://github.com/cosmos/cosmos-sdk/releases/download/cosmovisor%2Fv1.5.0/cosmovisor-v1.5.0-darwin-amd64.tar.gz && tar -xvzf cosmovisor-v1.5.0-darwin-amd64.tar.gz
```

{% endtab %}

{% tab title="Linux ARM64" %}

```sh
wget https://github.com/cosmos/cosmos-sdk/releases/download/cosmovisor%2Fv1.5.0/cosmovisor-v1.5.0-linux-arm64.tar.gz && tar -xvzf cosmovisor-v1.5.0-linux-arm64.tar.gz
```

{% endtab %}
{% endtabs %}

2. Add the following to the end of your `~/.bashrc` or `~/.zshrc` file:

```
# cosmovisor
export DAEMON_NAME=layerd
export DAEMON_HOME=$HOME/.layer
export DAEMON_RESTART_AFTER_UPGRADE=true
export DAEMON_ALLOW_DOWNLOAD_BINARIES=false
export DAEMON_POLL_INTERVAL=300ms
export UNSAFE_SKIP_BACKUP=true
export DAEMON_PREUPGRADE_MAX_RETRIES=0
```

Use `source ~/.bashrc` or `source ~/.zshrc` to load the variables.

3. Initialize cosmovisor:

```sh
# Initialize cosmovisor.
./cosmovisor init ~/layer/binaries/v6.1.8/layerd
```

4. Start your node with cosmovisor:

{% code overflow="wrap" %}

```sh
./cosmovisor run start --home ~/.layer --keyring-backend test --key-name YOUR_ACCOUNT_NAME --api.enable --api.swagger
```

{% endcode %}

When a new upgrade is announced, follow the [Binary Upgrades](/tellor/running-palmito-testnet/node-setup/binary-upgrades#upgrading-with-cosmovisor) page to download the binary and run `add-upgrade` before the upgrade height.


# Binary Upgrades

Example commands for upgrading the layerd binary.

Use these steps when Palmito reaches a planned chain upgrade and your node stops at the upgrade height.

There are two upgrade paths depending on how you run your node:

* **Cosmovisor** — Download the new binary and register it with cosmovisor before the upgrade height. Cosmovisor swaps binaries and restarts the node automatically. See [Upgrading with Cosmovisor](#upgrading-with-cosmovisor) below.
* **Manual or systemd** — Download the new binary, optionally install it to your PATH, and restart the node yourself. Follow sections 1–3 below.

If you have not set up cosmovisor yet, see [Cosmovisor Sync](/tellor/running-palmito-testnet/node-setup/cosmovisor-sync).

## 1. Download the new binary

The new `layerd` binary version is `v6.1.8`. Choose the command for your machine:

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.8 && cd v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_x86_64.tar.gz && tar -xvzf layer_Linux_x86_64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Linux ARM64" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.8 && cd v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_arm64.tar.gz && tar -xvzf layer_Linux_arm64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="MacOS" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries && cd ~/layer/binaries && mkdir v6.1.8 && cd v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Darwin_arm64.tar.gz && tar -xvzf layer_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

Confirm the version:

```sh
~/layer/binaries/v6.1.8/layerd version
```

## 2. (optional) Install it in `~/go/bin/layerd`

Copy the new binary into `~/go/bin`:

```sh
mkdir -p ~/go/bin
cp ~/layer/binaries/v6.1.8/layerd ~/go/bin/layerd
chmod +x ~/go/bin/layerd
```

Make sure `~/go/bin` is in your shell `PATH` so new terminal sessions can find `layerd`. Edit with nano or use the commands below to add `export PATH="$HOME/go/bin:$PATH"` in your `.bashrc` or `.zshrc`

{% tabs %}
{% tab title="bash" %}

```sh
echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
```

{% endtab %}

{% tab title="zsh" %}

```sh
echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```

{% endtab %}
{% endtabs %}

Check that your shell is using the new binary:

```sh
which layerd
layerd version
```

## 3. Restart at the upgrade height

The node will stop and wait for the upgraded binary when the upgrade height is reached. When this happens, stop your node process. If you start the node manually, restart it with the new binary:

{% code overflow="wrap" %}

```sh
~/layer/binaries/v6.1.8/layerd start --home ~/.layer --key-name ACCOUNT_NAME --keyring-backend test --api.enable --api.swagger
```

{% endcode %}

If you run your node with systemd, update the `ExecStart` line in your `.service` file to point at the new binary. Use an absolute path instead of `~`:

{% code overflow="wrap" %}

```sh
ExecStart=/home/USERNAME/layer/binaries/v6.1.8/layerd start --home /home/USERNAME/.layer --keyring-backend="test" --key-name=ACCOUNT_NAME --api.enable --api.swagger
```

{% endcode %}

Then reload systemd and restart your service:

```sh
sudo systemctl daemon-reload
sudo systemctl restart layerd
sudo journalctl -u layerd -f
```

Replace `layerd` with the actual name of your service if it is different.

{% hint style="info" %}
Keep the old versioned binary directory until you are sure the node is running correctly after the upgrade.
{% endhint %}

## Upgrading with Cosmovisor

If you run your node with cosmovisor (see [Cosmovisor Sync](/tellor/running-palmito-testnet/node-setup/cosmovisor-sync)), register the new binary before the upgrade height. Cosmovisor handles the swap and restart automatically — you do not need to update systemd or restart the process yourself.

The new `layerd` binary version is `v6.1.8`. Choose the command for your machine:

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/v6.1.8 && cd ~/layer/binaries/v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_x86_64.tar.gz && tar -xvzf layer_Linux_x86_64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Linux ARM64" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/v6.1.8 && cd ~/layer/binaries/v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Linux_arm64.tar.gz && tar -xvzf layer_Linux_arm64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="MacOS" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/v6.1.8 && cd ~/layer/binaries/v6.1.8 && wget https://github.com/tellor-io/layer/releases/download/v6.1.8/layer_Darwin_arm64.tar.gz && tar -xvzf layer_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

Confirm the version:

```sh
~/layer/binaries/v6.1.8/layerd version
```

Then register the upgrade with cosmovisor:

```sh
./cosmovisor add-upgrade v6.1.8 ~/layer/binaries/v6.1.8/layerd
```

{% hint style="info" %}
Run `add-upgrade` before the chain reaches the upgrade height. Keep the old versioned binary directory until you are sure the node is running correctly after the upgrade.
{% endhint %}


# State Sync Troubleshooting / Resetting Chain Data

Steps for resetting / re-syncing a state synced node (or recovering from a failed state sync).

## State Sync Failed!?

There are three main reasons why a state sync will fail:

* RPC connection fails, or is rate limited
* Not enough healthy peers / seeds configured
* Incorrect trusted height / trusted hash

### Steps to reset chain data without losing your accounts:

1\) Stop the node process with `ctrl^c` (or `sudo systemctl stop layer` if it's a service)

2\) Remove the chain data from `~/.layer/data/`, being careful to NOT delete the `priv_validator_state.json` file:

<pre class="language-sh"><code class="lang-sh"># Delete the binaries
# This is useful if you're not sure that you downloaded the right binaries:
rm -rf ~/layer/binaries

# deletes chain data
# This is useful if state sync fails and you need to try a different config
<strong>rm -rf ~/.layer/data/application.db; \
</strong>rm -rf ~/.layer/data/blockstore.db; \
rm -rf ~/.layer/data/cs.wal; \
rm -rf ~/.layer/data/evidence.db; \
rm -rf ~/.layer/data/snapshots; \
rm -rf ~/.layer/data/state.db; \
rm -rf ~/.layer/data/tx_index.db
</code></pre>

Next, open up your configs.

```sh
nano ~/.layer/config/config.toml
```

Use `ctrl^w` to search, or scroll down to the `[p2p]` section.

```toml
#######################################################
###           P2P Configuration Options             ###
#######################################################
[p2p]

# Address to listen for incoming connections
laddr = "tcp://0.0.0.0:26656"

# Address to advertise to peers for them to dial. If empty, will use the same
# port as the laddr, and will introspect on the listener to figure out the
# address. IP and port are required. Example: 159.89.10.97:26656
external_address = ""

# Comma separated list of seed nodes to connect to
seeds = "f4786bc2a40172e29784b9f8d..."

# Comma separated list of nodes to keep persistent connections to
persistent_peers = "f4786bc2a40172e29784b9f8d69567c474d..."

# Path to address book
addr_book_file = "config/addrbook.json"

# Set true for strict address routability rules
# Set false for private or local networks
addr_book_strict = false

```

Try manually editing the seeds and persistent\_peers to match [those shown here](/tellor/running-palmito-testnet/node-setup/peers-list-and-public-rpcs).

In most cases `addr_book_strict` can be safely changed to `true`.

Find the `[statesync]` section.

```toml
#######################################################
###         State Sync Configuration Options        ###
#######################################################
[statesync]
# State sync rapidly bootstraps a new node by discovering, fetching, and restoring a state machine
# snapshot from peers instead of fetching and replaying historical blocks. Requires some peers in
# the network to take and serve state machine snapshots. State sync is not attempted if the node
# has any local state (LastBlockHeight > 0). The node will have a truncated block history,
# starting from the height of the snapshot.
enable = true

# RPC servers (comma-separated) for light client verification of the synced state machine and
# retrieval of state data for node bootstrapping. Also needs a trusted height and corresponding
# header hash obtained from a trusted source, and a period during which validators can be trusted.
#
# For Cosmos SDK-based chains, trust_period should usually be about 2/3 of the unbonding time (~2
# weeks) during which they can be financially punished (slashed) for misbehavior.
rpc_servers = "https://tellor-testnet.nirvanalabs.xyz/tellor-testnet-public/,https://node-palmito.tellorlayer.com/rpc/"
trust_height = 217310
trust_hash = "F526C5B5C79DECDC27F555A96A7B3F33444DE060AD5C9A02A7F5D15C5DBE85"
trust_period = "168h0m0s"

# Time to spend discovering snapshots before initiating a restore.
discovery_time = "15s"
```

***Take a moment to check that\*\*\*\*****&#x20;****`enable = true`****&#x20;****, and check that your\*\*\*\* ****`rpc_servers`****,****&#x20;****`trust_height`****&#x20;****, and\*\*\*\*****&#x20;****`trust_hash`****&#x20;****\*\*\*\*are configured using the steps shown in***[ ***Node Setup***](/tellor/running-palmito-testnet/node-setup)***. (be careful to choose the tabs that match your system)***

The `trust_period` should be left alone, and the `discovery_time` can be safely increased to "30s".

### Start your Node

{% code overflow="wrap" %}

```sh
./layerd start --home ~/.layer --keyring-backend test --key-name YOUR_ACCOUNT_NAME
```

{% endcode %}

If the sync is working, you will see your node quickly finding, downloading, and applying snapshots.

{% hint style="success" %}
***Notes:***\
***- "We need more peers..." messages are normal and can be ignored.***\
***- A statesync with good RPCs and Peers can still take an hour or more to start downloading blocks.***
{% endhint %}


# Example .service Files

Templates for systemd service files that work with Tellor

Tellor requires two separate services that use two different binaries: `layerd` and `reporterd`.

For running the layer node client (`layerd`):

{% code overflow="wrap" %}

```sh
[Unit]
Description=Layer Node Client
After=network-online.target

[Service]
User=USERNAME
Group=USERNAME
WorkingDirectory=/home/USERNAME/layer
ExecStart=/home/USERNAME/path/to/layerd start --home /home/USERNAME/.layer --keyring-backend="test" --key-name=ACCOUNT_NAME  --api.enable --api.swagger
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
```

{% endcode %}

For running the reporter daemon (`reporterd`):

{% code overflow="wrap" %}

```sh
[Unit]
Description=Layer Reporter
After=network-online.target

[Service]
User=USERNAME
Group=USERNAME
WorkingDirectory=/home/USERNAME/layer/binaries/reporter
ExecStart=/home/USERNAME/layer/binaries/reporter/reporterd
Restart=always
RestartSec=10
# Reporter identity
Environment="LAYER_HOME=/home/USERNAME/.layer"
Environment="FROM=ACCOUNT_NAME"
Environment="KEYRING_BACKEND=test"
# Environment="KEYRING_PASSWORD_FILE=/etc/layer-daemons/reporter-keyring-password"  # required when KEYRING_BACKEND=file
Environment="RPC_NODES=tcp://127.0.0.1:26657"
Environment="GRPC_NODES=127.0.0.1:9090"
Environment="BRIDGE_CHAIN_RPC_NODES=https://sepolia.infura.io/v3/YOUR_INFURA_API_KEY,https://eth-sepolia.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY"
Environment="ETH_MAINNET_RPC_NODES=https://mainnet.infura.io/v3/YOUR_INFURA_API_KEY,https://eth-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY"
Environment="REPORTERS_VALIDATOR_ADDRESS=tellorvaloper1_your_address"
Environment="WITHDRAW_FREQUENCY=43200"
Environment="CMC_PRO_API_KEY=YOUR_COINMARKETCAP_API_KEY"
Environment="CGPRO_API_KEY=YOUR_COINGECKO_PRO_API_KEY"
Environment="SUBGRAPH_API_KEY=YOUR_GRAPH_API_KEY"
Environment="INFURA_API_KEY=YOUR_INFURA_API_KEY"
Environment="ALCHEMY_API_KEY=YOUR_ALCHEMY_API_KEY"
# Optional settings:
# Environment="REMOTE_SIGNER_ADDR=127.0.0.1:9191"
# Environment="REMOTE_SIGNER_CA_CERT=/etc/layer-daemons/remote-signer-ca.pem"
# Environment="REMOTE_SIGNER_CLIENT_CERT=/etc/layer-daemons/remote-signer-client.pem"
# Environment="REMOTE_SIGNER_CLIENT_KEY=/etc/layer-daemons/remote-signer-client-key.pem"
# Environment="DISPUTE_MONITOR_ENABLED=false"
# Environment="API_URLS=http://localhost:1317"
# Environment="CUSTOM_QUERY_CACHE_TTL=3s"

[Install]
WantedBy=multi-user.target
```

{% endcode %}

When using `KEYRING_BACKEND=file`, also set `KEYRING_PASSWORD_FILE` to a password file readable only by the service user. See the [layer-daemons README](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/README.md#keyring-password-file) for setup details.

Alternatively, you can load all reporter settings from a file:

```sh
EnvironmentFile=/home/USERNAME/layer/binaries/reporter/.env
```

For running a layer validator with cosmovisor:

{% code overflow="wrap" %}

```shell
[Unit]
Description=Cosmovisor Validator Start
After=network-online.target

[Service]
User=USERNAME
Group=USERNAME
WorkingDirectory=/home/USERNAME/layer
ExecStart=/home/USERNAME/cosmovisor run start --home /home/USERNAME/.layer --keyring-backend="test" --key-name="ACCOUNT_NAME" --api.enable --api.swagger
Restart=always
RestartSec=10
MemoryMax=25G
Environment="DAEMON_NAME=layerd"
Environment="DAEMON_HOME=/home/USERNAME/.layer"
Environment="DAEMON_RESTART_AFTER_UPGRADE=true"
Environment="DAEMON_ALLOW_DOWNLOAD_BINARIES=false"
Environment="DAEMON_POLL_INTERVAL=300ms"
Environment="UNSAFE_SKIP_BACKUP=true"
Environment="DAEMON_PREUPGRADE_MAX_RETRIES=0"


[Install]
WantedBy=multi-user.target
```

{% endcode %}


# Run a Layer Validator (testnet)

Follow the steps to become a Tellor testnet validator.

## Prerequisites

You will need a [node that's fully synced](/tellor/running-palmito-testnet/node-setup) and [an account that has a balance](/tellor/running-palmito-testnet/manage-accounts) (loya).

#### Create your Validator:

1\) Check if your account has funds:

{% code overflow="wrap" %}

```bash
./layerd query bank balance YOUR_ACCOUNT_NAME loya
```

{% endcode %}

This outputs something like:

```bash
balance:
  amount: "123456789"
  denom: loya
```

{% hint style="success" %} <mark style="color:blue;">**If you need testnet TRB, send us a message in the public**</mark> [<mark style="color:blue;">**Discord**</mark>](https://discord.gg/HX76jMhvG6) <mark style="color:blue;">**(#testing-layer channel)!**</mark> \ <mark style="color:blue;">**Note: You will need to**</mark> [<mark style="color:blue;">**bridge the funds**</mark>](/tellor/bridging-trb) <mark style="color:blue;">**once they are received on Sepolia.**</mark>
{% endhint %}

#### 2) Retrieve your Node's Pubkey

This is a unique identifier for a node running on your computer:

<pre class="language-bash"><code class="lang-bash"><strong>./layerd comet show-validator
</strong></code></pre>

This returns your validator pubkey. It should look like this:

```bash
{"@type":"/cosmos.crypto.ed25519.PubKey","key":"FX9cKNl+QmxtLcL926P5yJqZw7YyuSX3HQAZboz3TjM="}
```

Copy this output for the next step.

#### **3) Edit the Validator Configuration File**

Create (or edit) the validator.json file:

```bash
nano validator.json
```

Edit or add the following code. Always double check that the pubkey matches the output that you got in step 2:

```json
{
    "pubkey": {"@type":"/cosmos.crypto.ed25519.PubKey","key":"c1234EuycPpuasdfVlasdfoyPSImHHJz1z0ODKveo="},
    "amount": "69666420loya",
    "moniker": "yourmoniker",
    "identity": "optional identity signature (ex. UPort or Keybase)",
    "website": "validator's (optional) website",
    "security": "validator's (optional) security contact email",
    "details": "validator's (optional) details",
    "commission-rate": "0.1",
    "commission-max-rate": "0.2",
    "commission-max-change-rate": "0.01",
    "min-self-delegation": "2"
}
```

* Edit `"pubkey"` to match yours from step 2. (important!)
* Edit `"amount"` to be the amount of testnet TRB that you would like to stake with 6 decimals and the "loya" denom. (For example: if you want to stake 99 TRB use `"amount": "99000000loya"`)
* Edit `"moniker"` with a name you choose for your validator node.
* Edit identity, website, security, and details with your identifying information. (optional)
* Edit `commission-rate`, `commission-max-rate`, `commission-max-change-rate`, and `min-self-delegation` if desired. (these can be changed later using the `edit-validator` command).

{% hint style="success" %} <mark style="color:blue;">**Important Considerations for your Validator:**</mark>

* <mark style="color:blue;">When creating your validator, be sure that you are NOT choosing an "amount" that is larger than your balance of test-net TRB.</mark>
* <mark style="color:blue;">TRB has 6 decimals: 1 loya is 0.000001 TRB</mark>
* <mark style="color:blue;">Note: TRB tokens are used for gas on the layer network. As a validator / reporter you will need to make transactions to send tokens, become a reporter, unjail, etc. When choosing the amount to stake, it is important to reserve some TRB for gas.</mark>
* <mark style="color:blue;">**Staking on Tellor is limited to 5% of the total staked tokens per 12 hours. You can check the current amount that's allowed to stake**</mark> [<mark style="color:blue;">**here**</mark>](https://explorer.tellor.io)<mark style="color:blue;">**.**</mark>
  {% endhint %}

#### **4) Create your validator.**

Run the following command to create-validator:

{% code overflow="wrap" %}

```bash
./layerd tx staking create-validator ./validator.json --chain-id layertest-5 --from YOUR_ACCOUNT_NAME --gas 300000 --fees 8loya --yes
```

{% endcode %}

**5) Verify that creation was successful.**

Use the command:

{% code overflow="wrap" %}

```bash
./layerd query staking validator YOUR_ACCOUNT_NAME
```

{% endcode %}

If `status: 3,`you are staked and validating!

{% hint style="info" %}
If `status` is `1`, It means that you are not bonded. This can happen If you accidentally made your "amount" in step 4 too small. Check that you are staking at least 1 TRB (1000000loya).\
\
If `status` is `2`, It means that your validator is jailed. If this happens, check if the node process is running on your host machine.
{% endhint %}

You can unjail with steps shown in the [next section.](/tellor/running-palmito-testnet/run-the-data-reporter)


# Slashing Rules for Validators

Slashing, jailing, and how to unjail your validator.

### Context

*Tellor inherits validator slashing mechanisms from CometBFT. A detailed understanding can be found in the* [*cosmos SDK documentation*](https://docs.cosmos.network/main/build/modules/slashing)*.*

## Slashing, Jailing, and Tombstoneing

There are two basic reasons that a validator may be automatically slashed, jailed or tombstoned: <mark style="color:yellow;">**liveness**</mark> and <mark style="color:red;">double signing</mark>.

### **Liveness (inactivity):**

If your validator fails to sign for 500 blocks (e.g. the validator node is down for 500 blocks), the validator will be automatically jailed. At the time of writing layertest-5 has a 1.8s average block time, so it takes approximately 15 minutes of inactivity before a validator is jailed.

The penalty for inactivity is 1% of bonded tokens. Liveness slashes do not lead to a tombstoning.

If your node is Jailed for inactivity, you can simply "**unjail**" it via cli on the host machine:

**Double Signing:**

Unjustified pre-commits (double signs) are rare, and the penalty is severe. If a double sign is detected the validator is automatically slashed up to 50% and tombstoned, while their delegators are forced to unbond or redelegate their token voting power.\
\
A “tombstoned" validator key can never be used again. The validator may rejoin the network using another node key, but they will have to earn back the trust of any delegators they previously had.

{% hint style="danger" %}
Warning: It is possible to double sign blocks accidentally during complex operations like migrating a validator node to a different machine. Always be 100% sure that the layer node process on the old machine is dead before starting it up on the new machine!
{% endhint %}

## Check Your Validator's Status

You can check your validator's status on the[ block explorer ](https://explorer.tellor.io/validators)or via cli:

```sh
./layerd query staking validator ACCOUNT_NAME
```

"status: 2" means that you are jailed.

## How to Unjail

Unjail your validator with the command:

{% code overflow="wrap" %}

```bash
./layerd tx slashing unjail --from YOUR_ACCOUNT_NAME --chain-id layertest-5 --fees 5loya --yes
```

{% endcode %}


# Run a Data Reporter (testnet)

Operate a Data Reporter!

## Prerequisites

* A working[ node](/tellor/running-palmito-testnet/node-quick-start-testnet).
* An account for creating a reporter that has either [created](/tellor/running-palmito-testnet/run-a-layer-validator) or [delegated](/tellor/command-line-usage/leveraging-layerd/delegate-to-a-validator) to a validator.

#### 1) Configure a Reporter on Tellor

Use the `layerd` cli register and initialize your reporter configuration. Commission-rate and min-tokens-required are shown at safe values, but can be adjusted (now or later) for personal preference:

{% code overflow="wrap" %}

```bash
# create-reporter [commission-rate] [min-tokens-required] [moniker] [flags]
./layerd tx reporter create-reporter 0.05 1000000 REPORTER_MONIKER --from YOUR_ACCOUNT_NAME --chain-id layertest-5 --fees 10loya --yes
```

{% endcode %}

Parameters:

* A (example) `commission-rate` of `0.05` means that you get 5% of rewards from your selectors.
* A (example) `min-tokens-required` value of `1000000` prevents spam by requiring that selectors have at least 1 TRB in their wallet. This can be changed later.
* Choose a `REPORTER_MONIKER` that you love! (It does not need to be the same as your validator moniker.)

#### 2) Check if your reporter was created successfully:

```sh
./layerd query reporter reporters | grep -A 7 YOUR_TELLOR_ADDRESS
```

If your reporter was created successfully, this will output your reporter information.

#### 3) Download the latest `reporterd` binary:

Download [reporterd v0.2.8](https://github.com/tellor-io/layer-daemons/releases/tag/v0.2.8):

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/reporter && cd ~/layer/binaries/reporter && wget https://github.com/tellor-io/layer-daemons/releases/download/v0.2.8/reporterd_Linux_x86_64.tar.gz && tar -xvzf reporterd_Linux_x86_64.tar.gz && rm reporterd_Linux_x86_64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Mac" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/reporter && cd ~/layer/binaries/reporter && wget https://github.com/tellor-io/layer-daemons/releases/download/v0.2.8/reporterd_Darwin_arm64.tar.gz && tar -xvzf reporterd_Darwin_arm64.tar.gz && rm reporterd_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### 4) Create `.env`

`reporterd` loads environment variables from a `.env` file in the current working directory (or from `../.env` when run from a subdirectory). You can also set these in a [systemd service file](/tellor/running-palmito-testnet/node-setup/example-.service-files) instead.

Copy [`env.example`](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/env.example) from layer-daemons and edit the values for your setup:

{% code overflow="wrap" %}

```sh
cd ~/layer/binaries/reporter
wget https://raw.githubusercontent.com/tellor-io/layer-daemons/v0.2.8/env.example
cp env.example .env
```

{% endcode %}

At minimum, set `LAYER_HOME`, `FROM`, `KEYRING_BACKEND`, `RPC_NODES`, `GRPC_NODES`, and your custom query API keys. `RPC_NODES`, `GRPC_NODES`, `BRIDGE_CHAIN_RPC_NODES`, and `ETH_MAINNET_RPC_NODES` accept comma-separated endpoint lists, with the first endpoint used as the primary and later endpoints used as ordered fallbacks.

Most CLI flags can be provided as environment variables by uppercasing the flag name and replacing `-` or `.` with `_` (for example, `--keyring-backend` becomes `KEYRING_BACKEND`). Use `LAYER_HOME` for the Layer home directory instead of relying on the shell's `HOME`. When using `KEYRING_BACKEND=file`, set `KEYRING_PASSWORD_FILE` to a file that contains the keyring password and is readable only by the service user.

On testnet, point `BRIDGE_CHAIN_RPC_NODES` at your Sepolia (or other bridge-chain) RPC endpoints. Because the bridge chain is not Ethereum mainnet, also set `ETH_MAINNET_RPC_NODES` so custom query contract reads use mainnet endpoints. The built-in custom query templates also use `CMC_PRO_API_KEY`, `CGPRO_API_KEY`, `SUBGRAPH_API_KEY`, and, when `ETH_MAINNET_RPC_NODES` is unset, `INFURA_API_KEY` and `ALCHEMY_API_KEY`.

*Note: API keys are not strictly required, but reporters should set them to enable reporting for all tipped feeds and maximize earnings.*

{% hint style="info" %}
See the [layer-daemons README](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/README.md) and [`env.example`](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/env.example) for all available options, including remote signer, dispute monitor, custom query cache, auto-unbonding, price guard, and auto balance-to-keep bridge settings.
{% endhint %}

#### 5) Start the reporter:

From the directory containing your `.env` file:

{% code overflow="wrap" %}

```bash
cd ~/layer/binaries/reporter && ./reporterd
```

{% endcode %}

If you prefer CLI flags instead of `.env`, you can still pass them explicitly. Environment variables take precedence over matching flags when both are set:

{% code overflow="wrap" %}

```bash
./reporterd --grpc 127.0.0.1:9090 --node tcp://127.0.0.1:26657 --from ACCOUNT_NAME --home ~/.layer --keyring-backend test
```

{% endcode %}

Here is an example start command for a reporter who wants to automatically unbond 2.999 TRB (2999999 loya) per day with a maximum set to 1% of their total stake:

{% code overflow="wrap" %}

```bash
./reporterd --auto-unbonding-frequency 1 --auto-unbonding-amount 2999999 --auto-unbonding-max-stake-percentage 0.01
```

{% endcode %}

The same auto-unbonding settings can be set in `.env`:

```sh
AUTO_UNBONDING_FREQUENCY=1
AUTO_UNBONDING_AMOUNT=2999999
AUTO_UNBONDING_MAX_STAKE_PERCENTAGE=0.01
```

{% hint style="success" %}
You can set up a grafana dashboard using [this\_guide](/tellor/setting-up-a-grafana-dashboard-for-your-layer-node) to monitor things in Tellor such as average gas price for submitting a report, block times, total bonded tokens, etc.
{% endhint %}

Congratulations on becoming a Tellor Reporter! 🎉


# Updating reporterd

Steps for updating your reporter daemon.

{% hint style="success" %}
It's important to keep your Tellor reporter software up-to-date with all the latest feeds so that you can maximize rewards. This is done separately from chain (layerd) upgrades
{% endhint %}

### 1. Stop your reporter.

### 2. Remove the old `reporterd` binary and Configs:

*Be sure to set the correct paths to these files if your setup is different:*

{% code overflow="wrap" %}

```sh
rm ~/layer/binaries/reporter/reporterd
rm ~/layer/binaries/reporter/README.md
rm ~/.layer/config/market_params.toml
rm ~/.layer/config/custom_query_config.toml
rm ~/.layer/config/pricefeed_exchange_config.toml
```

{% endcode %}

### 3. Update your `.env` or service file

Compare your `.env` against the [layer-daemons `env.example`](https://github.com/tellor-io/layer-daemons/blob/v0.2.8/env.example) for the current variable names and defaults.

Compare your `.service` file against the [example reporterd service file](/tellor/running-palmito-testnet/node-setup/example-.service-files) and update your `Environment` settings to match the current variable names and defaults.

### 4. Download the latest `reporterd` release

Download [reporterd v0.2.8](https://github.com/tellor-io/layer-daemons/releases/tag/v0.2.8):

{% tabs %}
{% tab title="Linux" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/reporter && cd ~/layer/binaries/reporter && wget https://github.com/tellor-io/layer-daemons/releases/download/v0.2.8/reporterd_Linux_x86_64.tar.gz && tar -xvzf reporterd_Linux_x86_64.tar.gz && rm reporterd_Linux_x86_64.tar.gz
```

{% endcode %}
{% endtab %}

{% tab title="Mac" %}
{% code overflow="wrap" %}

```sh
mkdir -p ~/layer/binaries/reporter && cd ~/layer/binaries/reporter && wget https://github.com/tellor-io/layer-daemons/releases/download/v0.2.8/reporterd_Darwin_arm64.tar.gz && tar -xvzf reporterd_Darwin_arm64.tar.gz && rm reporterd_Darwin_arm64.tar.gz
```

{% endcode %}
{% endtab %}
{% endtabs %}

### 5. Restart your reporter

Note: The `--chain-id` flag has been removed. All other CLI flags are optional when configuration is provided via your `.env` or service file.

{% code overflow="wrap" %}

```sh
cd ~/layer/binaries/reporter && ./reporterd
```

{% endcode %}


# Unjail Your Reporter

Example command to unjail your reporter:

In the event of a dispute, your reporter will be jailed.

If the dispute is just a warning, you can unjail right away. The command to do this is:

{% code overflow="wrap" %}

```sh
# layerd tx reporter unjail-reporter [flags]
./layerd tx reporter unjail-reporter --from ACCOUNT_NAME --fees 5loya --chain-id layertest-5
```

{% endcode %}


# Switch Reporter or Selector

Steps for changing your reporter selection.

Note: Reporters who want to "retire" and become selectors must wait 21 days to prevent bridge manipulation.

The following command can be used to change your reporter selection:

{% code overflow="wrap" %}

```sh
./layerd tx reporter switch-reporter NEW_REPORTER_ADDRESS --from OLD_REPORTER_ADDRESS --fees 5loya --chain-id layertest-5
```

{% endcode %}


# Withdraw TRB (to Sepolia)

How to get your funds back to Ethereum

#### **1.** Navigate to [hub.tellor.io](https://hub.tellor.io/)

Click the bridge to ethereum toggle and connect your wallets:

<figure><img src="https://2729899787-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fs90SVtIdiQ8dmMsqriIa%2Fuploads%2FBsrDiIlswjl94WPBuzNK%2FScreenshot%202025-09-25%20at%202.46.00%E2%80%AFPM.png?alt=media&amp;token=33df9008-d984-4823-9cbd-c55fd0b665da" alt=""><figcaption></figcaption></figure>

2. Fill in the fields with the number of TRB that you wish to withdraw, and a good receiving address for ERC20 TRB on ethereum.
3. Click Request Withdrawal!
4. Wait 12 hours for your withdrawal to process.


# Withdraw Using CLI

Exit tellor permissionlessly even if the front-end is down.

#### 1. Use the CLI to Request a Withdrawal

In the following example command, our Tellor address is `tellor1suuc9d5dr5stps5tzjv5d95ur02827ardn5` and the ethereum address that we want to withdraw to is `0x7660794eF8f978Ea0922DC29B4d93e1fc94A`. (Adjust these two parameters to match your addresses.)

{% code overflow="wrap" %}

```sh
# layerd tx bridge withdraw-tokens [creator] [recipient] [amount] [flags]
./layerd tx bridge withdraw-tokens tellor1suuc9d5dr5stps5tzjv5d95ur02827ardn5 7660794eF8f978Ea0922DC29B4d93e1fc94A 69010069loya --from YOUR_ACCOUNT_NAME --fees 5loya --chain-id layertest-5
```

{% endcode %}

*Save the transaction hash from the output.*

#### 2. Gather information about your request

Use the command:

{% code overflow="wrap" %}

```sh
./layerd query tx --type=hash <YOUR_TRANSACTION_HASH> | grep -A 1 -e raw_log -e query_id -e withdraw_id
```

{% endcode %}

Copy the output to use later. It should look similar to this:

```
    key: query_id
    value: 866997ed9d1a463f0ce8ba1d55a6b7545ba1e4ba1292ae502b6a859b5e1d3a5d
--
    key: withdraw_id
    value: "8"
--
raw_log: ""
timestamp: "2025-05-02T16:11:27Z"
```

#### **3. Wait 12 hours.**

There is a 12 hour delay for bridge requests to and from Tellor.

#### 4. Find the timestamp of the aggregate report using the query\_id from step 2:

<pre class="language-sh" data-overflow="wrap"><code class="lang-sh"># layerd query oracle get-current-aggregate-report [query_id] [flags]
<strong>./layerd query oracle get-current-aggregate-report &#x3C;your_query_id_from_step_2>
</strong></code></pre>

This will output information about the report. Copy the `timestamp` for step 4.

**5. Request attestations for your withdraw request report:**

{% code overflow="wrap" %}

```bash
# layerd tx bridge request-attestations [creator] [query_id] [timestamp] [flags]
./layerd tx bridge request-attestations $TELLOR_ADDRESS <query_id_from_step2> <timestamp_from_step_3> --from $ACCOUNT_NAME --chain-id layertest-5 --fees 50loya --yes
```

{% endcode %}

{% hint style="info" %}
Behind the scenes, py-relayer is used to send attestation information back to the bridge contract on Sepolia. As long as gas costs on the network are not egregious, `withdrawFromLayer` will be called automatically!
{% endhint %}

**6. Check your balance on Sepolia!**


# Leveraging layerd

Commands for interacting with Tellor using the command line interface.

{% content-ref url="/pages/cKxpMcRsfNuBfUY6dsWA" %}
[Query the Chain](/tellor/command-line-usage/leveraging-layerd/query-the-chain)
{% endcontent-ref %}

{% content-ref url="/pages/48i08kwxtvnTkRHuDwCT" %}
[Creating Transactions](/tellor/command-line-usage/leveraging-layerd/creating-transactions)
{% endcontent-ref %}

{% content-ref url="/pages/F93sv8tCGQmBklb3psHa" %}
[Delegate to a Validator](/tellor/command-line-usage/leveraging-layerd/delegate-to-a-validator)
{% endcontent-ref %}

{% content-ref url="/pages/Kh7vy5R2neboWp2bU5VM" %}
[Select a Reporter](/tellor/command-line-usage/leveraging-layerd/select-a-reporter)
{% endcontent-ref %}


# Query the Chain

Use the cli to query Tellor for information about accounts, validators, reports, disputes, governance and more.

{% hint style="info" %}
*<mark style="color:blue;">**Use the node flag like**</mark><mark style="color:blue;">**&#x20;**</mark><mark style="color:blue;">**`--node=http://tellorlayer.com:26657`**</mark><mark style="color:blue;">**&#x20;**</mark><mark style="color:blue;">**to query the chain without running a local node.**</mark>*
{% endhint %}

If you don't already have the binary, download the latest release [here](https://github.com/tellor-io/layer/tags).

The full list of `./layerd query` as shown via `./layerd query --help` :

```sh
Available Commands:
  auth                Querying commands for the auth module
  authz               Querying commands for the authz module
  bank                Querying commands for the bank module
  block               Query for a committed block by height, hash, or event(s)
  bridge              Querying commands for the bridge module
  comet-validator-set Get the full CometBFT validator set at given height
  consensus           Querying commands for the consensus module
  dispute             Querying commands for the dispute module
  distribution        Querying commands for the distribution module
  evidence            Querying commands for the evidence module
  feegrant            Querying commands for the feegrant module
  globalfee           Querying commands for the global fee module
  gov                 Querying commands for the gov module
  group               Querying commands for the group module
  ibc                 Querying commands for the IBC module
  ibc-transfer        IBC fungible token transfer query subcommands
  interchain-accounts IBC interchain accounts query subcommands
  oracle              Querying commands for the oracle module
  registry            Querying commands for the registry module
  reporter            Querying commands for the reporter module
  slashing            Querying commands for the slashing module
  staking             Querying commands for the staking module
  tx                  Query for a transaction by hash, "<addr>/<seq>" combination or comma-separated signatures in a committed block
  tx                  Query for a transaction by hash, "<addr>/<seq>" combination or comma-separated signatures in a committed block
  txs                 Query for paginated transactions that match a set of events
  upgrade             Querying commands for the upgrade mod
```

### examples:

```sh
# to check balance. Use a tellor address or your local account name.
# e.g. for tellor1p8xk2xqwgszmerk83dvjszddp5adqs5hwaupjt
./layerd query bank balance tellor1p8xk2xqwgszmerk83dvjszddp5adqs5hwaupjt loya

# get a list of validators and their status
./layerd query staking validators

# get info about a validator by it's moniker. 
./layerd query staking validators | grep -A 5 "bob_moniker"

# get a list of reporters
./layerd query reporter reporters

# get a list of their reportrs
# e.g. for tellor1d8rrlk20qqxd69xl2zen503x7uux0wnl
./layerd query oracle get-reportsby-reporter tellor1d8rrlk20qqxd69xl2zen503x7uux0wnl

# check the reporter address that your account is selecting
# any address may also be used instead of $ACCOUNT_NAME
./layerd query reporter selector-reporter $ACCOUNT_NAME

# get governance information
./layerd query gov proposals

# get gov proposal vote tallies
./layerd query gov tally 1

# get list of open dispute IDs
./layerd query dispute open-disputes

# query record of disputes with more information
./layerd query dispute disputes

# check rewards
# delegator-addr should be a tellor prefix address
# validator-addr should be a tellorvaloper prefix address
# both addresses are required even if validator and reporter are same account
./layerd query distribution rewards-by-validator [delegator-addr] [validator-addr]

# to examine a transaction (tx)
# example for tx hash 9CE91600D5291C0CD267F950AC254AA469FE97C8444EFE9EC8E9E41BD4DEE523
./layerd query tx --type=hash 9CE91600D5291C0CD267F950AC254AA469FE97C8444EFE9EC8E9E41BD4DEE523
```


# Creating Transactions

Use the cli to create Tellor transactions.

Use `./layerd tx --help` to view available commands.

{% hint style="info" %} <mark style="color:blue;">Note: the --help flag can be used after any command to show it's sub-commands and required arguments.</mark>
{% endhint %}

```
Available Commands:
                      
  auth                Transactions commands for the auth module
  authz               Authorization transactions subcommands
  bank                Bank transaction subcommands
  bridge              Transactions commands for the bridge module
  broadcast           Broadcast transactions generated offline
  consensus           Transactions commands for the consensus module
  decode              Decode a binary encoded transaction string
  dispute             Transactions commands for the dispute module
  distribution        Distribution transactions subcommands
  encode              Encode transactions generated offline
  evidence            Evidence transaction subcommands
  feegrant            Feegrant transactions sub-commands
  globalfee           Transactions commands for the globalfee module
  gov                 Governance transactions subcommands
  group               Group transaction subcommands
  ibc                 IBC transaction subcommands
  ibc-transfer        IBC fungible token transfer transaction subcommands
  interchain-accounts IBC interchain accounts transaction subcommands
  interchainquery     Transactions commands for the interchainquery module
  mint                Transactions commands for the mint module
  multi-sign          Generate multisig signatures for transactions generated offline
  oracle              Transactions commands for the oracle module
  registry            Transactions commands for the registry module
  reporter            Transactions command for the reporter module
  sign                Sign a transaction generated offline
  sign-batch          Sign transaction batch files
  slashing            Transactions commands for the slashing module
  staking             Staking transaction subcommands
  upgrade             Upgrade transaction subcommands
  validate-signatures validate transactions signatures
  vesting             Vesting transaction subcommands
```

## Examples

### **To send tokens:**

{% code overflow="wrap" %}

```sh
# NOTE: balances of TRB have 6 decimals on layer.
# e.g. sending 123 TRB to tellor18wjwgr0j8pv4ekkpntdylftwz8ml97
./layerd tx bank send $ACCOUNT_NAME tellor18wjwgr0j8pv4ekkpntdylftwz8ml97 123000000loya --fees 5loya --chain-id layertest-5
```

{% endcode %}

### **Sending a Tip (data request):**

Tips can be used by anyone to request data. The tip command has three required arguments.\
`./layerd tx oracle tip [tipper] [query_data] [amount] [flags]` . Here is an example of a tip command for the current USDC/USD Spot Price.

{% code overflow="wrap" %}

```
./layerd tx oracle tip 00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000953706f745072696365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000004757364630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037573640000000000000000000000000000000000000000000000000000000000 10000loya from $ACCOUNT_NAME --fees 12loya --gas auto --chain-id layertest-5
```

{% endcode %}

{% hint style="danger" %} <mark style="color:blue;">**To prevent spam, Tellor requires that a tip a provided for the data that's being reported.**</mark>
{% endhint %}

**Report a value optimistically (requires tipping first):**

{% code overflow="wrap" %}

```sh
# layerd tx oracle submit-value [creator] [qdata] [value] [salt] [flags]
# example for reporter's address tellor1xk9amtcxllqh8s8cyy0kzxhmreuttq0
./layerd tx oracle submit-value tellor1xk9amtcxllqh8s8cyy0kzxhmreuttq0 
00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000953706f745072696365000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000047573646300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000375736400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004a5ba50 --from tellor1xk9amtcxllqh8s8cyy0kzxhmreuttq0 --chain-id 
layertest-5 --fees 1000loya --gas 400000
```

{% endcode %}

***Note: The query\_data shown here is for usdc-usd-spot . To generate query\_data for the query that you need, check out the*** [***"querybuilder" tool here.***](https://tellor.io/queryidstation/)


# Delegate to a Validator

When you delegate to a validator you will increase their power while earning rewards minus that validators commission.

When you delegate to a validator, losses can occur due to that validator's inactivity or misbehavior.

Be sure to select a validator that you trust!

{% code overflow="wrap" %}

```sh
# layerd tx staking delegate [validator-addr] [amount] [flags]
# example delegating 12 TRB to tellorvaloper1dct4uwgcfjxqaphjm33n9fycxdz2m6
./layerd tx staking delegate tellorvaloper1dct4uwgcfjxqaphjm33n9fycxdz2m6 12000000loya --from YOUR_ACCOUNT_NAME --fees 5loya --chain-id layertest-5 --node https://node-palmito.tellorlayer.com/rpc/
```

{% endcode %}


# Select a Reporter

When you select a reporter you increase their reporting power while earning rewards minus the reporter's commission.\
\
When you select a reporter, losses can occur if that reporter is disputed.

Be sure to select an active reporter who you trust!

{% code overflow="wrap" %}

```sh
# layerd tx reporter select-reporter [reporter-address] [flags]
# Example selecting reporter tellor148zgkh394d382g4rft3dhl2wx0g6r743vv4q
./layerd tx reporter select-reporter tellor148zgkh394d382g4rft3dhl2wx0g6r743vv4q --from YOUR_ACCOUNT_NAME --fees 5loya --chain-id layertest-5 --node https://node-palmito.tellorlayer.com/rpc/
```

{% endcode %}


# Contracts Reference

Record of EVM contracts for Tellor by network

<details>

<summary>Ethereum</summary>

#### **Mainnet**

* DataBridge: [0xFfa3393BE1E4b442fff6cD0df0794B0031e9CF65](https://etherscan.io/address/0xffa3393be1e4b442fff6cd0df0794b0031e9cf65)
* DataBank: [0x5526e7e7CF982f5D3045DAf18b7e813E4b7a8FE5](https://etherscan.io/address/0x5526e7e7cf982f5d3045daf18b7e813e4b7a8fe5)

#### **Sepolia**

* DataBridge: [0xc6760FD47FbB799619F3fD5BD79929d330628506](https://sepolia.etherscan.io/address/0xc6760FD47FbB799619F3fD5BD79929d330628506)
* DataBank: [0x3d3263D0c2637eA55dEA4110eDD4F2cf3102f613](https://sepolia.etherscan.io/address/0x3d3263d0c2637ea55dea4110edd4f2cf3102f613)

</details>

<details>

<summary>Base</summary>

#### **Mainnet**

* DataBridge: [0xFfa3393BE1E4b442fff6cD0df0794B0031e9CF65](https://basescan.org/address/0xFfa3393BE1E4b442fff6cD0df0794B0031e9CF65)
* DataBank: [0x5589e306b1920F009979a50B88caE32aecD471E4](https://basescan.org/address/0x5589e306b1920f009979a50b88cae32aecd471e4)

</details>


# Relay Data to EVM Chains

Relay oracle data, validator set, and bridge information updates back and forth between tellor and any EVM chain.

The [relayer](https://github.com/tellor-io/py-relayer) queries tellor for oracle data and their proofs and submits them to a user contract on other chains.

### Setup

1. Clone the repo:

```bash
git clone https://github.com/tellor-io/py-relayer.git
```

2. Navigate to the repository directory:

```bash
cd py-relayer
```

3. Create a virtual environment:

```bash
python3 -m venv venv
source venv/bin/activate
```

4. Install the dependencies:

```bash
pip install -r requirements.txt
```

5. Install the package:

```bash
pip install -e .
```

6. Copy the .env.example file to .env and set the appropriate environment variables:

```bash
cp .env.example .env
```

The "email" section of the .env file is optional. If you want to receive emails when layer is down, input your gmail username and password. We recommend using an [app password](https://support.google.com/accounts/answer/185833?hl=en) for your gmail account.

Other than the email section, all .env variables can alternatively be set through the CLI. We recommend setting your ethereum private key in the .env file for security reasons. For convenience, you should set any parameters which tend to remain constant across runs in the .env file. CLI arguments will override .env variables.

#### Additional Requirements for Ubuntu

If you are running the relayer on ubuntu, you may need to install additional tools:

```bash
sudo apt update
sudo apt install build-essential python3-dev
```

After installing these dependencies, proceed with the setup instructions above.

### Usage

The relayer provides several commands through its CLI:

#### Start Relaying

```bash
relayer relay --layer-test-user-address 0x44941f399c4c009b01bE2D3b0A0852dC8FFD2C4a --data-bridge-address 0xC69f43741D379cE93bdaAC9b5135EA3e697df1F8 --layer-swagger https://node-palmito.tellorlayer.com/ --layer-rpc https://node-palmito.tellorlayer.com/rpc/ --contract-type TestPriceFeedUser --sleep-time 7200
```

#### Update Oracle Data Once

```bash
relayer update --query-id 0x83a7f3d48786ac2667503a61e8c415438ed2922eb86a2906e4ee66d9a2ce4992
```

#### Relay Token Bridge Withdraw

```bash
relayer relay-bridge --data-bridge-address 0xC69f43741D379cE93bdaAC9b5135EA3e697df1F8 --token-bridge-address 0x5acb5977f35b1A91C4fE0F4386eB669E046776F2 --withdraw-id 8
```

#### Initialize Data Bridge

This command initializes the TellorDataBridge contract after deployment. This must be run by the contract deployer address.

```bash
relayer init
```

#### Reset Data Bridge

This command resets the validator set in the TellorDataBridge contract in the event that the last relayed validator set is over 21 days old. This can only be run by the TellorDataBridge contract’s `guardian` address.

```bash
relayer reset
```

To see all available options for each command:

```bash
relayer --help
relayer relay --help
```


# Integrating Tellor Data

Safely integrate tellor oracle data into your contracts

Integrating tellor data into a user contract involves two major aspects:

* Verifying that the data is authentic tellor data
* Custom data checks unique to your use case and data needs

{% hint style="info" %}
See the [SampleLayerUser repo](https://github.com/tellor-io/SampleLayerUser) for a few example oracle use case implementations.
{% endhint %}

{% hint style="info" %}
See the [Contracts Reference](/tellor/using-tellor-data/databridge-contracts-reference) page for deployed contract addresses. You are also welcome to deploy your own.
{% endhint %}

### Verifying Data Authenticity

Tellor uses validator attestations to verify that data came from tellor. If at least 2/3 of tellor validators (by stake power) signed some data, we consider that to be authentic tellor data. The TellorDataBridge contract is responsible for verifying data authenticity. It does this by keeping track of the tellor validator set and verifying that at least 2/3 of tellor validators signed the data. As a user contract, you only need to pass the attestation data, validator set, and signature info to the TellorDataBridge contract for this authentication step.

We will install the usingtellorlayer npm package to gain access to the TellorDataBridge interface:

```bash
npm i usingtellorlayer
```

The code block below shows how you can connect your contract to TellorDataBridge and pass tellor data to it to verify its authenticity.

```solidity
import "usingtellorlayer/contracts/interfaces/ITellorDataBridge.sol";

contract SamplePredictionMarketUser {
	ITellorDataBridge public bridge;
	
	constructor(address _bridge) {
		bridge = ITellorDataBridge(_bridge);
	}

	function updateOracleData(
        	OracleAttestationData calldata _attestData, 
        	Validator[] calldata _currentValidatorSet, 
        	Signature[] calldata _sigs
    	) public {
		// **************************************************
		// * AUTHENTICITY: verify that data came from tellor chain
		// **************************************************
		bridge.verifyOracleData(_attestData, _currentValidatorSet, _sigs);

		// … 
	}
}
```

Once your contract has verified that the inputted data is authentic tellor data, you should continue to performing custom checks based on your unique use case.

### Custom Checks

Custom checks will vary based on the use case and any other unique data needs. In this example contract, we show some checks used by an example prediction market.

#### Example Case

1. Verify that relayed data is the data we expect by checking the `queryId`.
   * For this example, we created a custom data type `PredictionMarketExample` which uses `marketId` and `chainId` arguments to create a unique identifier for each market
2. As a sanity check, make sure the data was reported after the market expiration time.
   * If your market allows resolution anytime after the market was created, use the market's start time instead of expiration time here.
3. Verify that `aggregatePower` meets some threshold. This is the amount of reporter stake power that was used to create the oracle data.
   * We used the `powerThreshold` from the TellorDataBridge contract as our threshold in the example below. This is equal to 2/3 of the total tellor stake amount.
   * In the event that the power does not reach the higher threshold, we check that the data both reaches the lower threshold, and has been on chain for a period of time to allow for disputes.

```solidity
	function updateOracleData(
        		OracleAttestationData calldata _attestData, 
        		Validator[] calldata _currentValidatorSet, 
        		Signature[] calldata _sigs, 
        		uint256 _marketId // id created for this use case
        ) public {
                // ...

		// **************************************************
		// * USER CHECKS: verify that the data is correct for this unique use case
		// **************************************************
		// verify that this data is for the correct marketId
		bytes32 _queryId = _getQueryId(_marketId);
		require(_queryId == _attestData.queryId);

                // verify that the attestations are not too old
                require(block.timestamp - (_attestData.attestationTimestamp / 1000) < 10 minutes);

		// verify that data was created after market expiration time
		require(_attestData.report.timestamp / 1000 > markets[_marketId].expiration);

		// verify data reporter power meets threshold (2/3 total power) or optimistic period
		if (_attestData.report.aggregatePower < bridge.powerThreshold()) {
				// make sure optimistic data meets lower threshold (1/3 total power)
				require(_attestData.report.aggregatePower > bridge.powerThreshold() / 2);
				// make sure data stayed on chain for at least 12 hours without being disputed
				require(_attestData.attestationTimestamp - _attestData.report.timestamp > (12 hours * 1000));
		}

		// ...
	}

	function _getQueryId(uint256 _marketId) private pure returns(bytes32) {
		bytes memory _queryDataArgs = abi.encode(chainId, _marketId);
		bytes memory _queryData = abi.encode(“PredictionMarketExample”, _queryDataArgs);
		bytes32 _queryId = keccak256(_queryData);
		return _queryId;
	}
```

### Use the Data

Once the data has passed the authenticity and custom user checks, you can decode and use the data. In this example, we defined a data type `PredictionMarketExample` which returns a `uint` 1-3 denoting a result of "Yes", "No", or "Invalid", respectively. Since all tellor data is reported in bytes, we decode the bytes to a uint, perform a few more sanity checks, and finally save the relayed oracle data in the contract.

```solidity
pragma solidity 0.8.19;

import "usingtellorlayer/contracts/interfaces/ITellorDataBridge.sol";

contract SamplePredictionMarketUser {
	ITellorDataBridge public bridge;
	MarketInfo[] public markets;
	uint256 public chainId = block.chainid;

	struct MarketInfo {
		string details;
		uint256 result; // 0-unresolved, 1-yes, 2-no, 3-invalid 
		uint256 expiration;
	}
	
	constructor(address _bridge) {
		bridge = ITellorDataBridge(_bridge);
	}

	function updateOracleData(
        	OracleAttestationData calldata _attestData, 
        	Validator[] calldata _currentValidatorSet, 
        	Signature[] calldata _sigs, 
        	uint256 _marketId
        ) public {
		// **************************************************
		// * AUTHENTICITY: verify that data came from tellor chain
		// **************************************************
		bridge.verifyOracleData(_attestData, _currentValidatorSet, _sigs);

		// **************************************************
		// * CUSTOM USER CHECKS: verify that the data is correct for this unique use case
		// **************************************************
		// verify that this data is for the correct marketId
		bytes32 _queryId = _getQueryId(_marketId);
		require(_queryId == _attestData.queryId);

        	// verify that the attestations are not too old
        	require(block.timestamp - (_attestData.attestationTimestamp / 1000) < 10 minutes);

		// verify that data was created after market expiration time
		require(_attestData.report.timestamp / 1000 > markets[_marketId].expiration);

        	// verify data reporter power meets threshold (2/3 total power) or optimistic period
        	if (_attestData.report.aggregatePower < bridge.powerThreshold()) {
            		// make sure optimistic data meets lower threshold (1/3 total power)
            		require(_attestData.report.aggregatePower > bridge.powerThreshold() / 2);
            		// make sure data stayed on chain for at least 12 hours without being disputed
            		require(_attestData.attestationTimestamp - _attestData.report.timestamp > (12 hours * 1000));
        	}

		// **************************************************
		// * USE THE DATA: resolve the market
		// **************************************************
		uint256 _result = abi.decode(_attestData.report.value, (uint256));
		_resolveMarket(_marketId, _result);
	}

	function _getQueryId(uint256 _marketId) internal view returns(bytes32) {
		bytes memory _queryDataArgs = abi.encode(chainId, _marketId);
		bytes memory _queryData = abi.encode("PredictionMarketExample", _queryDataArgs);
		bytes32 _queryId = keccak256(_queryData);
        	return _queryId;
	}

	function _resolveMarket(uint256 _marketId, uint256 _result) private {
		// make sure market is expired
		MarketInfo storage _market = markets[_marketId];
		require(block.timestamp > _market.expiration);

		// make sure market has not already been resolved
		require(_market.result == 0);

		// make sure the data conforms to the expected range (1, 2, or 3)
		require(_result > 0 && _result <= 3);
		
		// finally, save result
		_market.result = _result;
	}
}
```

### Available Metadata

Below is all of the data and metadata available to a user contract. We encourage users to find ways to use it to protect the integrity of their oracle data.

* **QueryId** - The unique identifier for each data type.
* **Aggregate Value** - This is the aggregated oracle data from all reporters who submitted.
* **Report Timestamp** - This is the timestamp of the block when the report was aggregated
* **Aggregate Power** - This is the total stake power of all reporters who reported to create this aggregate data.
* **Previous Timestamp** - This is the timestamp of the last aggregate report before this one.
* **Next Timestamp** - This is the timestamp of the next report aggregated after this one.
* **Last Validator Set Checkpoint** - This is a hash of the current validator set and some extra metadata.
* **Attestation Timestamp** - This is the time of when the attestation was created
* **Last Consensus Timestamp** - This is the timestamp of the last aggregate which had at least 2/3 of reporter power
* **Power Threshold** - This is equal to 2/3 of the total tokens tellor validators have at stake


# Integrate Tellor on a New Chain

Follow these steps to provide tellor data on a new evm chain

In this guide, we will go through the steps of providing access to tellor data on a new chain. You do not have to perform these steps yourself, and the tellor team would be happy to help if you contact us on [Discord](https://discord.com/invite/tellor).

For those with a do-it-yourself attitude, this guide will involve:

* deploying the TellorDataBridge contract
* deploying an example YOLO user contract YoloUser
* installing the relayer
* running the relayer

{% hint style="danger" %}
Following the steps in this guide does not guarantee access to absolutely secure oracle data. See the [Tellor Security 201](https://tellor.io/blog/layer-security-201/) article for more information.
{% endhint %}

### Clone Tellor and Install

First, clone SampleLayerUser repo:

```bash
git clone https://github.com/tellor-io/SampleLayerUser.git
```

Move to the SampleLayerUser directory:

```bash
cd SampleLayerUser
```

Install the tellor hardhat project:

```bash
npm i
```

### Deploy Contracts

Create an env file:

```bash
cp .env.example .env
```

Open your new `.env` file and add your ethereum private key and an rpc node url.

Open the `hardhat.config.js` file and add your evm chain information under `networks`. You can use the `sepolia` section as a guide.

#### TellorDataBridge

Now we're going to use deployment scripts to deploy the TellorDataBridge contract. This is the contract responsible for verifying that relayed data is authentic tellor data.

Open the deployment script `./scripts/DeployTellorDataBridge.js`. At the top of the file, you will see a variable `guardianaddress`. You will need to choose an address who is responsible for resetting the TellorDataBridge validator set in the event that it becomes stale (no updates within 21 days). As long as the validator set is always kept up to date in the contract, the guardian will have no special privileges or responsibilities.

\
Set the address to one of your own addresses:

```js
var guardianaddress = "0xYOUR_ADDRESS"
```

You should also update the `PK` and `NODE_URL` variables to match those in your `.env` file.

Now you should be able to deploy the TellorDataBridge contract:

```bash
npx hardhat run scripts/DeployTellorDataBridge.js --network YOUR_NETWORK
```

The following should print in your logs:

```
deploy TellorDataBridge
TellorDataBridge deployed to: 0xYOUR_DATA_BRIDGE_ADDRESS
```

We will use the address `0xYOUR_DATA_BRIDGE_ADDRESS` in the steps below.

#### YoloUser

Now we will deploy the YoloUser contract as an example oracle user.

Open the deployment script `./scripts/DeployYoloUser.js`. Set the TellorDataBridge address

```js
var dataBridgeAddress = "0xYOUR_DATA_BRIDGE_ADDRESS"
```

You will also need a queryId. We will use the ETH/USD spot price queryId in this example.

```js
var queryId = "0x83a7f3d48786ac2667503a61e8c415438ed2922eb86a2906e4ee66d9a2ce4992"
```

Update the `PK` and `NODE_URL` variables to match those in your `.env` file.

Now we are ready to deploy the YoloUser:

```bash
npx hardhat run scripts/DeployYoloUser.js --network YOUR_NETWORK
```

This will print in your logs:

```
deploying YoloUser
YoloUser deployed to: 0xYOUR_TELLOR_USER_ADDRESS
```

We will use `0xYOUR_TELLOR_USER_ADDRESS` when running the relayer below.

**Custom User Contracts**

The relayer will try to submit oracle data to the user contract using a function with the following interface. If you are following this guide, but building your own custom user contract instead of using the YoloUser contract, please make sure your custom contract has a function with this interface:

<pre class="language-solidity"><code class="lang-solidity"><strong>function updateOracleData(
</strong>        OracleAttestationData calldata _attestData,
        Validator[] calldata _currentValidatorSet,
        Signature[] calldata _sigs
) external;
</code></pre>

See the [Verifying Data Authenticity](https://docs.tellor.io/tellor/using-tellor-data/integrating-tellor-data#verifying-data-authenticity) section in the docs for more information on setting up your custom contracts.

### Setup and Run the Relayer

The relayer is used to get oracle data from tellor and submit it to your user contract.

Follow the [setup instructions for the relayer](https://docs.tellor.io/tellor/using-tellor-data/relay-data-to-evm-chains). We recommend you set your `ETH_PRIVATE_KEY` in the relayer .env file, using the same evm address you used to deploy the contracts in the steps above. Only the deployer address can initialize the TellorDataBridge contract, but any address can run the relayer after initialization. You should also set the `WEB3_PROVIDER_URL`.

#### Initialize TellorDataBridge

We need to initialize the TellorDataBridge contract with the current tellor validator set information.

```bash
relayer init --data-bridge-address 0xYOUR_DATA_BRIDGE_ADDRESS
```

Now you should be ready to relay data to your contract.

#### Relay Data

```bash
relayer relay --layer-user-address 0xYOUR_TELLOR_USER_ADDRESS --data-bridge-address 0xYOUR_DATA_BRIDGE_ADDRESS --contract-type YoloTellorUser --sleep-time 3600
```

The relayer should gather tellor oracle data and submit it to your contract. If you see a transaction hash printed in the relayer logs, that's a good sign. Check your evm chain's block explorer to see whether you relayed data successfully.

Given the `sleep-time` argument we entered in that last command, the relayer will continuously submit new oracle data once every hour. You may also see the relayer update the validator set in the TellorDataBridge contract occasionally.


# Pull Oracle

A pull implementation for Tellor users

## Using Tellor Pull on EVM: library, flow, and sample borrow app

Tellor Pull is for builders who need **oracle data inside the same transaction** as the user action—borrow, liquidate, and so on. Instead of relying on a stored on-chain value that someone else pushed earlier, you **pull** the latest attested report and proofs from Tellor, attach them to the call, and your contract **verifies** via Tellor’s DataBridge and **uses** the value in one shot. That gives you fresher, user-driven reads without a separate “update oracle” step, and it maps cleanly to lending, stablecoins, and prediction markets where price or outcome must be atomic with the protocol logic.

This article combines the practical material from two places: the **using-tellor-pull** npm package from the [UsingTellorPull](https://github.com/tellor-io/UsingTellorPull) repository, and the [**SampleTellorUserPull**](https://github.com/tellor-io/SampleTellorUserPull) repo & reference app (React + Solidity borrow on Sepolia). Read it top-down for context, then use the sections as checklists for your own integration.

### Package contents

* **API** — Fetch and encoding helpers, plus explicit pull modes (consensus-first, consensus-only, optimistic-only). Build output lives in `dist/` when you consume the published package.

### End-to-end flow

* Your app uses the library to fetch attestation, validator set, and signatures from Tellor and encode them for the EVM.
* If the DataBridge’s validator set is stale, you use `getValsetUpdatePayloads` to build `updateValidatorSet` transactions (skip relay) before oracle verification will succeed.
* You pass `attestData`, `validators`, and `sigs` into your contract (for example as ABI-encoded calldata).
* Your contract calls `dataBridge.verifyOracleData(...)` and uses the value in the same transaction.

**Assumption:** You deploy on an EVM chain where Tellor’s DataBridge is deployed.

### Install

```bash
npm install usingtellorpull ethers
```

### Quick start (fetch and encode)

Production integrations should bind the pull to the destination DataBridge before submitting calldata. Read `validatorTimestamp()`, `powerThreshold()`, and `lastValidatorSetCheckpoint()`, then use `getVerifiedPullPayload` (or a mode helper with `bridgeState`). `getPullPayload` remains a raw fetch helper for tests and inspection—it does not check destination bridge checkpoint or recovered signature power by itself.

```typescript
import {
  getVerifiedPullPayload,
  encodeBridgeCallArgsFromPayload,
  spotPriceQueryId,
  TELLOR_LAYER_API,
  type BridgeState,
} from "using-tellor-pull";

const queryIdHex = spotPriceQueryId("eth", "usd");
const bridgeState: BridgeState = {
  timestamp: (await dataBridge.validatorTimestamp()).toString(),
  powerThreshold: (await dataBridge.powerThreshold()).toString(),
  checkpoint: await dataBridge.lastValidatorSetCheckpoint(),
};
const payload = await getVerifiedPullPayload(queryIdHex, TELLOR_LAYER_API, bridgeState);
const { attestData, validators, sigs } = encodeBridgeCallArgsFromPayload(payload);
// Pass attestData, validators, sigs to your contract; it calls dataBridge.verifyOracleData(...)
```

#### Explicit pull modes

Use mode helpers when you want the library to enforce acceptance policy *before* you submit calldata (recommended for production UX).

```typescript
import {
  getConsensusFirstPayload,
  getConsensusOnlyPayload,
  getOptimisticOnlyPayload,
  encodeBridgeCallArgsFromPayload,
  spotPriceQueryId,
  TELLOR_LAYER_API,
} from "using-tellor-pull";
import type { BridgeState } from "using-tellor-pull";

const queryId = spotPriceQueryId("eth", "usd");
const bridgeState: BridgeState = {
  timestamp: (await dataBridge.validatorTimestamp()).toString(),
  powerThreshold: (await dataBridge.powerThreshold()).toString(),
  checkpoint: await dataBridge.lastValidatorSetCheckpoint(),
};
const powerThreshold = Number(await dataBridge.powerThreshold());

const result = await getConsensusFirstPayload(queryId, TELLOR_LAYER_API, {
  bridgeState,
  filterOptions: { powerThreshold },
});

if (result.status !== "ok" || !result.payload) {
  console.log(result.status, result.reason, result.message);
  return;
}

const { attestData, validators, sigs } = encodeBridgeCallArgsFromPayload(result.payload);
```

**Mode behavior:**

* `getConsensusFirstPayload` — Matches SampleTellorUserPull semantics (consensus first, controlled optimistic fallback).
* `getConsensusOnlyPayload` — Requires consensus report plus freshness checks.
* `getOptimisticOnlyPayload` — Requires optimistic report plus freshness, dispute delay, and optimistic power gate.

All mode helpers return a structured `PullModeResult` with `status: "ok" | "unsatisfied" | "error"` and `reason` (for example `checkpoint_mismatch` or `insufficient_signature_power` when `bridgeState` is supplied).

#### Validator set skip relay

If the DataBridge’s on-chain validator set is behind Tellor Layer, attestations will fail verification until the bridge is updated. Use `getValsetUpdatePayloads` and submit `updateValidatorSet` in a loop until caught up:

```typescript
import { getValsetUpdatePayloads, TELLOR_LAYER_API } from "using-tellor-pull";
import type { BridgeState } from "using-tellor-pull";

const bridgeState: BridgeState = {
  timestamp: (await dataBridge.validatorTimestamp()).toString(),
  powerThreshold: (await dataBridge.powerThreshold()).toString(),
  checkpoint: await dataBridge.lastValidatorSetCheckpoint(),
};

while (true) {
  const payloads = await getValsetUpdatePayloads(bridgeState, TELLOR_LAYER_API);
  if (payloads.length === 0) break;
  for (const p of payloads) {
    const tx = await dataBridge.updateValidatorSet(
      p.newValsetHash, p.newPowerThreshold, p.newTimestamp,
      p.currentValidators, p.sigs
    );
    await tx.wait();
  }
  bridgeState.timestamp = (await dataBridge.validatorTimestamp()).toString();
  bridgeState.powerThreshold = (await dataBridge.powerThreshold()).toString();
  bridgeState.checkpoint = await dataBridge.lastValidatorSetCheckpoint();
}
```

### Solidity

Your contract verifies attestations via Tellor’s DataBridge. Use the DataBridge interface (structs and `verifyOracleData`) from Tellor’s DataBridge repository. Off-chain production flow: `getVerifiedPullPayload` or a mode helper with `bridgeState` → `encodeBridgeCallArgsFromPayload` → pass `attestData`, `validators`, `sigs`. The sample repo below shows a full consumer contract.

### API (npm package)

| Function                                                               | Description                                                                                                                                                                 |
| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `getReport(queryIdHex, apiBase, options?)`                             | Current aggregate value and timestamp for the query ID.                                                                                                                     |
| `getAttestationBundle(queryIdHex, reportTimestamp, apiBase, options?)` | Validator set and signatures for that report.                                                                                                                               |
| `getPullPayload(queryIdHex, apiBase, options?)`                        | Raw report plus attestation assembly. With `reportTimestampMs`, skips current aggregate and loads that report time from Layer. Does not check destination DataBridge state. |
| `getVerifiedPullPayload(queryIdHex, apiBase, bridgeState, options?)`   | Production helper: raw payload plus destination DataBridge checkpoint and recovered signature power checks.                                                                 |
| `getConsensusFirstPayload(queryIdHex, apiBase, options?)`              | Consensus-first with controlled optimistic fallback (sample-compatible defaults).                                                                                           |
| `getConsensusOnlyPayload(queryIdHex, apiBase, options?)`               | Consensus-only with freshness checks.                                                                                                                                       |
| `getOptimisticOnlyPayload(queryIdHex, apiBase, options?)`              | Optimistic-only with freshness, delay, and power checks.                                                                                                                    |
| `encodeBridgeCallArgs(attestation)`                                    | Returns `{ attestData, validators, sigs }` for the bridge.                                                                                                                  |
| `encodeBridgeCallArgsFromPayload(payload)`                             | Same encoding from a pull payload.                                                                                                                                          |
| `spotPriceQueryId(asset, currency)`                                    | Query ID for SpotPrice (for example `"btc"`, `"usd"`).                                                                                                                      |
| `spotPriceQueryIdBytes32(asset, currency)`                             | Same as bytes32 (0x-prefixed) for Solidity.                                                                                                                                 |
| `generateWithdrawalQueryId(withdrawalId)`                              | TRBBridge withdrawal (Layer → Ethereum).                                                                                                                                    |
| `generateDepositQueryId(depositId)`                                    | TRBBridge deposit (Ethereum → Layer).                                                                                                                                       |
| `queryIdFromData(queryData)`                                           | Generic: `keccak256(queryData)`.                                                                                                                                            |
| `getValsetUpdatePayloads(bridgeState, apiBase, options?)`              | Skip relay: build `updateValidatorSet` payloads to bring the DataBridge current.                                                                                            |

Types include `BridgeState`, `ValsetUpdatePayload`, `PullPayload`, `PullModeResult`, `PullModeOptions`, `VerifiedPullPayloadOptions`, `AttestationBundle`, `BridgeCallArgsEncodable`, and others.

Constants include `TELLOR_LAYER_API` (for example `https://mainnet.tellorlayer.com`), `LAYER_MAINNET_API`, and `LAYER_TESTNET_API`.

#### Fetch options and `reportTimestampMs`

Optional last parameter for `getReport`, `getPullPayload`, `getAttestationBundle`: `{ timeoutMs?: number, maxRetries?: number, reportTimestampMs?: number }`. Defaults are typically a 30s timeout and retries on 5xx or network errors.

When `reportTimestampMs` is set on `getPullPayload` (or in `PullModeOptions` for mode helpers), the client does **not** call the current aggregate endpoint; it loads the attestation bundle for that report time. Use this with a real `apiBase` after you discover a report timestamp (for example via `npm run discover-report`) so optimistic-only rules can run against Layer-backed signatures.

#### Mode helper options (`PullModeOptions`)

Fetch options (including optional `reportTimestampMs`), optional `bridgeState`, plus `filterOptions`:

* `nowSec` (optional test override)
* `maxDataAgeSec` (default 24h)
* `maxAttestationAgeSec` (default 10m)
* `optimisticDelaySec` (default 12h)
* `powerThreshold` (required for optimistic checks)
* `requiredSignaturePower` (optional; defaults to `bridgeState.powerThreshold` when `bridgeState` is supplied)

When `bridgeState` is supplied, mode helpers reject `status: "ok"` if the attestation checkpoint does not match the destination DataBridge checkpoint or recovered signature power is below the configured threshold.

#### Optimistic-only example

```typescript
import {
  getOptimisticOnlyPayload,
  encodeBridgeCallArgsFromPayload,
  spotPriceQueryId,
  TELLOR_LAYER_API,
} from "using-tellor-pull";
import type { BridgeState } from "using-tellor-pull";

const queryId = spotPriceQueryId("eth", "usd");
const reportTimestampMs = 1730000000000;
const bridgeState: BridgeState = {
  timestamp: (await dataBridge.validatorTimestamp()).toString(),
  powerThreshold: (await dataBridge.powerThreshold()).toString(),
  checkpoint: await dataBridge.lastValidatorSetCheckpoint(),
};
const powerThreshold = Number(await dataBridge.powerThreshold());

const result = await getOptimisticOnlyPayload(queryId, TELLOR_LAYER_API, {
  bridgeState,
  reportTimestampMs,
  filterOptions: { powerThreshold },
});

if (result.status !== "ok" || !result.payload) {
  console.log(result.status, result.reason, result.message);
  return;
}

const { attestData, validators, sigs } = encodeBridgeCallArgsFromPayload(result.payload);
```

**Optional Sepolia fork:** Point Anvil or Hardhat at Sepolia, use Layer API with `discover-report` / `getOptimisticOnlyPayload` and `reportTimestampMs`, then submit encoded args to your contract. Environment-specific; not part of default CI.

***

### Sample application: Borrow TRB (Tellor Pull)

The [SampleTellorUserPull](https://github.com/tellor-io/SampleTellorUserPull) repo demonstrates one use case: **borrow TRB** against **Sepolia ETH** collateral, then **repay TRB** to reclaim collateral. The frontend pulls **ETH/USD** and **TRB/USD** using `getConsensusFirstPayload(...)`, updates the DataBridge validator set when needed (skip relay, multiple hops capped in the UI), and passes attestations into `borrow`. The contract verifies through Tellor’s DataBridge and applies an **80% LTV**.

#### How it looks

* Connect wallet (Sepolia).
* Enter collateral (ETH) and borrow amount (TRB).
* **Borrow** — Check bridge validator set → pull oracle data → encode for EVM → `borrow(amount, ethAttest, trbAttest, validators, ethSigs, trbSigs)`.
* **Repay** — Approve TRB spend → `repay(amount)` → collateral returned proportionally (partial or full repay).

#### Sample flow: Borrow

1. User clicks Borrow in the frontend.
2. Frontend reads the DataBridge’s `validatorTimestamp()`, `powerThreshold()`, and `lastValidatorSetCheckpoint()`, then loops (up to 10 hops): fetch skip-relay payloads via `getValsetUpdatePayloads` and submit `dataBridge.updateValidatorSet(...)` until caught up.
3. After sync, frontend builds `bridgeState` from the bridge and requests ETH/USD and TRB/USD via `getConsensusFirstPayload(queryId, TELLOR_LAYER_API, { bridgeState, filterOptions: { powerThreshold } })`, then `encodeBridgeCallArgsFromPayload(payload)` for each feed (with retries if signatures cannot be recovered).
4. Frontend sends: `contract.borrow(amountTrbWei, ethAttestData, trbAttestData, validators, ethSigs, trbSigs, { value: collateralWei })`.
5. Contract verifies both attestations via `dataBridge.verifyOracleData(...)`, decodes prices, checks LTV, updates position, and transfers TRB.

#### Sample flow: Repay

1. User enters repay amount and confirms Repay.
2. Frontend approves the borrow contract to spend TRB if allowance is insufficient.
3. Frontend sends `contract.repay(amountTrbWei)`.
4. Contract returns ETH collateral proportionally.

#### Validator set skip relay in the sample

The frontend is responsible for keeping the DataBridge validator set current. If the bridge lags multiple rotations, skip relay:

1. Read the bridge’s trusted state (timestamp, power threshold, checkpoint).
2. Try to jump directly to the latest validator set.
3. If not enough signing power from the bridge’s current trusted set, walk backward to the furthest reachable target.
4. Repeat until caught up (the sample caps hops, for example 10).

The sample imports pull and relay helpers through `frontend/src/tellorPull.js`, which re-exports `using-tellor-pull` and sets `TELLOR_LAYER_API` (Vite dev proxy vs production URL). Implementation lives in [UsingTellorPull](https://github.com/tellor-io/UsingTellorPull) (`src/valsetRelay.ts`, `src/attestation.ts`).

#### Sample repo layout

```
SampleTellorUserPull/
├── README.md
├── docs/
│   └── borrow-ui.png
├── hardhat/
│   ├── contracts/
│   │   ├── BorrowWithTellorPull.sol
│   │   ├── interfaces/ITellorDataBridge.sol
│   │   └── testing/
│   ├── scripts/deploy.js
│   ├── test/BorrowWithTellorPull.test.js
│   ├── hardhat.config.js
│   ├── .env
│   └── package.json
└── frontend/
    ├── src/
    │   ├── App.jsx
    │   ├── tellorPull.js
    │   ├── contracts/
    │   └── index.css
    ├── vite.config.js
    ├── .env
    └── package.json
```

### Run the sample

#### 1. Contracts (Sepolia or local)

```bash
cd hardhat
npm install
npx hardhat test
```

Deploy to Sepolia (set `hardhat/.env`: `SEPOLIA_PRIVATE_KEY`, `SEPOLIA_RPC_URL`, `ETHERSCAN_API_KEY`, optional `TRB_ADDRESS`):

```bash
npx hardhat run scripts/deploy.js --network sepolia
```

The script deploys, waits for confirmations, and can auto-verify on Etherscan. Fund the borrow contract with TRB after deploy so it can lend (approve + `fundTrb` from the deployer wallet).

#### 2. Frontend

```bash
cd frontend
npm install
```

Set `frontend/.env`:

```
VITE_BORROW_CONTRACT_ADDRESS=<deployed borrow contract>
VITE_TRB_ADDRESS=<TRB token address>
VITE_TELLOR_LAYER_API=<tellor layer REST API base URL>
VITE_SEPOLIA_RPC_URL=https://1rpc.io/sepolia
```

```bash
npm run dev
```

Open the dev URL, connect on Sepolia, and exercise borrow and repay. Local dev often uses a Vite proxy so browser calls avoid CORS; production builds use `VITE_TELLOR_LAYER_API` directly.

### Testing the library (developers)

```bash
npm install
npm test
npm run test:smoke
npm run live:modes
npm run discover-report -- <queryIdHex> <reportTimestampMs>
```

Hardhat tests in the sample include optimistic-shaped oracle data so on-chain filter rules are covered without Live Layer or a fork in the default test run.

### Secure integrations

For production security guidance, use the [Tellor documentation](https://docs.tellor.io) and review how your protocol uses decoded values (liquidations, LTV, resolution rules). The DataBridge’s `VALIDATOR_SET_HASH_DOMAIN_SEPARATOR` is chain-specific (`keccak256(abi.encode("checkpoint", CHAIN_ID))`). Skip relay behavior is implemented in `using-tellor-pull` (`src/valsetRelay.ts` in [UsingTellorPull](https://github.com/tellor-io/UsingTellorPull)); relay builders validate the bridge’s on-chain checkpoint and power threshold against Tellor Layer before proposing hops.

### Repositories and links

* **Library:** [tellor-io/UsingTellorPull](https://github.com/tellor-io/UsingTellorPull) (npm **using-tellor-pull**)
* **Sample:** [tellor-io/SampleTellorUserPull](https://github.com/tellor-io/SampleTellorUserPull)

*Maintainers and community: see the GitHub repos for issues; Tellor* [*Discord*](https://discord.gg/teAMSZAfJZ) *for contributions. Tellor Inc.*


# Setting up a Grafana Dashboard for your Layer Node

The goal of this guide is to help other node operators set up a grafana dashboard that monitors things in Layer such as average gas price for submitting a report, block times, total bonded tokens, and

1. Navigate to your node’s home config folder and use your text editor of choice to edit config.toml
   1. Adjust the "Instrumentation Configuration Options" by setting `prometheus = true`. If port 26660 is unavailable, modify the `prometheus_listen_addr` field as
2. Open up app.toml and find the “**Telemetry Configuration**” section
   1. Set enabled to true, Set the prometheus\_retention\_time field to 60, and define a global label for the chain id.
3. Restart your node so that these changes can be applied
4. Install and set up a Prometheus server on the same machine or a different one
   1. I used these [docs](https://prometheus.io/docs/prometheus/latest/installation/?utm_source=chatgpt.com) to set mine up, but there is tons of documentation for setting up a prometheus server.
5. Configure prometheus.yml to scrape your node for metrics
   1. Set Global Labels at the top of the file with the following `values: scrape_interval: 5s`, `evaluation_interval: 10s`, and `scrape_timeout: 4s`
   2. When setting up the scrape\_config section set the scrape\_interval to 5s, set your node IP address pointing to the port you set in step 1, and then add a params section where you will need to add `format: [‘prometheus’]` in order for grafana to be able to use the data.
6. Start your prometheus server
7. We are now ready to start setting up the grafana dashboard so you will need to either use grafana cloud or you can do what I did and host it yourself (here are some good docs for hosting your own [grafana server](https://grafana.com/docs/grafana/latest/setup-grafana/installation/debian/))
8. Once you have your grafana server set up navigate to its front end and add your prometheus server as a data source.
   1. Click “**Add new connection**” in the “**Connections**” section of the side bar
   2. Use the search bar to find the “**prometheus**” data source
   3. Set the prometheus server URL to your prometheus server (Ex: [http://{IP\_ADDRESS}:9090](about:blank))
   4. Adjust the internal behavior section to set the `scrape_interval` field to 15s and the `query_timeout` field to 60s
   5. Click “**Save and test**” at the bottom to verify it is working and save it for you to be able to use in your dashboard.
9. Go to the Dashboards page and click the new button and then select to import a dashboard and then use this [json file](https://github.com/tellor-io/layer/blob/main/layer_grafana_dashboard.json).
10. After the dashboard loads you will notice a lot of errors and that is expected. You will need to set up the panels to use the datasource that you just created.
    1. To set the data source of a panel click on the 3 vertical dots in the upper right hand corner of the panel and then select edit. Once you do that just select your data source from the drop down and click “**Run queries**” to verify that it works and then save the dashboard.
    2. You will most likely need to do this for each panel or once you figure out one you may be able to edit the dashboard json directly to add the right data source uid to each panel.
11. Once you have the data sources set up for everything you are good to go and are free to change anything and use any tool that grafana offers. And if you set up anything cool on your dashboard and want to share feel free to come to our discord to share it with other validators.


