HissZapV2

0x85014ba9f2a4fd2da895f92076fa3776765b5a9f

Verification
Verified
v0.8.34+commit.80d5c536
Type
Contract
3,666 bytes
ABI entries
15
6 read · 4 write
License
none

Contract information

Address
0x85014ba9f2a4fd2da895f92076fa3776765b5a9f
Chain
Robinhood Chain (4663)
Compiler
v0.8.34+commit.80d5c536
Optimization
Enabled
Creation tx
0x223e31cb59…9383f8f08e

Token

Not a token

This contract does not expose ERC-20 metadata.

Read contract (6)

POOL_FEE()uint24
REFERRAL_BPS()uint256
pendingReferralEth(address)uint256
swapRouter()address
totalReferralEth()uint256
weth()address

Events (3)

ReferralClaimedZapBuyZapSell

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "swapRouter_",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "weth_",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "referrer",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "ReferralClaimed",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "buyer",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethIn",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokensOut",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "referrer",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "referralFee",
        "type": "uint256"
      }
    ],
    "name": "ZapBuy",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "seller",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokensIn",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethOut",
        "type": "uint256"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "referrer",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "referralFee",
        "type": "uint256"
      }
    ],
    "name": "ZapSell",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "POOL_FEE",
    "outputs": [
      {
        "internalType": "uint24",
        "name": "",
        "type": "uint24"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "REFERRAL_BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "minOut",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "referrer",
        "type": "address"
      }
    ],
    "name": "buy",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "amountOut",
        "type": "uint256"
      }
    ],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "claimReferral",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "pendingReferralEth",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "minOut",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "referrer",
        "type": "address"
      }
    ],
    "name": "sell",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "ethOut",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "minOut",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "deadline",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      },
      {
        "internalType": "address",
        "name": "referrer",
        "type": "address"
      }
    ],
    "name": "sellWithPermit",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "ethOut",
        "type": "uint256"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapRouter",
    "outputs": [
      {
        "internalType": "contract ISwapRouter02ZapV2",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalReferralEth",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "weth",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "stateMutability": "payable",
    "type": "receive"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/// ---------------------------------------------------------------------------
/// HissZapV2 — one-transaction buy/sell helper with referral fees
/// ---------------------------------------------------------------------------
/// Everything HissZap does (native-ETH buys, EIP-2612 permit sells with no
/// approval tx, plain sells for pre-V3.3 tokens) PLUS an optional referrer:
///
///   buy(token, minOut, referrer)
///     REFERRAL_BPS (0.5%) of the ETH is credited to `referrer` before the
///     swap. Pass address(0) for no referral (full amount is swapped).
///
///   sellWithPermit / sell(..., referrer)
///     REFERRAL_BPS of the ETH proceeds is credited to `referrer`.
///
/// Referral earnings use the same pull pattern as the launchpad: they accrue
/// in pendingReferralEth and the referrer withdraws with claimReferral().
/// Self-referrals are ignored (treated as no referrer) so the fee cannot be
/// used as a rebate loophole.
///
/// Stateless apart from referral accounting. No owner, no admin, immutable
/// referral rate — integrators can rely on it never changing under them.
///
/// Deploy (Robinhood Chain mainnet, chain id 4663):
///   swapRouter_: 0xcaf681a66d020601342297493863e78c959e5cb2 (SwapRouter02)
///   weth_:       0x0bd7d308f8e1639fab988df18a8011f41eacad73 (WETH9)
/// Compile with solc 0.8.24+, optimization enabled (200 runs).
/// ---------------------------------------------------------------------------

interface IERC20PermitV2 {
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

interface ISwapRouter02ZapV2 {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }

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

interface IWETH9ZapV2 {
    function withdraw(uint256 amount) external;
}

contract HissZapV2 {
    uint24 public constant POOL_FEE = 10_000; // HISS pools are all 1%
    /// Referral fee on the ETH side of every referred trade: 50 bps = 0.5%.
    /// Immutable by design — no admin can raise it later.
    uint256 public constant REFERRAL_BPS = 50;
    uint256 internal constant BPS = 10_000;

    ISwapRouter02ZapV2 public immutable swapRouter;
    address public immutable weth;

    /// Referral earnings, pull pattern.
    mapping(address => uint256) public pendingReferralEth;
    /// Sum of all pendingReferralEth — kept so sells never touch escrowed
    /// referral money when computing proceeds.
    uint256 public totalReferralEth;

    event ZapBuy(
        address indexed buyer,
        address indexed token,
        uint256 ethIn,
        uint256 tokensOut,
        address indexed referrer,
        uint256 referralFee
    );
    event ZapSell(
        address indexed seller,
        address indexed token,
        uint256 tokensIn,
        uint256 ethOut,
        address indexed referrer,
        uint256 referralFee
    );
    event ReferralClaimed(address indexed referrer, uint256 amount);

    uint256 private locked = 1;

    modifier nonReentrant() {
        require(locked == 1, "reentrancy");
        locked = 2;
        _;
        locked = 1;
    }

    constructor(address swapRouter_, address weth_) {
        swapRouter = ISwapRouter02ZapV2(swapRouter_);
        weth = weth_;
    }

    /// Buy `token` with native ETH in one transaction. If `referrer` is set
    /// (and isn't the buyer), 0.5% of the ETH is credited to them and the
    /// rest is swapped. Tokens go straight to the caller.
    function buy(address token, uint256 minOut, address referrer)
        external
        payable
        nonReentrant
        returns (uint256 amountOut)
    {
        require(msg.value > 0, "no eth");
        uint256 fee = _takeReferral(msg.value, referrer, msg.sender);
        uint256 ethIn = msg.value - fee;

        amountOut = swapRouter.exactInputSingle{value: ethIn}(
            ISwapRouter02ZapV2.ExactInputSingleParams({
                tokenIn: weth,
                tokenOut: token,
                fee: POOL_FEE,
                recipient: msg.sender,
                amountIn: ethIn,
                amountOutMinimum: minOut,
                sqrtPriceLimitX96: 0
            })
        );
        emit ZapBuy(msg.sender, token, msg.value, amountOut, referrer, fee);
    }

    /// Sell using an EIP-2612 permit signed off-chain — one transaction, no
    /// prior approval. 0.5% of the ETH proceeds goes to `referrer` if set.
    function sellWithPermit(
        address token,
        uint256 amount,
        uint256 minOut,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s,
        address referrer
    ) external nonReentrant returns (uint256 ethOut) {
        // Front-running a broadcast permit can only grief (the griefer pays
        // gas to set the exact allowance we want), so tolerate it.
        if (IERC20PermitV2(token).allowance(msg.sender, address(this)) < amount) {
            IERC20PermitV2(token).permit(msg.sender, address(this), amount, deadline, v, r, s);
        }
        ethOut = _sell(token, amount, minOut, referrer);
    }

    /// Sell after a one-time ERC-20 approval (pre-V3.3 tokens without permit).
    function sell(address token, uint256 amount, uint256 minOut, address referrer)
        external
        nonReentrant
        returns (uint256 ethOut)
    {
        ethOut = _sell(token, amount, minOut, referrer);
    }

    /// Withdraw accumulated referral earnings.
    function claimReferral() external nonReentrant {
        uint256 amount = pendingReferralEth[msg.sender];
        require(amount > 0, "nothing to claim");
        pendingReferralEth[msg.sender] = 0;
        totalReferralEth -= amount;
        (bool ok, ) = msg.sender.call{value: amount}("");
        require(ok, "eth send failed");
        emit ReferralClaimed(msg.sender, amount);
    }

    // ------------------------------ internal ------------------------------

    function _takeReferral(uint256 ethAmount, address referrer, address trader)
        internal
        returns (uint256 fee)
    {
        if (referrer == address(0) || referrer == trader) return 0;
        fee = (ethAmount * REFERRAL_BPS) / BPS;
        if (fee > 0) {
            pendingReferralEth[referrer] += fee;
            totalReferralEth += fee;
        }
    }

    function _sell(address token, uint256 amount, uint256 minOut, address referrer)
        internal
        returns (uint256 ethOut)
    {
        require(amount > 0, "no tokens");
        require(IERC20PermitV2(token).transferFrom(msg.sender, address(this), amount), "transfer");
        require(IERC20PermitV2(token).approve(address(swapRouter), amount), "approve");

        uint256 wethOut = swapRouter.exactInputSingle(
            ISwapRouter02ZapV2.ExactInputSingleParams({
                tokenIn: token,
                tokenOut: weth,
                fee: POOL_FEE,
                recipient: address(this),
                amountIn: amount,
                amountOutMinimum: minOut,
                sqrtPriceLimitX96: 0
            })
        );

        IWETH9ZapV2(weth).withdraw(wethOut);
        uint256 fee = _takeReferral(wethOut, referrer, msg.sender);
        ethOut = wethOut - fee;
        (bool ok, ) = msg.sender.call{value: ethOut}("");
        require(ok, "eth send failed");
        emit ZapSell(msg.sender, token, amount, ethOut, referrer, fee);
    }

    /// Accept ETH only from WETH withdrawals.
    receive() external payable {
        require(msg.sender == weth, "no direct eth");
    }
}
Chain explorer5762msChain node90ms