Midpoint Cross Testnet

chainId 139420 · tMIDX · temporary explorer

Address

Address
0xce11fbd4a8f246920630d589a421269a5f6073af
Type
contract
Balance
0 tMIDX (0 wei)
Nonce
1
Code size
2,473 bytes

Contract

Creator
0x59de9c0c9e9ff2e83d21a44ebd4fa83eb9ac1394
Creation tx
0xa911d0018368732083ec52e43ca2… (block 9,775)

Source code ✓ verified

Contract
FxSettlement
Compiler
solc 0.8.36+commit.8a079791
Optimizer
enabled, 200 runs
Verified
2026-09-22 19:33:34 UTC
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IERC20 {
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

/// @title FxSettlement
/// @notice Settles an FX fill from the MIDX maker as TWO real ERC-20 transfers -- the base leg and the
///         quote leg -- between the maker wallet and a taker wallet, atomically in one transaction, and
///         emits a paired `Settled` event. This is what makes the mock stablecoins behave as a PAIR: a
///         USD/MXN buy moves USDC one way and MXNB the other, and both token contracts log a Transfer.
///
///         Both wallets pre-approve this contract once (allowance), so at runtime only the owner (the
///         maker's signer key) submits `settle`; the contract pulls each leg with `transferFrom`. If either
///         leg fails the whole settlement reverts -- there are no half-settled trades. It custodies nothing.
///
///         Conventions match FxTradeRecorder: `side` is the TAKER side (1 = taker buys base, 2 = taker
///         sells base); `priceE8` is the rate scaled by 1e8; amounts are in each token's own base units.
///         Testnet only.
contract FxSettlement {
    address public owner;
    address public maker;
    uint256 public settleCount;

    struct Fill {
        bytes32 clOrdId;
        string symbol;        // e.g. "USD/MXN"
        uint8 side;           // taker side: 1 = buy base, 2 = sell base
        address baseToken;
        uint256 baseAmount;   // base token units
        address quoteToken;
        uint256 quoteAmount;  // quote token units
        uint256 priceE8;
        address taker;
    }

    // Kept to 10 values: one more and solc 0.8.x hits "stack too deep" without viaIR, which the explorer's
    // verifier does not use. execId / FIX time are omitted: clOrdId identifies the order and the block
    // timestamp is on the transaction.
    event Settled(
        uint256 indexed seq,
        bytes32 indexed clOrdId,
        string symbol,
        uint8 side,
        address baseToken,
        uint256 baseAmount,
        address quoteToken,
        uint256 quoteAmount,
        uint256 priceE8,
        address taker
    );

    event MakerChanged(address indexed previousMaker, address indexed newMaker);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }

    constructor(address _owner, address _maker) {
        require(_owner != address(0) && _maker != address(0), "zero address");
        owner = _owner;
        maker = _maker;
        emit OwnershipTransferred(address(0), _owner);
        emit MakerChanged(address(0), _maker);
    }

    /// @notice Settle one fill: move the base leg and the quote leg in opposite directions.
    function settle(Fill calldata f) external onlyOwner {
        require(f.side == 1 || f.side == 2, "bad side");
        require(f.taker != address(0), "zero taker");
        if (f.side == 1) {
            // Taker buys base: maker delivers base, taker pays quote.
            require(IERC20(f.baseToken).transferFrom(maker, f.taker, f.baseAmount), "base leg");
            require(IERC20(f.quoteToken).transferFrom(f.taker, maker, f.quoteAmount), "quote leg");
        } else {
            // Taker sells base: taker delivers base, maker pays quote.
            require(IERC20(f.baseToken).transferFrom(f.taker, maker, f.baseAmount), "base leg");
            require(IERC20(f.quoteToken).transferFrom(maker, f.taker, f.quoteAmount), "quote leg");
        }
        emit Settled(++settleCount, f.clOrdId, f.symbol, f.side, f.baseToken, f.baseAmount,
                     f.quoteToken, f.quoteAmount, f.priceE8, f.taker);
    }

    function setMaker(address newMaker) external onlyOwner {
        require(newMaker != address(0), "zero maker");
        emit MakerChanged(maker, newMaker);
        maker = newMaker;
    }

    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "zero owner");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

ABI

[
 {
  "type": "constructor",
  "inputs": [
   {
    "name": "_owner",
    "type": "address",
    "internalType": "address"
   },
   {
    "name": "_maker",
    "type": "address",
    "internalType": "address"
   }
  ],
  "stateMutability": "nonpayable"
 },
 {
  "name": "MakerChanged",
  "type": "event",
  "inputs": [
   {
    "name": "previousMaker",
    "type": "address",
    "indexed": true,
    "internalType": "address"
   },
   {
    "name": "newMaker",
    "type": "address",
    "indexed": true,
    "internalType": "address"
   }
  ],
  "anonymous": false
 },
 {
  "name": "OwnershipTransferred",
  "type": "event",
  "inputs": [
   {
    "name": "previousOwner",
    "type": "address",
    "indexed": true,
    "internalType": "address"
   },
   {
    "name": "newOwner",
    "type": "address",
    "indexed": true,
    "internalType": "address"
   }
  ],
  "anonymous": false
 },
 {
  "name": "Settled",
  "type": "event",
  "inputs": [
   {
    "name": "seq",
    "type": "uint256",
    "indexed": true,
    "internalType": "uint256"
   },
   {
    "name": "clOrdId",
    "type": "bytes32",
    "indexed": true,
    "internalType": "bytes32"
   },
   {
    "name": "symbol",
    "type": "string",
    "indexed": false,
    "internalType": "string"
   },
   {
    "name": "side",
    "type": "uint8",
    "indexed": false,
    "internalType": "uint8"
   },
   {
    "name": "baseToken",
    "type": "address",
    "indexed": false,
    "internalType": "address"
   },
   {
    "name": "baseAmount",
    "type": "uint256",
    "indexed": false,
    "internalType": "uint256"
   },
   {
    "name": "quoteToken",
    "type": "address",
    "indexed": false,
    "internalType": "address"
   },
   {
    "name": "quoteAmount",
    "type": "uint256",
    "indexed": false,
    "internalType": "uint256"
   },
   {
    "name": "priceE8",
    "type": "uint256",
    "indexed": false,
    "internalType": "uint256"
   },
   {
    "name": "taker",
    "type": "address",
    "indexed": false,
    "internalType": "address"
   }
  ],
  "anonymous": false
 },
 {
  "name": "maker",
  "type": "function",
  "inputs": [],
  "outputs": [
   {
    "name": "",
    "type": "address",
    "internalType": "address"
   }
  ],
  "stateMutability": "view"
 },
 {
  "name": "owner",
  "type": "function",
  "inputs": [],
  "outputs": [
   {
    "name": "",
    "type": "address",
    "internalType": "address"
   }
  ],
  "stateMutability": "view"
 },
 {
  "name": "setMaker",
  "type": "function",
  "inputs": [
   {
    "name": "newMaker",
    "type": "address",
    "internalType": "address"
   }
  ],
  "outputs": [],
  "stateMutability": "nonpayable"
 },
 {
  "name": "settle",
  "type": "function",
  "inputs": [
   {
    "name": "f",
    "type": "tuple",
    "components": [
     {
      "name": "clOrdId",
      "type": "bytes32",
      "internalType": "bytes32"
     },
     {
      "name": "symbol",
      "type": "string",
      "internalType": "string"
     },
     {
      "name": "side",
      "type": "uint8",
      "internalType": "uint8"
     },
     {
      "name": "baseToken",
      "type": "address",
      "internalType": "address"
     },
     {
      "name": "baseAmount",
      "type": "uint256",
      "internalType": "uint256"
     },
     {
      "name": "quoteToken",
      "type": "address",
      "internalType": "address"
     },
     {
      "name": "quoteAmount",
      "type": "uint256",
      "internalType": "uint256"
     },
     {
      "name": "priceE8",
      "type": "uint256",
      "internalType": "uint256"
     },
     {
      "name": "taker",
      "type": "address",
      "internalType": "address"
     }
    ],
    "internalType": "struct FxSettlement.Fill"
   }
  ],
  "outputs": [],
  "stateMutability": "nonpayable"
 },
 {
  "name": "settleCount",
  "type": "function",
  "inputs": [],
  "outputs": [
   {
    "name": "",
    "type": "uint256",
    "internalType": "uint256"
   }
  ],
  "stateMutability": "view"
 },
 {
  "name": "transferOwnership",
  "type": "function",
  "inputs": [
   {
    "name": "newOwner",
    "type": "address",
    "internalType": "address"
   }
  ],
  "outputs": [],
  "stateMutability": "nonpayable"
 }
]

Transactions (5 indexed)

HashBlockAgeFromToValue
0x280991f3493cf447fc…98303h 34m ago0x59de9c0c9e…0xce11fbd4a8…0 tMIDX (0 wei)
0x6dadb26b0298fbeea9…98283h 38m ago0x59de9c0c9e…0xce11fbd4a8…0 tMIDX (0 wei)
0x7e7fb37589a10cc607…98253h 50m ago0x59de9c0c9e…0xce11fbd4a8…0 tMIDX (0 wei)
0x426d947f4789c04841…97904h 6m ago0x59de9c0c9e…0xce11fbd4a8…0 tMIDX (0 wei)
0xbb502f63b01319734a…97894h 6m ago0x59de9c0c9e…0xce11fbd4a8…0 tMIDX (0 wei)
Temporary placeholder infrastructure for chain registration. Not a production network - state may be reset without notice.