Settle by stablecoin depeg

The following is an example of a settlement contract which determines the outcome of an Ante based on historic price of USDC which is fetched from a Chainlink price feed.

In order for B side to win the commitment, someone needs to provide a Chainlink roundId as a proof of a depeg of USDC. This is achieved by calling: the setDepegRoundId function directly on the settlement contract

This contract uses a historic data feed because it might be hard for someone to catch the exact moment when the asset depegs. But with an oracle like Chainlink, if the depeg happens for a long enough period or with a big enough spread, then you can prove that the depeg happened in the past. Make sure that the oracle heartbeat and deviation are suitable for your commitment (https://docs.chain.link/data-feeds/price-feeds/addresses?network=ethereum&page=1&search=USDC%2FUSD)

You can find more about roundId and historic price feeds here: https://docs.chain.link/data-feeds/historical-data

Full contract code

// SPDX-License-Identifier: GPL-3.0-only

pragma solidity 0.8.21;

import {IAnteSettlement} from "../../interfaces/IAnteSettlement.sol";
import {IAnteMetaPool} from "../../interfaces/IAnteMetaPool.sol";

// Chainlink Aggragator interface
// import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
interface AggregatorV3Interface {
    function getRoundData(
        uint80 _roundId
    )
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}

/**
 * Contract used for settling a commitment based on USDC peg to USD.
 * The data is fetched using Chainlink historic feed.
 * https://docs.chain.link/data-feeds/historical-data
 * A Chainlink roundId needs to be submitted before cut-off time in order
 * to determine if there was a depeg. Otherwise, the A side will be considered
 * the winner.
 */
contract AnteSettlementByUSDCDepeg is IAnteSettlement {
    /// @notice Date after you can no longer submit an roundId
    uint256 public constant END_DATE = 1704060000; // 01/01/2024 00:00:00
    /// @notice Price of USDC in USD with 8 decimals.
    ///         If the value is below this price, B side becomes the winner
    int public constant PRICE_THRESHOLD = 90000000; // 0.9 USD
    /**
     * @notice The Chainlink historical price feed address 
     * Network: Ethereum Mainnet
     * Aggregator: USDC/USD
     * Address:	0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6
     */
    address public constant FEED_ADDR = 0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6;

    uint80 public depegRoundId;

    error Expired();
    error InvalidProof();

    event RoundIdSet(uint80 roundId);

    function setDepegRoundId(uint80 _roundId) external {
        AggregatorV3Interface dataFeed = AggregatorV3Interface(FEED_ADDR);

        // prettier-ignore
        (
            /* uint80 roundID */,
            int price,
            /*uint startedAt*/,
            uint updatedAt,
            /*uint80 answeredInRound*/
        ) = dataFeed.getRoundData(_roundId);

        if (updatedAt > END_DATE) {
            revert Expired();
        }

        if (price >= PRICE_THRESHOLD) {
            revert InvalidProof();
        }

        depegRoundId = _roundId;

        emit RoundIdSet(_roundId);
    }

    function settle(bytes memory /*data*/) external view returns (WinningSide) {
        if (depegRoundId > 0) {
            return WinningSide.B;
        } else {
            return WinningSide.A;
        }
    }
}

Last updated