TruthTimedSellerV3

Description:

Decentralized Finance (DeFi) protocol contract providing Factory functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "tru3x.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// ---------- Interfaces ----------
interface IERC20 {
    function balanceOf(address a) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 value) external returns (bool);
    function transfer(address to, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
    function decimals() external view returns (uint8);
}

interface ISwapRouter {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24  fee;
        address recipient;
        uint256 deadline;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96; // set 0 for no limit
    }

    function exactInputSingle(ExactInputSingleParams calldata params)
        external
        payable
        returns (uint256 amountOut);
}

// ---------- Contract ----------
contract TruthTimedSellerV3 {
    // --- constants ---
    // Uniswap V3 Router (Ethereum mainnet)
    ISwapRouter public constant V3_ROUTER =
        ISwapRouter(0xE592427A0AEce92De3Edee1F18E0157C05861564);

    // --- immutables & storage ---
    address public immutable OWNER;     // deployer / admin
    address public truu;                // TRUU token (tokenIn)
    address public stable;              // USDT token (tokenOut)

    address public keeper;              // allowed caller besides OWNER
    address public payee;               // USDT receiver (default: OWNER)

    uint256 public sellAmount;          // in TRUU units (respecting TRUU decimals)
    uint256 public interval;            // seconds between sells (e.g. 10800 for 3h)
    uint24  public poolFee;             // 500, 3000, or 10000
    bool    public paused;              // emergency stop

    uint256 public lastExec;            // last successful execute() timestamp

    // --- events ---
    event Executed(uint256 amountIn, uint256 amountOut, uint256 ts);
    event ParamsUpdated(uint256 sellAmount, uint256 interval, uint24 fee, address keeper, address payee, bool paused);
    event ApprovedRouter(uint256 allowance);
    event Swept(address token, address to, uint256 amount);

    // --- modifiers ---
    modifier onlyOwner() {
        require(msg.sender == OWNER, "NOT_OWNER");
        _;
    }

    modifier onlyKeeperOrOwner() {
        require(msg.sender == keeper || msg.sender == OWNER, "NOT_AUTH");
        _;
    }

    constructor(
        address _truu,
        address _stable,
        address _keeper,
        uint256 _sellAmt,
        uint24  _poolFee,
        uint256 _interval
    ) {
        require(_truu != address(0) && _stable != address(0), "ZERO_ADDR");
        OWNER     = msg.sender;
        truu      = _truu;
        stable    = _stable;
        keeper    = _keeper;
        payee     = msg.sender;     // default: owner receives the USDT
        sellAmount= _sellAmt;       // e.g. 500_000 * 10**TRUU_DECIMALS
        poolFee   = _poolFee;       // e.g. 3000 (0.3%)
        interval  = _interval;      // e.g. 10800 (3h)
        paused    = false;
        lastExec  = 0;
        emit ParamsUpdated(sellAmount, interval, poolFee, keeper, payee, paused);
    }

    // ---------- Admin/ops ----------
    function approveRouter() external onlyOwner {
        // approve max so you don't have to re-approve
        uint256 max = type(uint256).max;
        require(IERC20(truu).approve(address(V3_ROUTER), max), "APPROVE_FAIL");
        emit ApprovedRouter(max);
    }

    function setParams(uint256 _sellAmt, uint256 _interval, uint24 _fee) external onlyOwner {
        if (_sellAmt > 0) sellAmount = _sellAmt;
        if (_interval > 0) interval = _interval;
        if (_fee == 500 || _fee == 3000 || _fee == 10000) poolFee = _fee;
        emit ParamsUpdated(sellAmount, interval, poolFee, keeper, payee, paused);
    }

    function setKeeper(address _k) external onlyOwner {
        keeper = _k;
        emit ParamsUpdated(sellAmount, interval, poolFee, keeper, payee, paused);
    }

    function setPayee(address _p) external onlyOwner {
        require(_p != address(0), "ZERO_PAYEE");
        payee = _p;
        emit ParamsUpdated(sellAmount, interval, poolFee, keeper, payee, paused);
    }

    function setPaused(bool _p) external onlyOwner {
        paused = _p;
        emit ParamsUpdated(sellAmount, interval, poolFee, keeper, payee, paused);
    }

    /// Sweep any ERC20 (incl. TRUU/USDT) stuck in the contract.
    function sweep(address token, address to, uint256 amount) external onlyOwner {
        require(IERC20(token).transfer(to, amount), "SWEEP_FAIL");
        emit Swept(token, to, amount);
    }

    // ---------- View helpers ----------
    function nextAllowedAt() public view returns (uint256) {
        return lastExec == 0 ? 0 : lastExec + interval;
    }

    // ---------- Core ----------
    /// @notice Execute a sell if interval elapsed.
    /// @param minOut USDT minimum out to protect against MEV / slippage (set 0 to skip)
    function execute(uint256 minOut) external onlyKeeperOrOwner {
        require(!paused, "PAUSED");
        require(block.timestamp >= nextAllowedAt(), "TOO_SOON");

        // check balance on contract
        uint256 bal = IERC20(truu).balanceOf(address(this));
        require(bal >= sellAmount, "INSUFFICIENT_TRUU");

        // router must have allowance from this contract
        uint256 alw = IERC20(truu).allowance(address(this), address(V3_ROUTER));
        require(alw >= sellAmount, "NEED_APPROVE");

        // perform V3 exactInputSingle
        ISwapRouter.ExactInputSingleParams memory p = ISwapRouter.ExactInputSingleParams({
            tokenIn: truu,
            tokenOut: stable,
            fee: poolFee,
            recipient: payee,                  // send USDT directly to payee
            deadline: block.timestamp + 300,   // 5 minutes
            amountIn: sellAmount,
            amountOutMinimum: minOut,          // set by caller (keeper/owner)
            sqrtPriceLimitX96: 0               // no price limit
        });

        uint256 outAmt = V3_ROUTER.exactInputSingle(p);

        lastExec = block.timestamp;
        emit Executed(sellAmount, outAmt, lastExec);
    }
}"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": []
  }
}}

Tags:
ERC20, DeFi, Factory|addr:0x18bb8bbd92a1b1d223ef4f25f5955fcc8745acb7|verified:true|block:23743097|tx:0xb6e491360ff77978128a8e8a77639bfb27a96bad4e8673534417f7899e6be6fc|first_check:1762509266

Submitted on: 2025-11-07 10:54:27

Comments

Log in to comment.

No comments yet.