Skip to main content
PulseScanner.io

Address

0xcbd4424a0cb71825e7bb1d2fa563eefd0b4278cc
Current Holdings
$0.00294000
TXs sent
0
First Active
2026-07-22
block 27,096,127
Last Active
3 days ago
block 27,540,383
Funded By
not identified

Net worth historyi

75 snapshots · to block 27,540,384coverage change 26 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Augcoverage change 27 Aug
exact matchCallMeBabysolc 0.8.20+commit.a1b79de6runtime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/// ============================================================================
/// CallMeBaby
/// ----------------------------------------------------------------------------
/// Atomic two-pool flash-swap arbitrage between a "V1" and "V2" SHD/WPLS pair.
///
/// How it avoids needing pre-funded capital:
///   Uniswap-V2-style pairs let you call `swap()` and receive the output token
///   BEFORE paying anything, as long as you repay (in either token) before the
///   same transaction ends, and you pass non-empty `data` so the pair calls
///   your contract's `uniswapV2Call` callback mid-swap. This contract:
///     1. Flash-borrows SHD from the cheaper pool (no payment yet).
///     2. Sells that SHD into the more expensive pool for WPLS.
///     3. Sends the WPLS needed to repay the flash-borrow back to the first pool.
///     4. Keeps whatever WPLS is left as profit.
///   If steps 2-4 don't produce enough WPLS to repay + clear minProfitWPLS,
///   the whole transaction reverts. There is no partial-failure state — the
///   contract never needs to hold WPLS/SHD ahead of time.
///
/// Only `owner` (the deployer, transferrable) can trigger arbitrage or move
/// funds out of the contract.
/// ============================================================================

interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

interface IUniswapV2Pair {
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
}

contract CallMeBaby {
    // ===================== STATE =====================

    address public owner;
    bool public paused;

    address public immutable WPLS;
    address public immutable SHD;
    address public immutable pairV1;
    address public immutable pairV2;

    // Fee numerators (denominator fixed at 1000). 997 = the common 0.3%-style
    // Uniswap-V2 fee. VERIFY the real fee for V1 and V2 on-chain before relying
    // on these defaults — if either pool actually charges a different fee, the
    // repay/profit math here will be wrong and every call will simply revert
    // (safe, but wastes gas) rather than silently mis-execute.
    uint256 public feeNumV1 = 997;
    uint256 public feeNumV2 = 997;
    uint256 public constant FEE_DENOM = 1000;

    // Optional safety cap on how much SHD a single call may flash-borrow.
    // 0 = no cap.
    uint256 public maxShdBorrowAmount;

    bool private locked;

    // ===================== EVENTS =====================

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event PausedSet(bool paused);
    event FeesUpdated(uint256 feeNumV1, uint256 feeNumV2);
    event MaxBorrowUpdated(uint256 maxShdBorrowAmount);
    event ArbExecuted(address indexed borrowPair, address indexed sellPair, uint256 shdBorrowed, uint256 profitWPLS);
    event Withdrawn(address indexed token, address indexed to, uint256 amount);

    // ===================== MODIFIERS =====================

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

    modifier whenNotPaused() {
        require(!paused, "paused");
        _;
    }

    modifier nonReentrant() {
        require(!locked, "reentrant");
        locked = true;
        _;
        locked = false;
    }

    // ===================== CONSTRUCTOR =====================

    constructor(address _wpls, address _shd, address _pairV1, address _pairV2) {
        require(
            _wpls != address(0) && _shd != address(0) && _pairV1 != address(0) && _pairV2 != address(0),
            "zero addr"
        );
        owner = msg.sender;
        WPLS = _wpls;
        SHD = _shd;
        pairV1 = _pairV1;
        pairV2 = _pairV2;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    // ===================== OWNER ADMIN =====================

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

    function setPaused(bool _paused) external onlyOwner {
        paused = _paused;
        emit PausedSet(_paused);
    }

    function setFees(uint256 _feeNumV1, uint256 _feeNumV2) external onlyOwner {
        require(_feeNumV1 <= FEE_DENOM && _feeNumV2 <= FEE_DENOM, "bad fee");
        feeNumV1 = _feeNumV1;
        feeNumV2 = _feeNumV2;
        emit FeesUpdated(_feeNumV1, _feeNumV2);
    }

    function setMaxShdBorrowAmount(uint256 _max) external onlyOwner {
        maxShdBorrowAmount = _max;
        emit MaxBorrowUpdated(_max);
    }

    /// @notice Sweep any ERC20 sitting in this contract (accumulated profit, dust, etc.)
    function withdrawToken(address token, uint256 amount, address to) external onlyOwner {
        require(to != address(0), "zero addr");
        require(IERC20(token).transfer(to, amount), "transfer failed");
        emit Withdrawn(token, to, amount);
    }

    /// @notice Sweep any native PLS sitting in this contract.
    function withdrawPLS(uint256 amount, address payable to) external onlyOwner {
        require(to != address(0), "zero addr");
        (bool ok, ) = to.call{value: amount}("");
        require(ok, "PLS transfer failed");
        emit Withdrawn(address(0), to, amount);
    }

    receive() external payable {}

    // ===================== VIEW / MATH HELPERS =====================

    function getReservesOrdered(address pair, address tokenA) public view returns (uint256 reserveA, uint256 reserveB) {
        (uint112 r0, uint112 r1, ) = IUniswapV2Pair(pair).getReserves();
        address token0 = IUniswapV2Pair(pair).token0();
        if (token0 == tokenA) {
            return (r0, r1);
        } else {
            return (r1, r0);
        }
    }

    function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut, uint256 feeNum)
        public
        pure
        returns (uint256)
    {
        if (amountIn == 0 || reserveIn == 0 || reserveOut == 0) return 0;
        uint256 amountInWithFee = amountIn * feeNum;
        uint256 numerator = amountInWithFee * reserveOut;
        uint256 denominator = reserveIn * FEE_DENOM + amountInWithFee;
        return numerator / denominator;
    }

    function getAmountIn(uint256 amountOut, uint256 reserveIn, uint256 reserveOut, uint256 feeNum)
        public
        pure
        returns (uint256)
    {
        require(amountOut < reserveOut, "insufficient liquidity");
        uint256 numerator = reserveIn * amountOut * FEE_DENOM;
        uint256 denominator = (reserveOut - amountOut) * feeNum;
        return (numerator / denominator) + 1;
    }

    /// @notice Read-only preview of an arb size, so an off-chain bot can check
    ///         profitability before sending a transaction. executeArb() re-derives
    ///         and re-checks all of this on-chain anyway, so this is a convenience,
    ///         not a security boundary.
    function quoteArb(bool buyOnV1, uint256 shdBorrowAmount)
        external
        view
        returns (uint256 wplsOut, uint256 wplsRepay, int256 profit)
    {
        address borrowPair = buyOnV1 ? pairV1 : pairV2;
        address sellPair = buyOnV1 ? pairV2 : pairV1;
        uint256 feeBorrow = buyOnV1 ? feeNumV1 : feeNumV2;
        uint256 feeSell = buyOnV1 ? feeNumV2 : feeNumV1;

        (uint256 reserveSHDSell, uint256 reserveWPLSSell) = getReservesOrdered(sellPair, SHD);
        wplsOut = getAmountOut(shdBorrowAmount, reserveSHDSell, reserveWPLSSell, feeSell);

        (uint256 reserveSHDBorrow, uint256 reserveWPLSBorrow) = getReservesOrdered(borrowPair, SHD);
        wplsRepay = getAmountIn(shdBorrowAmount, reserveWPLSBorrow, reserveSHDBorrow, feeBorrow);

        profit = int256(wplsOut) - int256(wplsRepay);
    }

    // ===================== ARB EXECUTION =====================

    /// @param buyOnV1 true  = SHD is cheaper on V1: borrow SHD from V1, sell it on V2, repay V1 in WPLS.
    ///                false = SHD is cheaper on V2: borrow SHD from V2, sell it on V1, repay V2 in WPLS.
    /// @param shdBorrowAmount how much SHD to flash-borrow from the cheap pool (sized off-chain,
    ///        e.g. by the same ternary-search optimizer used in arb.js).
    /// @param minProfitWPLS revert unless net profit (in WPLS, before gas) is at least this much.
    function executeArb(bool buyOnV1, uint256 shdBorrowAmount, uint256 minProfitWPLS)
        external
        onlyOwner
        whenNotPaused
        nonReentrant
    {
        require(shdBorrowAmount > 0, "zero amount");
        if (maxShdBorrowAmount > 0) {
            require(shdBorrowAmount <= maxShdBorrowAmount, "exceeds max borrow");
        }

        address borrowPair = buyOnV1 ? pairV1 : pairV2;

        address token0 = IUniswapV2Pair(borrowPair).token0();
        uint256 amount0Out = token0 == SHD ? shdBorrowAmount : 0;
        uint256 amount1Out = token0 == SHD ? 0 : shdBorrowAmount;

        // Non-empty data is what makes this a flash swap: the pair will call
        // uniswapV2Call on `to` (this contract) before checking repayment.
        bytes memory data = abi.encode(buyOnV1, minProfitWPLS);
        IUniswapV2Pair(borrowPair).swap(amount0Out, amount1Out, address(this), data);
    }

    /// @dev Uniswap-V2-style flash swap callback. Called by pairV1 or pairV2 mid-`swap()`,
    ///      never called directly by us.
    function uniswapV2Call(address sender, uint256 amount0, uint256 amount1, bytes calldata data) external {
        // Only one of our two known pairs may call this...
        require(msg.sender == pairV1 || msg.sender == pairV2, "unknown pair");
        // ...and only as a result of a swap *we* initiated (blocks a third party from
        // calling pair.swap(..., to: thisContract, ...) themselves to spoof this callback).
        require(sender == address(this), "not our flash swap");

        (bool buyOnV1, uint256 minProfitWPLS) = abi.decode(data, (bool, uint256));

        address borrowPair = msg.sender;
        address sellPair = buyOnV1 ? pairV2 : pairV1;
        uint256 feeBorrow = buyOnV1 ? feeNumV1 : feeNumV2;
        uint256 feeSell = buyOnV1 ? feeNumV2 : feeNumV1;

        uint256 shdReceived = amount0 > 0 ? amount0 : amount1;
        require(shdReceived > 0, "nothing borrowed");

        // ---- Leg 2: sell the borrowed SHD on the other pool for WPLS ----
        require(IERC20(SHD).transfer(sellPair, shdReceived), "transfer to sellPair failed");

        (uint256 reserveSHDSell, uint256 reserveWPLSSell) = getReservesOrdered(sellPair, SHD);
        uint256 wplsOut = getAmountOut(shdReceived, reserveSHDSell, reserveWPLSSell, feeSell);
        require(wplsOut > 0, "sell leg produced nothing");

        address sellToken0 = IUniswapV2Pair(sellPair).token0();
        uint256 s0Out = sellToken0 == WPLS ? wplsOut : 0;
        uint256 s1Out = sellToken0 == WPLS ? 0 : wplsOut;
        IUniswapV2Pair(sellPair).swap(s0Out, s1Out, address(this), ""); // empty data = plain swap, no callback

        // ---- Figure out what we owe the borrow pool to repay the flash swap ----
        (uint256 reserveSHDBorrow, uint256 reserveWPLSBorrow) = getReservesOrdered(borrowPair, SHD);
        uint256 wplsRepay = getAmountIn(shdReceived, reserveWPLSBorrow, reserveSHDBorrow, feeBorrow);

        require(wplsOut > wplsRepay, "unprofitable");
        uint256 profit = wplsOut - wplsRepay;
        require(profit >= minProfitWPLS, "profit below minimum");

        require(IERC20(WPLS).transfer(borrowPair, wplsRepay), "repay transfer failed");
        // Profit is left sitting in this contract in WPLS; withdraw anytime via withdrawToken().

        emit ArbExecuted(borrowPair, sellPair, shdReceived, profit);
    }
}