Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sample Tellor User Pull – Borrow TRB

One sample use case for the Tellor Pull flow: borrow TRB against Sepolia ETH collateral, then repay TRB to reclaim collateral. The frontend pulls ETH/USD and TRB/USD from the Tellor Layer API, automatically updates the DataBridge validator set if needed (skip relay), and includes attestations in the borrow transaction. The contract verifies via Tellor's DataBridge and applies an 80% LTV.

How it looks

Borrow UI

  • Connect wallet (Sepolia)
  • Enter collateral (ETH) and borrow amount (TRB)
  • Borrow runs: check bridge validator set → pull oracle data → encode for EVM → borrow(amount, ethAttest, trbAttest, validators, ethSigs, trbSigs)
  • Repay runs: approve TRB spend → repay(amount) → collateral returned proportionally

Flow

Borrow

  1. User clicks Borrow in the frontend.
  2. Frontend reads the DataBridge's validatorTimestamp() and compares with the Tellor Layer API's current validator set timestamp.
  3. If the bridge is behind, the frontend fetches validator set update data and calls dataBridge.updateValidatorSet() — using skip relay logic to jump as far forward as possible in a single update.
  4. Frontend calls Tellor Layer API for both ETH/USD and TRB/USD: getPullPayload(queryId, TELLOR_LAYER_API)encodeBridgeCallArgsFromPayload(payload).
  5. Frontend sends tx: contract.borrow(amountTrbWei, ethAttestData, trbAttestData, validators, ethSigs, trbSigs, { value: collateralWei }).
  6. Contract verifies both attestations via dataBridge.verifyOracleData(...), decodes prices, checks LTV, tracks the position, and transfers TRB to the user.

Repay

  1. User clicks Repay in the frontend.
  2. Frontend approves the borrow contract to spend TRB (if needed).
  3. Frontend sends tx: contract.repay(amountTrbWei).
  4. Contract returns ETH collateral proportionally (partial or full repay supported).

Validator Set Skip Relay

The pull oracle model means the frontend is responsible for keeping the DataBridge's validator set current. If the bridge falls behind by multiple validator rotations, the skip relay logic:

  1. Reads the bridge's current trusted state (timestamp, power threshold, checkpoint)
  2. Tries to jump directly to the latest validator set
  3. If not enough signing power from the bridge's current trusted set, walks backward to find the furthest reachable target
  4. Repeats until fully caught up (up to 10 hops)

See tellorPull.jsgetValsetUpdatePayloads() for the implementation.

Repo layout

SampleTellorUserPull/
├── README.md
├── docs/
│   └── borrow-ui.png
├── hardhat/
│   ├── contracts/
│   │   ├── BorrowWithTellorPull.sol
│   │   ├── interfaces/ITellorDataBridge.sol
│   │   └── testing/              # MockERC20, MockTellorDataBridge
│   ├── scripts/deploy.js
│   ├── test/BorrowWithTellorPull.test.js
│   ├── hardhat.config.js
│   ├── .env                      # SEPOLIA_PRIVATE_KEY, ETHERSCAN_API_KEY, etc.
│   └── package.json
└── frontend/
    ├── src/
    │   ├── App.jsx               # Connect + Borrow + Repay + position display
    │   ├── tellorPull.js         # Oracle pull helpers + skip relay
    │   ├── contracts/
    │   │   ├── borrowAbi.json
    │   │   └── dataBridgeAbi.json
    │   └── index.css
    ├── vite.config.js            # Dev proxy for CORS
    ├── .env                      # VITE_BORROW_CONTRACT_ADDRESS, VITE_TRB_ADDRESS, etc.
    └── package.json

Run

1. Contract (Sepolia or local)

cd hardhat
npm install
npx hardhat test

Deploy to Sepolia:

# Set in hardhat/.env:
#   SEPOLIA_PRIVATE_KEY=<deployer wallet private key>
#   SEPOLIA_RPC_URL=https://1rpc.io/sepolia
#   ETHERSCAN_API_KEY=<your etherscan api key>
#   TRB_ADDRESS=<sepolia TRB address, or leave blank to deploy MockERC20>

npx hardhat run scripts/deploy.js --network sepolia

On Sepolia, deploy uses TellorPlayground (TRBP) at 0x06BA179F22Bb34314ade96E96fa41C7951b2A731 — shows on Etherscan. Local Hardhat still deploys MockERC20.

The script funds the borrow pool with 10,000 TRBP by default (10× faucet calls). Override with FUND_AMOUNT=50000.

# Deploy (Sepolia → TellorPlayground + auto-fund pool)
npx hardhat run scripts/deploy.js --network sepolia

# Re-fund pool
BORROW=<borrow> TRB=0x06BA179F22Bb34314ade96E96fa41C7951b2A731 npx hardhat run scripts/fund.js --network sepolia

# Faucet TRBP to your wallet (1000 per call; for repay)
FAUCET_TO=<wallet> FAUCET_TIMES=2 npx hardhat run scripts/faucet.js --network sepolia

Frontend: “Get 1000 TRBP (TellorPlayground faucet)” after connecting wallet.

2. Frontend

cd frontend
npm install

Set in 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
npm run dev

Open the URL, connect wallet (Sepolia), and test borrow + repay.

References

  • Tellor Layer pull: tellor-io/tellor-layer-pull
  • DataBridge: Deployed per Tellor Layer chain. The bridge's VALIDATOR_SET_HASH_DOMAIN_SEPARATOR is chain-specific (keccak256(abi.encode("checkpoint", CHAIN_ID))).
  • Skip relay pattern: See docs/SKIP_VALSET_RELAYS.md for the full spec on validator set skip relays.
  • Sample structure: sample-tellor-layer-pull

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages