JuChain
zh
English
English
  • JuChain Documentation
  • What is JuChain?
  • Basics
    • Network Information
    • Start Using JuChain
    • Technical Architecture
    • Smart Contract
  • Ecosystem
    • On-Chain Ecosystem
    • Testnet Faucet
    • Cross-Chain Bridge
    • Decentralized Exchange
  • Price Oracle
  • Developer Guide
    • Getting Started
    • Tutorials and Examples: Building and Deploying a Simple dApp
    • Tutorials and Examples: Building a Simple DeFi Lending dApp
    • Technical Reference
    • Contract Source Code Verification Guide
      • Verifying Contract Source Code on JuScan Browser via GUI
      • Contract Verification on JuChain using the Hardhat framework
  • Community & Support
    • Community & Support
    • Brand Resources & Guidelines
Powered by GitBook
On this page

Price Oracle

The JuChain Oracle service provides reliable on-chain price data for decentralized applications (dApps). The JU-USDT Price Oracle specifically delivers real-time pricing of the JU token relative to USDT, supporting DeFi applications, trading platforms, and other smart contracts requiring precise price data.

Mainnet Deployment Information

  • Network: JuChain Mainnet

  • Contract Address: 0x49E5c7f25711abe668F404307b27f4bE4836B0e7

  • Deployer Address: 0x7389F1B4717F5152B6Cc107bce4A42a11dC0b76E

  • Owner: 0x5021A15FaAFEFEC1daCB1c8b24FFE3F3E3f7277b

  • Updater Permission Address: 0xa6F32fe2920AcF559699825AFaC493aa4F49Ac1D

  • Deployment Transaction Hash: 0x233654f76766fb0f9fd1377a573bed11c60a44c0cdc8e59340ffda333d191140

Testnet Deployment Information

This document also includes information about the JuChain Testnet environment, where developers can test oracle functionality.

The current public chain Solidity version compilation supports only <= 0.8.8. Support for subsequent versions will be gradually rolled out based on official announcements.


Contract Information

Mainnet Contract Information

  • Network: JuChain Mainnet

  • Contract Address: 0x49E5c7f25711abe668F404307b27f4bE4836B0e7

  • Deployer Address: 0x7389F1B4717F5152B6Cc107bce4A42a11dC0b76E

  • Owner: 0x5021A15FaAFEFEC1daCB1c8b24FFE3F3E3f7277b

  • Updater Permission Address: 0xa6F32fe2920AcF559699825AFaC493aa4F49Ac1D

  • Deployment Transaction Hash: 0x233654f76766fb0f9fd1377a573bed11c60a44c0cdc8e59340ffda333d191140

  • Update Frequency: Every 1 minute

  • Price Source: Aggregated data from JU-USDT trading pairs across multiple centralized and decentralized exchanges

Testnet Contract Information

  • Network: JuChain Testnet

  • Contract Address: 0x70D3Fc0bcf1ffD64111FC0C708DA407d9732Ab95

  • Deployer Address: 0xa01d5Be3fDea4Fd8f1C35Ced0919353036De15d0

  • Updater Permission Address: 0x4878683a8C3007258278824228a92aC4E072F050 (only this address can update prices)

  • Deployment Transaction Hash: 0x7e42454909c3ea9b52af4af84217149a87aa71aa08f129e11a01d5cea0989659

  • Update Frequency: Every 1 minute

  • Price Source: Aggregated data from JU-USDT trading pairs across multiple centralized and decentralized exchanges

Permission Details

  • Deployer (Owner):

    • Mainnet: 0x5021A15FaAFEFEC1daCB1c8b24FFE3F3E3f7277b, responsible for contract management and permission allocation.

    • Testnet: 0xa01d5Be3fDea4Fd8f1C35Ced0919353036De15d0, responsible for contract management and permission allocation.

  • Authorized Updater:

    • Mainnet: 0xa6F32fe2920AcF559699825AFaC493aa4F49Ac1D, the only account authorized to call updatePrice to update prices.

    • Testnet: 0x4878683a8C3007258278824228a92aC4E072F050, the only account authorized to call updatePrice to update prices.

  • Design Change: The new oracle version separates the deployer and price updater roles to enhance security.


Key Methods

getLatestPrice

  • Description: Retrieves the latest price information for the JU-USDT trading pair.

  • Returns:

    • string: Trading pair symbol (e.g., "JU/USDT").

    • uint256: Latest price (must be divided by the precision value).

    • uint256: Last update timestamp (Unix timestamp).

  • Call Example:

    (string memory symbol, uint256 price, uint256 timestamp) = oracle.getLatestPrice();

latestPrice

  • Description: Retrieves the latest price value (without additional information).

  • Returns:

    • uint256: Latest price value.

pricePrecision

  • Description: Retrieves the price precision value used to calculate the actual price.

  • Returns:

    • uint256: Price precision (e.g., 1e8, actual price = returned price / precision).

lastUpdatedAt

  • Description: Retrieves the timestamp of the last price update.

  • Returns:

    • uint256: Unix timestamp.

symbol

  • Description: Retrieves the trading pair symbol.

  • Returns:

    • string: Trading pair symbol (e.g., "JU/USDT").

updatePrice

  • Description: Updates the JU-USDT price, callable only by the authorized updater.

  • Parameters:

    • uint256 _price: New price value.

  • Permission: Only 0x4878683a8C3007258278824228a92aC4E072F050 can call this.

setAuthorizedUpdater

  • Description: Sets a new authorized updater, callable only by the Owner.

  • Parameters:

    • address newAuthorizedUpdater: New authorized updater address.

  • Permission: Only 0xa01d5Be3fDea4Fd8f1C35Ced0919353036De15d0 can call this.

owner

  • Description: Retrieves the current contract owner address.

  • Returns:

    • address: Owner address.


ABI

Below is the complete ABI for the JU-USDT Price Oracle:

[
  {
    "inputs": [
      {"internalType": "address", "name": "initialOwner", "type": "address"},
      {"internalType": "address", "name": "initialAuthorizedUpdater", "type": "address"}
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {"inputs": [{"internalType": "address", "name": "owner", "type": "address"}], "name": "OwnableInvalidOwner", "type": "error"},
  {"inputs": [{"internalType": "address", "name": "account", "type": "address"}], "name": "OwnableUnauthorizedAccount", "type": "error"},
  {
    "anonymous": false,
    "inputs": [
      {"indexed": false, "internalType": "address", "name": "previousUpdater", "type": "address"},
      {"indexed": false, "internalType": "address", "name": "newUpdater", "type": "address"}
    ],
    "name": "AuthorizedUpdaterChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {"indexed": true, "internalType": "address", "name": "previousOwner", "type": "address"},
      {"indexed": true, "internalType": "address", "name": "newOwner", "type": "address"}
    ],
    "name": "OwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {"indexed": false, "internalType": "uint256", "name": "price", "type": "uint256"},
      {"indexed": false, "internalType": "uint256", "name": "timestamp", "type": "uint256"},
      {"indexed": false, "internalType": "address", "name": "updater", "type": "address"}
    ],
    "name": "PriceUpdated",
    "type": "event"
  },
  {"inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
  {"inputs": [{"internalType": "address", "name": "newAuthorizedUpdater", "type": "address"}], "name": "setAuthorizedUpdater", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
  {"inputs": [{"internalType": "address", "name": "newOwner", "type": "address"}], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
  {"inputs": [{"internalType": "uint256", "name": "_price", "type": "uint256"}], "name": "updatePrice", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
  {"inputs": [], "name": "authorizedUpdater", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"},
  {"inputs": [], "name": "getLatestPrice", "outputs": [{"internalType": "string", "name": "", "type": "string"}, {"internalType": "uint256", "name": "", "type": "uint256"}, {"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"},
  {"inputs": [], "name": "lastUpdatedAt", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"},
  {"inputs": [], "name": "latestPrice", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"},
  {"inputs": [], "name": "owner", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"},
  {"inputs LuaTeX error (string "[]"):1: unexpected symbol near ']'.
": [], "name": "pricePrecision", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"},
  {"inputs": [], "name": "symbol", "outputs": [{"internalType": "string", "name": "", "type": "string"}], "stateMutability": "view", "type": "function"}
]

Usage Examples

Web3.js Example

The following code demonstrates how to interact with the oracle using Web3.js:

const { Web3 } = require('web3');

// Mainnet RPC
const mainnetRpc = 'https://rpc.juchain.org';
// Testnet RPC
const testnetRpc = 'https://testnet-rpc.juchain.org';

// Select network (Mainnet/Testnet)
const web3 = new Web3(mainnetRpc); // or testnetRpc

// Mainnet contract address
const mainnetContractAddress = '0x49E5c7f25711abe668F404307b27f4bE4836B0e7';
// Testnet contract address
const testnetContractAddress = '0x70D3Fc0bcf1ffD64111FC0C708DA407d9732Ab95';

// Select contract address
const contractAddress = mainnetContractAddress; // or testnetContractAddress
const contract = new web3.eth.Contract(abi, contractAddress);

// Get complete price information
async function getCompletePrice() {
  try {
    const [symbol, price, timestamp] = await contract.methods.getLatestPrice().call();
    const precision = await contract.methods.pricePrecision().call();
    console.log('Complete Price Information:');
    console.log(`Trading Pair: ${symbol}`);
    console.log(`Price: ${price / precision} JU/USDT`);
    console.log(`Timestamp: ${timestamp} (${new Date(Number(timestamp) * 1000).toLocaleString()})`);
    return { symbol, price, timestamp, precision };
  } catch (error) {
    console.error('Failed to fetch price information:', error);
  }
}

// Get latest price
async function getLatestPrice() {
  try {
    const price = await contract.methods.latestPrice().call();
    const precision = await contract.methods.pricePrecision().call();
    console.log(`Latest Price: ${price / precision} JU/USDT`);
    return price;
  } catch (error) {
    console.error('Failed to fetch latest price:', error);
  }
}

// Get authorized updater
async function getAuthorizedUpdater() {
  try {
    const updater = await contract.methods.authorizedUpdater().call();
    console.log(`Authorized Updater: ${updater}`);
    return updater;
  } catch (error) {
    console.error('Failed to fetch authorized updater:', error);
  }
}

// Update price (only for authorized updater)
async function updatePrice(newPrice, privateKey) {
  try {
    const account = web3.eth.accounts.privateKeyToAccount(privateKey);
    web3.eth.accounts.wallet.add(account);
    const tx = contract.methods.updatePrice(newPrice);
    const gas = await tx.estimateGas({ from: account.address });
    const receipt = await tx.send({ from: account.address, gas });
    console.log(`Price updated successfully, Transaction Hash: ${receipt.transactionHash}`);
    return receipt;
  } catch (error) {
    console.error('Failed to update price:', error);
  }
}

// Execute all queries
async function getAllInfo() {
  await getCompletePrice();
  await getLatestPrice();
  await getAuthorizedUpdater();
}

getAllInfo();

Solidity Example

Below is an example of a smart contract utilizing the oracle:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IJUOracle {
    function getLatestPrice() external view returns (string memory, uint256, uint256);
    function pricePrecision() external view returns (uint256);
}

contract JUPriceConsumer {
    IJUOracle public oracle;

    constructor(address _oracleAddress) {
        oracle = IJUOracle(_oracleAddress);
    }

    function getJUPrice() public view returns (uint256) {
        (, uint256 price, ) = oracle.getLatestPrice();
        uint256 precision = oracle.pricePrecision();
        return price; // Frontend needs to divide by precision
    }

    function getFormattedPrice() public view returns (string memory symbol, uint256 price, uint256 precision, uint256 timestamp) {
        (symbol, price, timestamp) = oracle.getLatestPrice();
        precision = oracle.pricePrecision();
        return (symbol, price, precision, timestamp);
    }
}

Important Notes

  • Network Selection:

    • Mainnet: For production environments, contract address is 0x49E5c7f25711abe668F404307b27f4bE4836B0e7.

    • Testnet: For development and testing, contract address is 0x70D3Fc0bcf1ffD64111FC0C708DA407d9732Ab95.

  • Price Precision: The price returned by the contract must be divided by the value from pricePrecision() (e.g., 1e8 indicates 8 decimal precision).

  • Update Permissions:

    • Mainnet: Only 0xa6F32fe2920AcF559699825AFaC493aa4F49Ac1D can call updatePrice.

    • Testnet: Only 0x4878683a8C3007258278824228a92aC4E072F050 can call updatePrice.

    • The Owner can change the updater via setAuthorizedUpdater.

  • Update Delay: Prices are updated every 1 minute. Check lastUpdatedAt to ensure data freshness before use.

  • Price Volatility: Cryptocurrency prices may fluctuate significantly; consider implementing risk management mechanisms in your dApp.

  • Contract Upgrades: The oracle contract may be updated. Stay tuned to official announcements for the latest addresses and features.

  • Mainnet Considerations:

    • Operations on the mainnet incur real costs; exercise caution.

    • Thoroughly test on the testnet before deploying to the mainnet.

PreviousDecentralized ExchangeNextGetting Started

Last updated 1 month ago