Contract detail
RobinPadRouter
RobinPadRouter is a verified Robinhood Chain smart contract at 0x94338247…d83a467a with 0 indexed transactions.
- Address type
- Smart contract
- Transactions
- 0
- History coverage
- No indexed activity found
- Emitted events
- 1
- Verification
- Verified
- Compiler
- v0.8.28+commit.7893614a
- Verification match
- full
- Creation transaction
- 0x0f7044f7…d43bb64f
- Created at block
- #832956
- Language
- solidity
- EVM version
- cancun
- License
- none
- Compiler optimization
- Enabled · 1 runs
Verified contract
Contract source code
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.9;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "./Interfaces.sol";
contract RobinPadRouter is Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;
address public immutable weth;
address public immutable swapRouter;
address public immutable quoter;
address public immutable factory;
address public platformFeeRecipient;
uint256 public feeBps = 50;
uint24 public constant POOL_FEE = 10000;
uint256 public constant MAX_FEE_BPS = 100;
uint256 public constant BPS_DENOMINATOR = 10000;
uint256 public constant PLATFORM_FEE_SHARE_BPS = 3000;
event Buy(
address indexed buyer,
address indexed token,
uint256 ethIn,
uint256 tokensOut,
uint256 fee,
address indexed launchFeeRecipient,
uint256 launchFee,
uint256 platformFee
);
event Sell(
address indexed seller,
address indexed token,
uint256 tokensIn,
uint256 ethOut,
uint256 fee,
address indexed launchFeeRecipient,
uint256 launchFee,
uint256 platformFee
);
event PlatformFeeRecipientUpdated(address indexed oldRecipient, address indexed newRecipient);
event FeeBpsUpdated(uint256 oldFeeBps, uint256 newFeeBps);
constructor(
address weth_,
address swapRouter_,
address quoter_,
address factory_,
address platformFeeRecipient_,
address owner_
) Ownable(owner_) {
require(weth_ != address(0), "Invalid WETH");
require(swapRouter_ != address(0), "Invalid router");
require(quoter_ != address(0), "Invalid quoter");
require(factory_ != address(0), "Invalid factory");
require(platformFeeRecipient_ != address(0), "Invalid fee recipient");
weth = weth_;
swapRouter = swapRouter_;
quoter = quoter_;
factory = factory_;
platformFeeRecipient = platformFeeRecipient_;
IERC20(weth_).approve(swapRouter_, type(uint256).max);
}
receive() external payable {}
function robinBuy(
address token,
uint256 amountIn,
uint256 minTokensOut
) external payable nonReentrant returns (uint256 tokensOut) {
require(amountIn > 0, "Zero amount");
require(token != address(0), "Invalid token");
uint256 fee = (amountIn * feeBps) / BPS_DENOMINATOR;
uint256 amountAfterFee = amountIn - fee;
if (msg.value > 0) {
require(msg.value >= amountIn, "Insufficient ETH");
IWETH(weth).deposit{value: amountAfterFee}();
if (fee > 0) {
_transferEthFee(token, fee);
}
uint256 excess = msg.value - amountIn;
if (excess > 0) {
_sendEth(msg.sender, excess);
}
} else {
IERC20(weth).safeTransferFrom(msg.sender, address(this), amountIn);
if (fee > 0) {
_transferWethFee(token, fee);
}
}
tokensOut = ISwapRouter02(swapRouter).exactInputSingle(
ISwapRouter02.ExactInputSingleParams({
tokenIn: weth,
tokenOut: token,
fee: POOL_FEE,
recipient: msg.sender,
amountIn: amountAfterFee,
amountOutMinimum: minTokensOut,
sqrtPriceLimitX96: 0
})
);
(address launchFeeRecipient, uint256 launchFee, uint256 platformFee) = _feeSplit(token, fee);
emit Buy(msg.sender, token, amountIn, tokensOut, fee, launchFeeRecipient, launchFee, platformFee);
}
function robinSell(
address token,
uint256 tokenAmount,
uint256 minEthOut
) external nonReentrant returns (uint256 ethOut) {
require(tokenAmount > 0, "No tokens");
require(token != address(0), "Invalid token");
IERC20(token).safeTransferFrom(msg.sender, address(this), tokenAmount);
if (IERC20(token).allowance(address(this), swapRouter) < tokenAmount) {
IERC20(token).approve(swapRouter, type(uint256).max);
}
uint256 wethOut = ISwapRouter02(swapRouter).exactInputSingle(
ISwapRouter02.ExactInputSingleParams({
tokenIn: token,
tokenOut: weth,
fee: POOL_FEE,
recipient: address(this),
amountIn: tokenAmount,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
})
);
uint256 ethBefore = address(this).balance;
IWETH(weth).withdraw(wethOut);
uint256 ethReceived = address(this).balance - ethBefore;
uint256 fee = (ethReceived * feeBps) / BPS_DENOMINATOR;
ethOut = ethReceived - fee;
require(ethOut >= minEthOut, "Slippage exceeded");
if (fee > 0) {
_transferEthFee(token, fee);
}
_sendEth(msg.sender, ethOut);
(address launchFeeRecipient, uint256 launchFee, uint256 platformFee) = _feeSplit(token, fee);
emit Sell(msg.sender, token, tokenAmount, ethOut, fee, launchFeeRecipient, launchFee, platformFee);
}
function quoteBuy(address token, uint256 ethAmount) external returns (uint256 tokensOut, uint256 fee) {
fee = (ethAmount * feeBps) / BPS_DENOMINATOR;
uint256 amountAfterFee = ethAmount - fee;
(tokensOut, , , ) = IQuoterV2(quoter).quoteExactInputSingle(
IQuoterV2.QuoteExactInputSingleParams({
tokenIn: weth,
tokenOut: token,
amountIn: amountAfterFee,
fee: POOL_FEE,
sqrtPriceLimitX96: 0
})
);
}
function quoteSell(address token, uint256 tokenAmount) external returns (uint256 ethOut, uint256 fee) {
(uint256 wethOut, , , ) = IQuoterV2(quoter).quoteExactInputSingle(
IQuoterV2.QuoteExactInputSingleParams({
tokenIn: token,
tokenOut: weth,
amountIn: tokenAmount,
fee: POOL_FEE,
sqrtPriceLimitX96: 0
})
);
fee = (wethOut * feeBps) / BPS_DENOMINATOR;
ethOut = wethOut - fee;
}
function calculateMinOutput(uint256 expectedOut, uint256 slippageBps) external pure returns (uint256 minOut) {
require(slippageBps <= 5000, "Slippage too high");
minOut = (expectedOut * (BPS_DENOMINATOR - slippageBps)) / BPS_DENOMINATOR;
}
function setPlatformFeeRecipient(address platformFeeRecipient_) external onlyOwner {
require(platformFeeRecipient_ != address(0), "Invalid address");
emit PlatformFeeRecipientUpdated(platformFeeRecipient, platformFeeRecipient_);
platformFeeRecipient = platformFeeRecipient_;
}
function setFeeBps(uint256 feeBps_) external onlyOwner {
require(feeBps_ <= MAX_FEE_BPS, "Fee too high");
emit FeeBpsUpdated(feeBps, feeBps_);
feeBps = feeBps_;
}
function rescueTokens(address token, uint256 amount) external onlyOwner {
IERC20(token).safeTransfer(owner(), amount);
}
function rescueETH() external onlyOwner {
_sendEth(owner(), address(this).balance);
}
function _transferEthFee(address token, uint256 fee) internal {
(address launchFeeRecipient, uint256 launchFee, uint256 platformFee) = _feeSplit(token, fee);
if (launchFee > 0) {
_sendEthOrWeth(launchFeeRecipient, launchFee);
}
if (platformFee > 0) {
_sendEthOrWeth(platformFeeRecipient, platformFee);
}
}
function _transferWethFee(address token, uint256 fee) internal {
(address launchFeeRecipient, uint256 launchFee, uint256 platformFee) = _feeSplit(token, fee);
if (launchFee > 0) {
IERC20(weth).safeTransfer(launchFeeRecipient, launchFee);
}
if (platformFee > 0) {
IERC20(weth).safeTransfer(platformFeeRecipient, platformFee);
}
}
function _feeSplit(address token, uint256 fee)
internal
view
returns (address launchFeeRecipient, uint256 launchFee, uint256 platformFee)
{
launchFeeRecipient = ILaunchFeeRecipientRegistry(factory).feeRecipientForToken(token);
if (launchFeeRecipient == address(0)) {
launchFeeRecipient = platformFeeRecipient;
}
launchFee = (fee * (BPS_DENOMINATOR - PLATFORM_FEE_SHARE_BPS)) / BPS_DENOMINATOR;
platformFee = fee - launchFee;
}
function _sendEth(address recipient, uint256 amount) internal {
(bool success, ) = recipient.call{value: amount}("");
require(success, "ETH transfer failed");
}
function _sendEthOrWeth(address recipient, uint256 amount) internal {
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
IWETH(weth).deposit{value: amount}();
IERC20(weth).safeTransfer(recipient, amount);
}
}
}