ReferralRouter
0xc216662891de8eaf591cfc74e1b33abc1779eafb
Verification
Verified
v0.8.20+commit.a1b79de6
Type
Contract
4,611 bytes
ABI entries
19
5 read · 7 write
License
none
Contract information
- Address
- 0xc216662891de8eaf591cfc74e1b33abc1779eafb
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.20+commit.a1b79de6
- Optimization
- Enabled
- Creator
- 0xCB962B93BD…06c2D67929
- Creation tx
- 0xcb2700bb94…bb9cd2cb6f
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (5)
PROTOCOL_REFERRAL_CODE() → bytes32
ZERO_REFERRAL_CODE() → bytes32
launchpad() → address
owner() → address
referralHandler() → address
Events (2)
OwnershipTransferredReferralHandlerSet
ABI
[
{
"inputs": [
{
"internalType": "contract Launchpad",
"name": "_launchpad",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "OwnableInvalidOwner",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "OwnableUnauthorizedAccount",
"type": "error"
},
{
"inputs": [],
"name": "ReferralRouter__InvalidToken",
"type": "error"
},
{
"inputs": [],
"name": "ReferralRouter__ZeroAddress",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "newReferralHandler",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "oldReferralHandler",
"type": "address"
}
],
"name": "ReferralHandlerSet",
"type": "event"
},
{
"inputs": [],
"name": "PROTOCOL_REFERRAL_CODE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "ZERO_REFERRAL_CODE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "minAmountOut",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "code",
"type": "bytes32"
}
],
"name": "buyExactEth",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "amountOut",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "code",
"type": "bytes32"
}
],
"name": "buyExactTokens",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "launchpad",
"outputs": [
{
"internalType": "contract Launchpad",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "referralHandler",
"outputs": [
{
"internalType": "contract ReferralHandler",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "amountOut",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "maxInput",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "code",
"type": "bytes32"
}
],
"name": "sellExactEth",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "amountIn",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minAmountOut",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "code",
"type": "bytes32"
}
],
"name": "sellExactTokens",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "contract ReferralHandler",
"name": "_referralHandler",
"type": "address"
}
],
"name": "setReferralHandler",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]Source code
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Gauge } from "./Gauge.sol";
import { Launchpad } from "./Launchpad.sol";
import { LaunchpadToken } from "./LaunchpadToken.sol";
import { ReferralHandler } from "./ReferralHandler.sol";
/**
* --------------------------------------------------------------------------------
*
* @title Referral Router
* @notice Atomically set referral and trade tokens
* @author BowTiedPickle
*
* --------------------------------------------------------------------------------
*/
contract ReferralRouter is Ownable {
////////////////////////////////////////////////////////////////////////////////
// CONSTANTS AND IMMUTABLES
////////////////////////////////////////////////////////////////////////////////
/// @dev The zero referral code is reserved for referral nonexistence
bytes32 public constant ZERO_REFERRAL_CODE = bytes32(0);
/// @dev The protocol referral code is reserved for protocol fees
bytes32 public constant PROTOCOL_REFERRAL_CODE = ~bytes32(0);
/// @notice Launchpad contract
Launchpad public immutable launchpad;
////////////////////////////////////////////////////////////////////////////////
// CONFIGURATION
////////////////////////////////////////////////////////////////////////////////
/// @notice Referral handler contract
ReferralHandler public referralHandler;
////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTOR
////////////////////////////////////////////////////////////////////////////////
/**
* @param _launchpad Launchpad contract
*/
constructor(Launchpad _launchpad) Ownable(msg.sender) {
if (address(_launchpad) == address(0)) revert ReferralRouter__ZeroAddress();
launchpad = _launchpad;
}
////////////////////////////////////////////////////////////////////////////////
// TRADE TOKENS
////////////////////////////////////////////////////////////////////////////////
/**
* @notice Buy an exact amount of tokens
* @dev Allowable slippage is defined by msg.value
* @param token Token address
* @param amountOut Amount of tokens to buy
* @param code Referral code to set, bytes32(0) to leave unchanged
*/
function buyExactTokens(address token, uint256 amountOut, bytes32 code) external payable {
address gauge = launchpad.tokenToGauge(token);
if (gauge == address(0)) revert ReferralRouter__InvalidToken();
bytes32 existingReferral = referralHandler.getReferralCode(msg.sender);
if (code != ZERO_REFERRAL_CODE && existingReferral == ZERO_REFERRAL_CODE) {
referralHandler.setReferral(msg.sender, code);
} else if (code == ZERO_REFERRAL_CODE && existingReferral == ZERO_REFERRAL_CODE) {
referralHandler.setReferral(msg.sender, PROTOCOL_REFERRAL_CODE);
}
Gauge(gauge).buyExactTokens{ value: msg.value }(msg.sender, amountOut);
}
/**
* @notice Sell an exact amount of tokens
* @param token Token address
* @param amountIn Amount of tokens to sell
* @param minAmountOut Minimum amount of ETH to receive
* @param code Referral code to set, bytes32(0) to leave unchanged
*/
function sellExactTokens(address token, uint256 amountIn, uint256 minAmountOut, bytes32 code) external {
address gauge = launchpad.tokenToGauge(token);
if (gauge == address(0)) revert ReferralRouter__InvalidToken();
bytes32 existingReferral = referralHandler.getReferralCode(msg.sender);
if (code != ZERO_REFERRAL_CODE && existingReferral == ZERO_REFERRAL_CODE) {
referralHandler.setReferral(msg.sender, code);
} else if (code == ZERO_REFERRAL_CODE && existingReferral == ZERO_REFERRAL_CODE) {
referralHandler.setReferral(msg.sender, PROTOCOL_REFERRAL_CODE);
}
LaunchpadToken(token).transferFrom(msg.sender, address(this), amountIn);
LaunchpadToken(token).approve(gauge, amountIn);
Gauge(gauge).sellExactTokens(msg.sender, amountIn, minAmountOut);
}
/**
* @notice Buy the maximum amount of tokens for an exact ETH input
* @param token Token address
* @param minAmountOut Minimum amount of tokens to receive
* @param code Referral code to set, bytes32(0) to leave unchanged
*/
function buyExactEth(address token, uint256 minAmountOut, bytes32 code) external payable {
address gauge = launchpad.tokenToGauge(token);
if (gauge == address(0)) revert ReferralRouter__InvalidToken();
bytes32 existingReferral = referralHandler.getReferralCode(msg.sender);
if (code != ZERO_REFERRAL_CODE && existingReferral == ZERO_REFERRAL_CODE) {
referralHandler.setReferral(msg.sender, code);
} else if (code == ZERO_REFERRAL_CODE && existingReferral == ZERO_REFERRAL_CODE) {
referralHandler.setReferral(msg.sender, PROTOCOL_REFERRAL_CODE);
}
Gauge(gauge).buyExactEth{ value: msg.value }(msg.sender, minAmountOut);
}
/**
* @notice Sell the minimum amount of tokens for an exact ETH output
* @param token Token address
* @param amountOut Amount of ETH to receive
* @param maxInput Maximum amount of tokens to sell
* @param code Referral code to set, bytes32(0) to leave unchanged
*/
function sellExactEth(address token, uint256 amountOut, uint256 maxInput, bytes32 code) external {
address gauge = launchpad.tokenToGauge(token);
if (gauge == address(0)) revert ReferralRouter__InvalidToken();
bytes32 existingReferral = referralHandler.getReferralCode(msg.sender);
if (code != ZERO_REFERRAL_CODE && existingReferral == ZERO_REFERRAL_CODE) {
referralHandler.setReferral(msg.sender, code);
} else if (code == ZERO_REFERRAL_CODE && existingReferral == ZERO_REFERRAL_CODE) {
referralHandler.setReferral(msg.sender, PROTOCOL_REFERRAL_CODE);
}
(uint256 amountIn, ) = Gauge(gauge).quoteSellExactEth(amountOut);
LaunchpadToken(token).transferFrom(msg.sender, address(this), amountIn);
LaunchpadToken(token).approve(gauge, amountIn);
Gauge(gauge).sellExactEth(msg.sender, amountOut, maxInput);
}
////////////////////////////////////////////////////////////////////////////////
// ADMINISTRATION
////////////////////////////////////////////////////////////////////////////////
/**
* @notice Set the referral handler
* @param _referralHandler The new referral handler
*/
function setReferralHandler(ReferralHandler _referralHandler) external onlyOwner {
if (address(_referralHandler) == address(0)) revert ReferralRouter__ZeroAddress();
emit ReferralHandlerSet(address(_referralHandler), address(referralHandler));
referralHandler = _referralHandler;
}
////////////////////////////////////////////////////////////////////////////////
// ERRORS
////////////////////////////////////////////////////////////////////////////////
error ReferralRouter__ZeroAddress();
error ReferralRouter__InvalidToken();
////////////////////////////////////////////////////////////////////////////////
// EVENTS
////////////////////////////////////////////////////////////////////////////////
event ReferralHandlerSet(address newReferralHandler, address oldReferralHandler);
}Chain explorer2587msChain node83ms