RobinToken
0x56a98db16cf501b686c14ba00a5dec02e87083fa
Verification
Verified
v0.8.26+commit.8a97fa7a
Type
Contract
4,634 bytes
ABI entries
30
18 read · 6 write
License
none
Contract information
- Address
- 0x56a98db16cf501b686c14ba00a5dec02e87083fa
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.26+commit.8a97fa7a
- Optimization
- Enabled
- Creator
- 0xD952A74C85…EBa8C94AFC
- Creation tx
- 0xa3bd786b02…0b9b522648
Token
- Name
- Robinfun
- Symbol
- ROBINFUN
- Decimals
- 18
- Holders
- 1,658
- Market
- View token page →
Read contract (18)
FEE_BPS() → uint256
SWAP_THRESHOLD_USD() → uint256
allowance(address, address) → uint256
balanceOf(address) → uint256
creator() → address
decimals() → uint8
dexLive() → bool
ethUsdPrice8() → uint256
factory() → address
feeExempt(address) → bool
feeRecipient() → address
name() → string
pair() → address
router() → address
symbol() → string
totalSupply() → uint256
treasury() → address
weth() → address
Events (4)
ApprovalDexConfiguredFeeSwappedTransfer
ABI
[
{
"inputs": [
{
"internalType": "string",
"name": "_name",
"type": "string"
},
{
"internalType": "string",
"name": "_symbol",
"type": "string"
},
{
"internalType": "uint256",
"name": "_supply",
"type": "uint256"
},
{
"internalType": "address",
"name": "_creator",
"type": "address"
},
{
"internalType": "address",
"name": "_feeRecipient",
"type": "address"
},
{
"internalType": "address",
"name": "_treasury",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "pair",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "router",
"type": "address"
}
],
"name": "DexConfigured",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "tokensSold",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "ethToCreator",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "ethToTreasury",
"type": "uint256"
}
],
"name": "FeeSwapped",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
{
"inputs": [],
"name": "FEE_BPS",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "SWAP_THRESHOLD_USD",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "spender",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_router",
"type": "address"
},
{
"internalType": "address",
"name": "_pair",
"type": "address"
},
{
"internalType": "address",
"name": "_weth",
"type": "address"
},
{
"internalType": "uint256",
"name": "_ethUsdPrice8",
"type": "uint256"
}
],
"name": "configureDex",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "creator",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "decimals",
"outputs": [
{
"internalType": "uint8",
"name": "",
"type": "uint8"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "dexLive",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "ethUsdPrice8",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "factory",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "feeExempt",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "feeRecipient",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "name",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pair",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "router",
"outputs": [
{
"internalType": "contract IUniswapV2Router02",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_ethUsdPrice8",
"type": "uint256"
}
],
"name": "setEthUsdPrice",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "bool",
"name": "exempt",
"type": "bool"
}
],
"name": "setFeeExempt",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "from",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "treasury",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"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.26;
import {IUniswapV2Router02, IUniswapV2Pair} from "./interfaces/IUniswapV2.sol";
/// @title RobinToken
/// @notice Fixed-supply ERC20 with a 1% fee-on-transfer that, after graduation, is auto-swapped
/// to ETH and split 50/50 creator / treasury.
///
/// BEFORE graduation: the factory is fee-exempt, so all curve trades and the initial
/// liquidity add use exact amounts. The curve trade fee is taken in ETH by the factory.
///
/// AFTER graduation (token live on Uniswap V2): every non-exempt transfer (i.e. swaps)
/// charges 1%, accumulating tokens in THIS contract. When the accumulated tokens are worth
/// at least $5 (valued via the live pool reserves + the factory's ethUsdPrice), the
/// contract sells them for ETH and pays the creator and treasury 50/50 in ETH.
///
/// The auto-swap only runs when `from` is NOT the pair (i.e. on sells / normal transfers),
/// never inside a buy, to avoid reentering the pair mid-swap.
contract RobinToken {
string public name;
string public symbol;
uint8 public constant decimals = 18;
uint256 public immutable totalSupply;
address public immutable factory;
address public immutable creator;
/// @notice where the creator's 50% of the post-DEX auto-swap fee is sent. Chosen by the creator
/// at launch (defaults to the creator if they didn't pick a different address).
address public immutable feeRecipient;
address public immutable treasury;
uint256 public constant FEE_BPS = 100; // 1% total
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
mapping(address => bool) public feeExempt;
// --- DEX auto-swap config (set by factory at graduation) ---
IUniswapV2Router02 public router;
address public pair;
address public weth;
bool public dexLive; // true once graduated & pair is set
/// @notice USD price of ETH with 8 decimals (snapshotted at graduation; mirrors the factory).
uint256 public ethUsdPrice8;
/// @notice swap-back threshold in USD (8 decimals). $5 = 5e8.
uint256 public constant SWAP_THRESHOLD_USD = 5 * 1e8;
bool private _swapping; // reentrancy guard for the auto-swap
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event FeeSwapped(uint256 tokensSold, uint256 ethToCreator, uint256 ethToTreasury);
event DexConfigured(address pair, address router);
constructor(
string memory _name,
string memory _symbol,
uint256 _supply,
address _creator,
address _feeRecipient,
address _treasury
) {
name = _name;
symbol = _symbol;
totalSupply = _supply;
factory = msg.sender;
creator = _creator;
// fall back to the creator if no explicit recipient was chosen
feeRecipient = _feeRecipient == address(0) ? _creator : _feeRecipient;
treasury = _treasury;
feeExempt[msg.sender] = true; // factory exempt -> exact curve + liquidity math
feeExempt[address(this)] = true; // this contract (holds + sells fee tokens) exempt
balanceOf[msg.sender] = _supply;
emit Transfer(address(0), msg.sender, _supply);
}
modifier onlyFactory() {
require(msg.sender == factory, "ONLY_FACTORY");
_;
}
function setFeeExempt(address account, bool exempt) external onlyFactory {
feeExempt[account] = exempt;
}
/// @notice Called by the factory at graduation to wire up the DEX auto-swap.
function configureDex(address _router, address _pair, address _weth, uint256 _ethUsdPrice8)
external
onlyFactory
{
require(!dexLive, "ALREADY_CONFIGURED"); // graduation is one-time
router = IUniswapV2Router02(_router);
pair = _pair;
weth = _weth;
ethUsdPrice8 = _ethUsdPrice8;
dexLive = true;
// approve router once to sell accumulated fee tokens
allowance[address(this)][_router] = type(uint256).max;
emit Approval(address(this), _router, type(uint256).max);
emit DexConfigured(_pair, _router);
}
/// @notice Owner-side (factory) may refresh the ETH/USD price used for the $5 threshold.
function setEthUsdPrice(uint256 _ethUsdPrice8) external onlyFactory {
ethUsdPrice8 = _ethUsdPrice8;
}
function approve(address spender, uint256 value) external returns (bool) {
allowance[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
function transfer(address to, uint256 value) external returns (bool) {
return _transfer(msg.sender, to, value);
}
function transferFrom(address from, address to, uint256 value) external returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) {
require(allowed >= value, "ERC20: insufficient allowance");
allowance[from][msg.sender] = allowed - value;
}
return _transfer(from, to, value);
}
function _transfer(address from, address to, uint256 value) internal returns (bool) {
require(to != address(0), "ERC20: transfer to zero");
uint256 bal = balanceOf[from];
require(bal >= value, "ERC20: insufficient balance");
// Try the auto-swap BEFORE applying this transfer's fee, but only on sells (to == pair)
// and never while already swapping or during a buy (from == pair).
if (dexLive && !_swapping && from != pair && to == pair) {
_maybeSwapBack();
}
unchecked {
balanceOf[from] = bal - value;
}
// Tax ONLY DEX trades: a transfer is taxed when one side is the pair (1% per buy, 1% per
// sell). Plain wallet-to-wallet transfers are NOT taxed. Exempt addresses are never taxed.
uint256 fee = 0;
bool isDexTrade = (from == pair || to == pair);
if (isDexTrade && !feeExempt[from] && !feeExempt[to] && FEE_BPS > 0) {
fee = (value * FEE_BPS) / 10_000;
}
if (fee > 0) {
unchecked {
balanceOf[address(this)] += fee; // accumulate fee tokens in this contract
balanceOf[to] += value - fee;
}
emit Transfer(from, address(this), fee);
emit Transfer(from, to, value - fee);
} else {
unchecked {
balanceOf[to] += value;
}
emit Transfer(from, to, value);
}
return true;
}
/// @dev If the accumulated fee tokens are worth >= $5, sell them for ETH and pay
/// creator/treasury 50/50. Valued via the live pool reserves + ethUsdPrice8.
function _maybeSwapBack() internal {
uint256 tokenBal = balanceOf[address(this)];
if (tokenBal == 0) return;
// value the accumulated tokens in USD (8 dec) using the pool's ETH/token ratio
(uint112 r0, uint112 r1,) = IUniswapV2Pair(pair).getReserves();
address t0 = IUniswapV2Pair(pair).token0();
uint256 tokenReserve = t0 == address(this) ? uint256(r0) : uint256(r1);
uint256 wethReserve = t0 == address(this) ? uint256(r1) : uint256(r0);
if (tokenReserve == 0 || wethReserve == 0) return;
// ethValue (wei) of tokenBal at spot = tokenBal * wethReserve / tokenReserve
uint256 ethValueWei = (tokenBal * wethReserve) / tokenReserve;
// usdValue (8 dec) = ethValueWei * ethUsdPrice8 / 1e18
uint256 usdValue8 = (ethValueWei * ethUsdPrice8) / 1e18;
if (usdValue8 < SWAP_THRESHOLD_USD) return;
// don't dump more than ~1% of the pool's token reserve in one go (limit price impact);
// a large accumulation clears over several swaps.
uint256 maxSell = tokenReserve / 100; // 1% of reserve
uint256 sellAmount = tokenBal > maxSell && maxSell > 0 ? maxSell : tokenBal;
// slippage floor: expected ETH out via constant product (0.3% pool fee), minus 10%.
// If the real out would breach this (sandwich / thin liquidity), the swap reverts and the
// tokens are simply retained for a later attempt — the user's transfer is never bricked.
uint256 amountInWithFee = sellAmount * 997;
uint256 expectedOut = (amountInWithFee * wethReserve) / (tokenReserve * 1000 + amountInWithFee);
uint256 minOut = (expectedOut * 90) / 100; // 10% tolerance
_swapping = true;
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = weth;
// sell tokens for ETH (this token is fee-exempt for its own transfers; router/pair exact).
try router.swapExactTokensForETHSupportingFeeOnTransferTokens(
sellAmount, minOut, path, address(this), block.timestamp
) {
// Pay out the ENTIRE ETH balance (sweeps any ETH orphaned by a prior failed payout),
// split 50/50 between the creator's chosen feeRecipient and the treasury. Best-effort:
// a failed leg never reverts the user's transfer.
uint256 ethBal = address(this).balance;
if (ethBal > 0) {
uint256 half = ethBal / 2;
uint256 paidCreator = 0;
(bool okC,) = feeRecipient.call{value: half}("");
if (okC) paidCreator = half;
uint256 toTreasury = ethBal - paidCreator; // creator's failed share folds in
uint256 paidTreasury = 0;
if (toTreasury > 0) {
(bool okT,) = treasury.call{value: toTreasury}("");
if (okT) paidTreasury = toTreasury;
}
emit FeeSwapped(sellAmount, paidCreator, paidTreasury);
}
} catch {
// swap failed (e.g. thin liquidity / slippage floor) — keep tokens for a later attempt
}
_swapping = false;
}
receive() external payable {}
}
Chain explorer4909msChain node81ms