CurvePoolRegistry

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "viaIR": true,
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "abi"
        ]
      }
    },
    "remappings": []
  },
  "sources": {
    "contracts/swap/CurvePoolRegistry.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.30;\r
\r
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";\r
\r
/**\r
 *⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r
 *⠀⠀⠀⠀⠈⢻⣿⠛⠻⢷⣄⠀⠀ ⣴⡟⠛⠛⣷⠀ ⠘⣿⡿⠛⠛⢿⡇⠀⠀⠀⠀\r
 *⠀⠀⠀⠀⠀⢸⣿⠀⠀ ⠈⣿⡄⠀⠿⣧⣄⡀ ⠉⠀⠀ ⣿⣧⣀⣀⡀⠀⠀⠀⠀⠀\r
 *⠀⠀⠀⠀⠀⢸⣿⠀⠀ ⢀⣿⠃ ⣀ ⠈⠉⠻⣷⡄⠀ ⣿⡟⠉⠉⠁⠀⠀⠀⠀⠀\r
 *⠀⠀⠀⠀⢠⣼⣿⣤⣴⠿⠋⠀ ⠀⢿⣦⣤⣴⡿⠁ ⢠⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\r
 *\r
 *      - Defining Successful Future -\r
 *\r
 * @title CurvePoolRegistry\r
 * @author Andrei Averin — CTO dsf.finance\r
 * @notice Centralized, owner-controlled registry for whitelisting safe and verified Curve pools.\r
 * @dev\r
 * - Intended to be consumed by aggregator modules (e.g., CurveDexModule).\r
 * - Stores:\r
 *    (1) Per-(tokenA, tokenB) allowlist of pools (strict routing allowlist).\r
 *    (2) Minimal per-pool call profile for `exchange(...)` (non-underlying branch).\r
 * - Pair allowlist is keyed by `keccak256(sorted(tokenA, tokenB))`.\r
 * - Admin (owner) can atomically set/clear allowlists and update per-pool profiles.\r
 * - The profile exposes three booleans:\r
 *      `exIndexUint`             : true => `exchange(uint256,uint256,...)`, false => `exchange(int128,int128,...)`\r
 *      `exHasEthFlag`            : true => non-underlying `exchange(..., bool use_eth)` (5-arg/6-arg forms)\r
 *      `exHasReceiver`           : true => presence of receiver overloads `exchange(..., address)` / `exchange(..., bool, address)`\r
 *      `exHasReceiverUnderlying` : true => underlying receiver overloads exist\r
 * - The registry also provides view-only probe helpers to heuristically detect a profile off-chain.\r
 */\r
 \r
/**\r
 * @title IPoolRegistry\r
 * @notice Interface for accessing whitelisted pools and their call profiles.\r
 */\r
interface IPoolRegistry {\r
    /**\r
     * @notice Minimal call profile for non-underlying `exchange(...)`.\r
     * @dev\r
     * - `exIndexUint`             selects indices type: uint256 vs int128.\r
     * - `exHasEthFlag`            indicates existence of a trailing `bool use_eth` argument in non-underlying exchange.\r
     * - `exHasReceiver`           indicates presence of receiver overloads (`..., address)` or `(..., bool, address)`.\r
     * - `exHasReceiverUnderlying` covers `exchange_underlying(..., address)`/`(..., bool, address)` presence.\r
     */\r
    struct PoolProfile {\r
        // exchange signatures (non-underlying branch)\r
        bool exIndexUint;             // true: exchange(uint256,uint256,...) ; false: exchange(int128,int128,...)\r
        bool exHasEthFlag;            // true: non-underlying exchange has trailing `bool use_eth`\r
        bool exHasReceiver;           // true: non-underlying exchange has overloads with `address receiver`\r
        bool exHasReceiverUnderlying; // underlying: has receiver overloads\r
    }\r
\r
    /**\r
     * @notice Get allowlisted pools for a (tokenA, tokenB) pair.\r
     * @param  tokenA First token.\r
     * @param  tokenB Second token.\r
     * @return Array of allowlisted pool addresses under the canonical pair key.\r
     */\r
    function getVerifiedPools(address tokenA, address tokenB) external view returns (address[] memory);\r
    \r
    /**\r
     * @notice Get a saved profile for a pool.\r
     * @param  pool    Pool address.\r
     * @return exists  True if a profile is set in the registry.\r
     * @return profile The stored PoolProfile ({exIndexUint, exHasEthFlag, exHasReceiver}).\r
     */\r
    function getPoolProfile(address pool) external view returns (bool exists, PoolProfile memory profile);\r
\r
    /**\r
     * @notice Returns stored profile flags for a pool as separate booleans (gas-cheaper in some cases).\r
     * @param  pool                    Pool address.\r
     * @return exists                  True if an explicit profile exists.\r
     * @return exIndexUint             See `PoolProfile.exIndexUint`.\r
     * @return exHasEthFlag            See `PoolProfile.exHasEthFlag`.\r
     * @return exHasReceiver           See `PoolProfile.exHasReceiver`.\r
     * @return exHasReceiverUnderlying See `PoolProfile.exHasReceiverUnderlying`.\r
     */\r
    function getPoolProfileFlags(address pool)\r
        external\r
        view\r
        returns (\r
            bool exists,\r
            bool exIndexUint,\r
            bool exHasEthFlag,\r
            bool exHasReceiver,\r
            bool exHasReceiverUnderlying\r
        );\r
}\r
\r
/**\r
 * @title  CurvePoolRegistry\r
 * @notice Stores and manages the list of officially verified Curve pools for specific token pairs.\r
 * @dev    Owner is the only actor allowed to mutate storage (allowlists and profiles).\r
 */\r
contract CurvePoolRegistry is Ownable, IPoolRegistry {\r
    // events \r
    event VerifiedPoolsSet(bytes32 indexed pairKey, address tokenA, address tokenB, address[] pools);\r
    event VerifiedPoolsCleared(bytes32 indexed pairKey, address tokenA, address tokenB);\r
    event PoolProfileSet(\r
        address indexed pool,\r
        bool exIndexUint,\r
        bool exHasEthFlag,\r
        bool exHasReceiver,\r
        bool exHasReceiverUnderlying\r
    );\r
    event PoolProfileCleared(address indexed pool);\r
    event DefaultProfileSet(PoolProfile profile);\r
\r
    // probe constants\r
    uint256 private constant DX  = 1;\r
    uint256 private constant MIN = 0;\r
\r
    // selectors\r
    // coins(...)\r
    bytes4 private constant COINS_U256        = bytes4(keccak256("coins(uint256)"));\r
    bytes4 private constant COINS_I128        = bytes4(keccak256("coins(int128)"));\r
    // non-underlying exchange base\r
    bytes4 private constant EX_U256_ETH       = bytes4(keccak256("exchange(uint256,uint256,uint256,uint256,bool)"));\r
    bytes4 private constant EX_U256           = bytes4(keccak256("exchange(uint256,uint256,uint256,uint256)"));\r
    bytes4 private constant EX_I128_ETH       = bytes4(keccak256("exchange(int128,int128,uint256,uint256,bool)"));\r
    bytes4 private constant EX_I128           = bytes4(keccak256("exchange(int128,int128,uint256,uint256)"));\r
    // non-underlying exchange with receiver\r
    bytes4 private constant EX_U256_RCV       = bytes4(keccak256("exchange(uint256,uint256,uint256,uint256,address)"));\r
    bytes4 private constant EX_U256_ETH_RCV   = bytes4(keccak256("exchange(uint256,uint256,uint256,uint256,bool,address)"));\r
    bytes4 private constant EX_I128_RCV       = bytes4(keccak256("exchange(int128,int128,uint256,uint256,address)"));\r
\r
\r
    // key: keccak256(sorted(tokenA, tokenB)) => allowlisted pools\r
    mapping(bytes32 => address[]) public verifiedPools;\r
\r
    // per-pool profile\r
    mapping(address => bool) internal exIndexUintOf;     // true => exchange(uint256,...)\r
    mapping(address => bool) internal exHasEthFlagOf;    // true => has trailing `bool use_eth`\r
    mapping(address => bool) internal exHasReceiverOf;   // true => has overloads with `address receiver`\r
    mapping(address => bool) internal exHasReceiverUnderlyingOf;\r
    mapping(address => bool) internal hasProfile;\r
\r
    PoolProfile private _defaultProfile = PoolProfile({\r
        exIndexUint: true,\r
        exHasEthFlag: true,\r
        exHasReceiver: false,\r
        exHasReceiverUnderlying: false\r
    });\r
\r
    constructor() Ownable(msg.sender) {}\r
\r
    /**\r
     * @inheritdoc IPoolRegistry\r
     */\r
    function getVerifiedPools(address tokenA, address tokenB) \r
        external \r
        view \r
        override \r
        returns (address[] memory) \r
    {\r
        return verifiedPools[_pairKey(tokenA, tokenB)];\r
    }\r
\r
    /**\r
     * @inheritdoc IPoolRegistry\r
     */\r
    function getPoolProfile(address pool)\r
        external\r
        view\r
        override\r
        returns (bool exists, PoolProfile memory profile)\r
    {\r
        if (hasProfile[pool]) {\r
            profile = PoolProfile({\r
                exIndexUint:   exIndexUintOf[pool],\r
                exHasEthFlag:  exHasEthFlagOf[pool],\r
                exHasReceiver: exHasReceiverOf[pool],\r
                exHasReceiverUnderlying:   exHasReceiverUnderlyingOf[pool]\r
            });\r
            return (true, profile);\r
        }\r
        return (false, _defaultProfile);\r
    }\r
    \r
    /**\r
     * @inheritdoc IPoolRegistry\r
     */\r
    function getPoolProfileFlags(address pool)\r
        external\r
        view\r
        override\r
        returns (\r
            bool exists,\r
            bool exIndexUint,\r
            bool exHasEthFlag,\r
            bool exHasReceiver,\r
            bool exHasReceiverUnderlying\r
        )\r
    {\r
        if (hasProfile[pool]) {\r
            return (\r
                true,\r
                exIndexUintOf[pool],\r
                exHasEthFlagOf[pool],\r
                exHasReceiverOf[pool],\r
                exHasReceiverUnderlyingOf[pool]\r
            );\r
        }\r
        IPoolRegistry.PoolProfile memory p = _defaultProfile;\r
        return (false, p.exIndexUint, p.exHasEthFlag, p.exHasReceiver, p.exHasReceiverUnderlying);\r
    }\r
\r
    \r
    /**\r
     * @notice Returns the current default profile that is used when a pool has no explicit profile.\r
     * @return profile The default `PoolProfile`.\r
     */\r
    function getDefaultProfile() external view returns (PoolProfile memory) {\r
        return _defaultProfile;\r
    }\r
\r
    /**\r
     * @notice Add/replace the allowlist of pools for a (tokenA, tokenB) pair.\r
     * @dev    Replaces the full list atomically.\r
     * @param  tokenA First token\r
     * @param  tokenB Second token\r
     * @param  pools  New full list of allowlisted pools (non-empty)\r
     */\r
    function setVerifiedPools(address tokenA, address tokenB, address[] calldata pools)\r
        external\r
        onlyOwner\r
    {\r
        require(pools.length > 0, "Registry: empty list");\r
        bytes32 key = _pairKey(tokenA, tokenB);\r
        verifiedPools[key] = pools;\r
        emit VerifiedPoolsSet(key, tokenA, tokenB, pools);\r
    }\r
    \r
    /**\r
     * @notice Clear the allowlist for a (tokenA, tokenB) pair.\r
     * @param  tokenA First token\r
     * @param  tokenB Second token\r
     */\r
    function clearVerifiedPools(address tokenA, address tokenB)\r
        external\r
        onlyOwner\r
    {\r
        bytes32 key = _pairKey(tokenA, tokenB);\r
        delete verifiedPools[key];\r
        emit VerifiedPoolsCleared(key, tokenA, tokenB);\r
    }\r
\r
    /**\r
     * @notice Set/update a pool profile (three flags).\r
     * @param  pool                     Pool address (non-zero)\r
     * @param  exIndexUint              true => `exchange(uint256,...)`; false => `exchange(int128,...)`\r
     * @param  exHasEthFlag             true => non-underlying has trailing `bool use_eth`\r
     * @param  exHasReceiver            true => receiver overloads exist (`..., address)` / `(..., bool, address)`\r
     * @param  exHasReceiverUnderlying  true => underlying receiver overloads exist\r
     */\r
    function setPoolProfile(\r
        address pool,\r
        bool exIndexUint,\r
        bool exHasEthFlag,\r
        bool exHasReceiver,\r
        bool exHasReceiverUnderlying\r
    )\r
        external\r
        onlyOwner\r
    {\r
        require(pool != address(0), "Registry: zero pool");\r
        exIndexUintOf[pool]               = exIndexUint;\r
        exHasEthFlagOf[pool]              = exHasEthFlag;\r
        exHasReceiverOf[pool]             = exHasReceiver;\r
        exHasReceiverUnderlyingOf[pool]   = exHasReceiverUnderlying;\r
        hasProfile[pool]                  = true;\r
        emit PoolProfileSet(pool, exIndexUint, exHasEthFlag, exHasReceiver, exHasReceiverUnderlying);\r
    }\r
\r
    /**\r
     * @notice Batch set/update pool profiles (arrays must be aligned).\r
     * @param  pools                    Pool addresses\r
     * @param  exIndexUint              Flags for indices type per pool\r
     * @param  exHasEthFlag             Flags for `use_eth` presence per pool\r
     * @param  exHasReceiver            Flags for receiver overloads per pool\r
     * @param exHasReceiverUnderlying   Flags for presence of receiver overloads per pool (underlying).\r
     */\r
    function setPoolProfiles(\r
        address[] calldata pools,\r
        bool[]    calldata exIndexUint,\r
        bool[]    calldata exHasEthFlag,\r
        bool[]    calldata exHasReceiver,\r
        bool[]    calldata exHasReceiverUnderlying\r
    )\r
        external\r
        onlyOwner\r
    {\r
        uint256 n = pools.length;\r
        require(n > 0, "Registry: empty arrays");\r
        require(\r
            exIndexUint.length == n &&\r
            exHasEthFlag.length == n &&\r
            exHasReceiver.length == n &&\r
            exHasReceiverUnderlying.length == n,\r
            "Registry: bad arrays"\r
        );\r
\r
        for (uint256 i; i < n; ++i) {\r
            address pool = pools[i];\r
            require(pool != address(0), "Registry: zero pool");\r
            exIndexUintOf[pool]             = exIndexUint[i];\r
            exHasEthFlagOf[pool]            = exHasEthFlag[i];\r
            exHasReceiverOf[pool]           = exHasReceiver[i];\r
            exHasReceiverUnderlyingOf[pool] = exHasReceiverUnderlying[i];\r
            hasProfile[pool]                = true;\r
            emit PoolProfileSet(pool, exIndexUint[i], exHasEthFlag[i], exHasReceiver[i], exHasReceiverUnderlying[i]);\r
        }\r
    }\r
\r
    /**\r
     * @notice Delete a saved profile for a pool.\r
     * @dev    After deletion, calling modules may fall back to defaults or skip routing.\r
     * @param  pool Pool address\r
     */\r
    function clearPoolProfile(address pool) external onlyOwner {\r
        delete exIndexUintOf[pool];\r
        delete exHasEthFlagOf[pool];\r
        delete exHasReceiverOf[pool];\r
        delete exHasReceiverUnderlyingOf[pool]; // NEW\r
        delete hasProfile[pool];\r
        emit PoolProfileCleared(pool);\r
    }\r
\r
    /**\r
     * @notice Sets the global default profile returned when a pool lacks an explicit profile.\r
     * @dev    Emits {DefaultProfileSet}. Parameter order matches {setPoolProfile} to reduce misconfiguration risk.\r
     * @param  exIndexUint                true => `exchange(uint256,...)`; false => `exchange(int128,...)`\r
     * @param  exHasEthFlag               true => non-underlying has trailing `bool use_eth`\r
     * @param  exHasReceiver              true => non-underlying receiver overloads exist\r
     * @param  exHasReceiverUnderlying    true => underlying receiver overloads exist\r
     */\r
    function setDefaultProfile(\r
        bool exIndexUint,\r
        bool exHasEthFlag,\r
        bool exHasReceiver,\r
        bool exHasReceiverUnderlying\r
    ) external onlyOwner {\r
        _defaultProfile = PoolProfile({\r
            exIndexUint: exIndexUint,\r
            exHasEthFlag: exHasEthFlag,\r
            exHasReceiver: exHasReceiver,\r
            exHasReceiverUnderlying: exHasReceiverUnderlying\r
        });\r
        emit DefaultProfileSet(_defaultProfile);\r
    }\r
\r
    /**\r
     * @notice Canonical pair key, order-independent.\r
     * @param  a    Token address\r
     * @param  b    Token address\r
     * @return Pair key `keccak256(sorted(a, b))`\r
     */\r
    function _pairKey(address a, address b) internal pure returns (bytes32) {\r
        return a < b ? keccak256(abi.encodePacked(a, b))\r
                     : keccak256(abi.encodePacked(b, a));\r
    }\r
}"
    },
    "@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
"
    }
  }
}}

Tags:
Multisig, Swap, Multi-Signature, Factory|addr:0x2c20ce911734ab586e8cddfac2b713a65b0163cb|verified:true|block:23704725|tx:0xdb049dc887e52dcdc3ebc8db6be82a6c4f6dfb3fe5482d4579d0e30785ea725d|first_check:1762003062

Submitted on: 2025-11-01 14:17:43

Comments

Log in to comment.

No comments yet.