USDS2USDC2DAI

Description:

ERC20 token contract with Factory capabilities. Standard implementation for fungible tokens on Ethereum.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/USDS2USDC2DAI.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.25;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IDssLitePsm} from "./interfaces/IDssLitePsm.sol";
import {IDaiUsds} from "./interfaces/IDaiUsds.sol";

contract USDS2USDC2DAI {
    IERC20 public constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);

    IERC20 public constant USDS = IERC20(0xdC035D45d973E3EC169d2276DDab16f1e407384F);

    IERC20 public constant DAI = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);

    //usdc<<->>dai
    IDssLitePsm public constant DssLitePsm = IDssLitePsm(0xf6e72Db5454dd049d0788e411b06CfAF16853042);

    //dai<<->>usds
    IDaiUsds public constant DaiUsds = IDaiUsds(0x3225737a9Bbb6473CB4a45b7244ACa2BeFdB276A);

    event Usdc2Usds(address usr, uint256 usdsAmount, uint256 usdcAmount);
    event Usds2Usdc(address usr, uint256 usdsAmount, uint256 usdcAmount);
    event Usdc2Dai(address usr, uint256 usdsAmount, uint256 daiAmount);
    event Dai2Usdc(address usr, uint256 daiAmount, uint256 usdcAmount);
    event Usds2Dai(address usr, uint256 usdsAmount, uint256 daiAmount);
    event Dai2Usds(address usr, uint256 daiAmount, uint256 usdsAmount);

    function usdc2usds(uint256 _fromAmount) external returns (uint256) {
        // usdc->dai
        USDC.transferFrom(msg.sender, address(this), _fromAmount);
        USDC.approve(address(DssLitePsm), _fromAmount);
        DssLitePsm.sellGem(address(this), _fromAmount);

        //  dai->usds
        uint256 daiAmount_ = DAI.balanceOf(address(this));
        DAI.approve(address(DaiUsds), daiAmount_);
        DaiUsds.daiToUsds(address(this), daiAmount_);
        uint256 usdsAmount_ = USDS.balanceOf(address(this));
        USDS.transfer(msg.sender, usdsAmount_);

        emit Usds2Usdc(msg.sender, _fromAmount, usdsAmount_);
        return usdsAmount_;
    }

    function usds2usdc(uint256 _fromAmount) external returns (uint256) {
        // usds->dai
        USDS.transferFrom(msg.sender, address(this), _fromAmount);
        USDS.approve(address(DaiUsds), _fromAmount);
        DaiUsds.usdsToDai(address(this), _fromAmount);

        // dai->usdc
        uint256 daiAmount_ = DAI.balanceOf(address(this));
        DAI.approve(address(DssLitePsm), daiAmount_);
        DssLitePsm.buyGem(address(this), daiAmount_ / 1e12);
        uint256 usdcAmount_ = USDC.balanceOf(address(this));
        USDC.transfer(msg.sender, usdcAmount_);

        emit Usds2Usdc(msg.sender, _fromAmount, usdcAmount_);
        return usdcAmount_;
    }

    function usdc2dai(uint256 _fromAmount) external returns (uint256) {
        // usdc->dai
        USDC.transferFrom(msg.sender, address(this), _fromAmount);
        USDC.approve(address(DssLitePsm), _fromAmount);
        DssLitePsm.sellGem(address(this), _fromAmount);

        uint256 daiAmount_ = DAI.balanceOf(address(this));
        DAI.transfer(msg.sender, daiAmount_);

        emit Usdc2Dai(msg.sender, _fromAmount, daiAmount_);
        return daiAmount_;
    }

    function dai2usdc(uint256 _fromAmount) external returns (uint256) {
        // dai->usdc
        DAI.transferFrom(msg.sender, address(this), _fromAmount);
        DAI.approve(address(DssLitePsm), _fromAmount);
        DssLitePsm.buyGem(address(this), _fromAmount / 1e12);
        uint256 usdcAmount_ = USDC.balanceOf(address(this));
        USDC.transfer(msg.sender, usdcAmount_);

        emit Dai2Usdc(msg.sender, _fromAmount, usdcAmount_);
        return usdcAmount_;
    }

    function usds2dai(uint256 _fromAmount) external returns (uint256) {
        // usds->dai
        USDS.transferFrom(msg.sender, address(this), _fromAmount);
        USDS.approve(address(DaiUsds), _fromAmount);
        DaiUsds.usdsToDai(address(this), _fromAmount);

        uint256 daiAmount_ = DAI.balanceOf(address(this));
        DAI.transfer(msg.sender, daiAmount_);

        emit Usds2Dai(msg.sender, _fromAmount, daiAmount_);
        return daiAmount_;
    }

    function dai2usds(uint256 _fromAmount) external returns (uint256) {
        //  dai->usds
        DAI.transferFrom(msg.sender, address(this), _fromAmount);
        DAI.approve(address(DaiUsds), _fromAmount);
        DaiUsds.daiToUsds(address(this), _fromAmount);
        uint256 usdsAmount_ = USDS.balanceOf(address(this));
        USDS.transfer(msg.sender, usdsAmount_);

        emit Dai2Usds(msg.sender, _fromAmount, usdsAmount_);
        return usdsAmount_;
    }
}"
    },
    "lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}
"
    },
    "src/interfaces/IDssLitePsm.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.25;

interface IDssLitePsm {
    //dai->usdc
    function buyGem(address usr, uint256 gemAmt) external returns (uint256 daiInWad);

    //usdc->dai
    function sellGem(address usr, uint256 gemAmt) external returns (uint256 daiOutWad);
}
"
    },
    "src/interfaces/IDaiUsds.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.25;

interface IDaiUsds {
    function daiToUsds(address usr, uint256 wad) external;

    function usdsToDai(address usr, uint256 wad) external;
}
"
    }
  },
  "settings": {
    "remappings": [
      "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
      "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
      "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
      "forge-std/=lib/forge-std/src/",
      "halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
      "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
      "openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/"
    ],
    "optimizer": {
      "enabled": false,
      "runs": 200
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs",
      "appendCBOR": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "prague",
    "viaIR": false
  }
}}

Tags:
ERC20, Token, Factory|addr:0x4f119f538cb77faafeb2a857e268ffb66fe60eee|verified:true|block:23394080|tx:0x43c2e72d577d04694eff098c8c70274e648ca0d6099dc621135355a8f1f5e162|first_check:1758276398

Submitted on: 2025-09-19 12:06:40

Comments

Log in to comment.

No comments yet.