circle-info
This is the first version of our Documentation, it will be improved and extended soon.
Page cover

Complete Example Contract

This page combines everything from the EVM integration guides into a production-ready example: a simple stablecoin-priced vault that accepts deposits, tracks value in USD using IFÁ Labs prices, and includes staleness checks, gas optimizations, and best practices.

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

import "ifapricefeed-interface/IIfaPriceFeed.sol";

contract StablecoinVault {
    IIfaPriceFeed public constant ORACLE = IIfaPriceFeed(0xA9F17344689C2c2328F94464998db1d3e35B80dC); // Base Mainnet

    // Common asset IDs (keccak256("SYMBOL/USD"))
    bytes32 public constant USDT_ASSET_ID = 0x6ca0cef6107263f3b09a51448617b659278cff744f0e702c24a2f88c91e65a0d;
    bytes32 public constant USDC_ASSET_ID = 0xf989296bde68043d307a2bc0e59de3445defc5f292eb390b80d78162c8a6b13d;
    bytes32 public constant CNGN_ASSET_ID = 0x83a18c73cf75a028a24b79cbedb3b8d8ba363b748a3210ddbcaa95eec3b87b3a;

    uint256 public constant MAX_STALENESS = 3600; // 1 hour
    uint256 public constant MAX_DEVIATION_BP = 500; // 5% in basis points

    mapping(address => uint256) public balances; // user => USD value (scaled to 18 decimals)

    event Deposit(address indexed user, bytes32 indexed assetId, uint256 amount, uint256 usdValue);
    event Withdraw(address indexed user, uint256 usdValue);

    /**
     * @dev Deposit an amount of a supported stablecoin and credit USD value
     * @param assetId The IFÁ Labs asset ID
     * @param amount Raw token amount (must approve vault first)
     */
    function deposit(bytes32 assetId, uint256 amount, IERC20 token) external {
        int256 usdValue = _getVerifiedPrice(assetId) * int256(amount);

        require(usdValue > 0, "Invalid price");

        uint256 scaledUsd = uint256(usdValue) / 1e18; // Adjust to 18 decimals if needed

        balances[msg.sender] += scaledUsd;

        token.transferFrom(msg.sender, address(this), amount);

        emit Deposit(msg.sender, assetId, amount, scaledUsd);
    }

    /**
     * @dev Internal: Fetch and verify price with staleness + deviation checks
     */
    function _getVerifiedPrice(bytes32 assetId) internal view returns (int256 price) {
        (IIfaPriceFeed.PriceFeed memory info, bool exists) = ORACLE.getAssetInfo(assetId);

        require(exists, "Asset not supported");
        require(block.timestamp - info.lastUpdateTime <= MAX_STALENESS, "Price stale");

        // Deviation check from $1 peg (common for stablecoins)
        int256 deviation = info.price - 1e18;
        if (deviation < 0) deviation = -deviation;
        require(uint256(deviation) <= 1e18 * MAX_DEVIATION_BP / 10000, "Excessive peg deviation");

        return info.price;
    }

    // Additional functions: withdraw, getUserValueUSD, etc.
    // Implement with similar verification
}

Key Features in This Example

  • Constants for oracle address and asset IDs → gas savings.

  • Verification → existence, staleness, and peg deviation checks.

  • Safe math → careful handling of signed prices and scaling.

  • Extensible → easy to add batch reads or caching.

This pattern is suitable for lending protocols, vaults, stablecoin swaps, or any price-sensitive application.

This concludes the EVM Smart Contracts integration guides.

Next: Dive into Core Concepts to understand the oracle mechanics under the hood.

Last updated

Was this helpful?