Frax Finance ¤
English 🇰🇾
English 🇰🇾
  • Frax Ecosystem Overview
  • FXS & veFXS
    • Frax Shares (FXS)
    • veFXS
    • Gauges
    • FXS Distribution
    • FXS Smart Contract & Addresses
  • GOVERNANCE
    • Frax Governance Overview
    • How It Works
    • Advanced Concepts
    • Fraxtal Snapshot Voting
  • FRAX V1 - ORIGINAL
    • Original Design
    • Staking Contracts
    • FRAX ABI & Token Addresses
    • Frax V1 Pool ABI & Addresses
    • Core Frax Multisigs
  • FRAX V2 - Algorithmic Market Operations (AMO)
    • AMO Overview
    • AMO Minter
    • Collateral Investor
    • Curve
    • Uniswap v3
    • FRAX Lending
    • Decentralization Ratio (DR)
  • FRAX V3 - 100% CR AND MORE
    • Overview
    • Fraxtal
    • AMOs
    • RWAs
    • sFRAX
    • FXBs
    • sFRAX Token Addresses
    • sFRAX & FXB Multisigs
  • Bridging
    • Fraxferry
    • LayerZero x Stargate
    • Fraxtal Bridge
  • Frax Price Index
    • Overview (CPI Peg & Mechanics)
    • Frax Price Index Share (FPIS)
    • FPIS Distribution
    • CPI Tracker Oracle
    • FPI Controller Pool
    • veFPIS
    • FPIS Conversion / FPIS Locker
    • FPI and FPIS Token Addresses
    • FPI Multisigs
  • Fraxswap
    • Overview
    • Technical Specifications
    • Fraxswap Contract Addresses
  • Fraxlend
    • Fraxlend Overview
    • Key Concepts
    • Lending
    • Borrowing
    • Advanced Concepts
      • Position Health & Liquidations
      • Interest Rates
      • Vault Account
    • ABI & Code
    • Fraxlend Multisigs
  • Frax Ether
    • Overview
    • frxETH and sfrxETH
    • Technical Specifications
    • Redemption
    • frxETH V2
    • frxETH V2 Technical Details
    • frxETH Code & V2 Addresses
    • frxETH and sfrxETH Token Addresses
    • frxETH Multisigs
  • BAMM
    • Overview
  • Frax Oracle
    • Frax Oracle Overview
    • How It Works
    • Advanced Concepts
    • Fraxtal Merkle Proof Oracles
  • Guides & FAQ
    • FAQ
    • Staking
    • Uniswap Migration / Uniswap V3
    • Fraxswap / FPI
  • Miscellany
    • All Contract Addresses
    • Bug Bounty
    • Miscellaneous & Bot Addresses
    • API
  • Other
    • Audits
    • Media Kit / Logos
Powered by GitBook
On this page

Was this helpful?

Export as PDF
  1. Frax Oracle

Fraxtal Merkle Proof Oracles

PreviousAdvanced ConceptsNextFAQ

Last updated 8 months ago

Was this helpful?

Fraxtal Merkle Oracles (Fraxtal-MOs) are a class of oracles that utilize the rpc method to proof L1 State on Ethereum L2s such as Fraxtal.

Overview

Fraxtal-MOs utilize 4 Key contracts in order to verify and transport state.

Predeploy contract which serves as a registry of L1 block hashes on the L2.

Contract which verifies a given blockheader against the L1 Blockhash relayed via the FraxchainL1Block contract. This contract is responsible for storing the stateroot hash as well as the L1 timestamp.

Contract which performs the state root verification. Given a merkle proof, constructed off chain via the eth_getProof rpc method. This contract will verify the and extract the storage slot values "proofed" onto the L2 blockchain. These "proofed" values are then relayed to the oracle itself.

The process of relaying these "proofed" values is trustless in the sense that anyone may submit a valid merkle proof corresponding to the pre-approved slots for a given Ethereum L1 address.

Contract which accepts "proofed" L1 data from the MerkleProofPriceSoure contract.

In the case of sFrax and other ERC4626 vaults. These "proofed" values define the current slope of the value accrual function of the vault token on the L1.

These oracles expose the following funtions in order to allow the user to query the price of the asset in question:

    /// @dev Adheres to chainlink's AggregatorV3Interface `latestRoundData()`
    /// @return _roundId The l1Block corresponding to the last time the oracle was proofed
    /// @return _answer The price of Sfrax in frax
    /// @return _startedAt The L1 timestamp corresponding to most recent proof
    /// @return _updatedAt Equivalent to `_startedAt`
    /// @return _answeredInRound Equivalent to `_roundId`
    function latestRoundData()
        external
        view
    returns (
        uint80 _roundId, 
        int256 _answer, 
        uint256 _startedAt, 
        uint256 _updatedAt, 
        uint80 _answeredInRound
    )
/// @return _pricePerShare The current exchange rate of the vault token 
///                        denominated in the underlying vault asset
function pricePerShare() public view returns (uint256 _pricePerShare);

Architecture

The Process of transporting/proving the L1 data onto the L2:

Step 1: Prove the L1 blockHeader on the L2

Step 2: Submit the Storage proof for a predefined L1 address and Slots

Demo Client

The following code should serve as an example of how to generate the function arguments that are accepted by the fraxtal smart contracts detailed above.

To generate the L1 Block Header

async function getHeaderFromBlock(provider, blockL1) {
    let block = await provider.send("eth_getBlockByNumber", [blockL1, false])
    let headerFields = [];
    headerFields.push(block.parentHash);
    headerFields.push(block.sha3Uncles);
    headerFields.push(block.miner);
    headerFields.push(block.stateRoot);
    headerFields.push(block.transactionsRoot);
    headerFields.push(block.receiptsRoot);
    headerFields.push(block.logsBloom);
    headerFields.push(block.difficulty);
    headerFields.push(block.number);
    headerFields.push(block.gasLimit);
    headerFields.push(block.gasUsed);
    headerFields.push(block.timestamp);
    headerFields.push(block.extraData);
    headerFields.push(block.mixHash);
    headerFields.push(block.nonce);
    headerFields.push(block.baseFeePerGas);
    if (block.withdrawalsRoot) {
        headerFields.push(block.withdrawalsRoot);
    }
    if (block.blobGasUsed) {
        headerFields.push(block.blobGasUsed);
    }
    if (block.excessBlobGas) {
        headerFields.push(block.excessBlobGas);
    }
    if (block.parentBeaconBlockRoot) {
        headerFields.push(block.parentBeaconBlockRoot);
    }
    convertHeaderFields(headerFields);
    let header = ethers.utils.RLP.encode(headerFields);
    return header
}

To generate a storage proof

        let blockToProof = "0x"+blockL1.toHexString().substring(2).replace(/^0+/, "");

        let sfrax_proof = await mainnetProvider.send("eth_getProof", 
        [
            // L1 address to generate proofs for
            SFRAX_MAINNET,
            // Slots to proof 
            [
                "0x0000000000000000000000000000000000000000000000000000000000000002",
                "0x0000000000000000000000000000000000000000000000000000000000000009",
                "0x0000000000000000000000000000000000000000000000000000000000000008",
                "0x0000000000000000000000000000000000000000000000000000000000000006",
                "0x0000000000000000000000000000000000000000000000000000000000000007"
            ], 
            blockToProof
        ]);
    
        // Format the proof info returned from `eth_getProof`
        let proof: Proof = {} as Proof;
        proof._accountProofSfrax = sfrax_proof.accountProof;
        proof._storageProofTotalSupply = sfrax_proof.storageProof[0].proof;
        proof._storageProofTotalAssets = sfrax_proof.storageProof[1].proof;
        proof._storageProofLastDist = sfrax_proof.storageProof[2].proof;
        proof._storageProofRewardsPacked = sfrax_proof.storageProof[3].proof;
        proof._storageProofRewardsCycleAmount = sfrax_proof.storageProof[4].proof;

        let txn = await proover.addRoundDataSfrax(
            SFRAX_L2_ORACLE,
            blockL1.toString(),
            proof
        )

Deployed Contracts

Description
Oracle
MerkleProofPriceSource

sFrax/Frax

sfrxEth/frxEth

FPI/USD

Screenshot 2024-09-23 at 11.04.48 AM
Screenshot 2024-09-23 at 11.05.00 AM

Documentation surrounding the RPC methods: &&

eth_getProof
FraxchainL1Block
StateRootOracle
MerkleProofPriceSource
FraxtalERC4626TransportOracle
eth_getBlockByNumber
eth_getProof
0x1b680f4385f24420d264d78cab7c58365ed3f1ff
0xe25d8aaa6df41b94a415ee39ccee0df6673b9bdb
0xEE095b7d9191603126Da584a1179BB403a027c3A
0xabca0b314d15B3e28F24AC0ee84A63001d1b44Db
0x0f50beeE2d2506634b1e6230F3867e30763CbB02
0x8fc7425Cd36D7e4605650198099e4539238e9c37