Source Code
Latest 14 from a total of 14 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap With Red Sn... | 16215357 | 35 hrs ago | IN | 0.0054 ETH | 0.00000161 | ||||
| Remove Stable To... | 16128923 | 2 days ago | IN | 0 ETH | 0.00000135 | ||||
| Swap With Red Sn... | 16116888 | 2 days ago | IN | 0 ETH | 0.00000169 | ||||
| Swap With Red Sn... | 16116860 | 2 days ago | IN | 0 ETH | 0.00000161 | ||||
| Swap With Red Sn... | 16116832 | 2 days ago | IN | 0 ETH | 0.00000162 | ||||
| Set Protocol Fee | 16040835 | 3 days ago | IN | 0 ETH | 0.00000135 | ||||
| Swap With Red Sn... | 15998573 | 4 days ago | IN | 0.002 ETH | 0.00000163 | ||||
| Swap With Red Sn... | 15998127 | 4 days ago | IN | 0.00209257 ETH | 0.00000164 | ||||
| Swap With Red Sn... | 15997790 | 4 days ago | IN | 0.00139559 ETH | 0.00000164 | ||||
| Swap With Red Sn... | 15940308 | 4 days ago | IN | 0 ETH | 0.00000162 | ||||
| Swap With Red Sn... | 15940258 | 4 days ago | IN | 0 ETH | 0.00000162 | ||||
| Swap With Red Sn... | 15939931 | 4 days ago | IN | 0.007 ETH | 0.00000164 | ||||
| Swap With Red Sn... | 15939866 | 4 days ago | IN | 0.00735728 ETH | 0.00000168 | ||||
| Set Referral Tre... | 14198400 | 24 days ago | IN | 0 ETH | 0.00000147 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 16215357 | 35 hrs ago | 0.0053865 ETH | ||||
| 16116888 | 2 days ago | 0.002004 ETH | ||||
| 16116888 | 2 days ago | 0.002004 ETH | ||||
| 16116860 | 2 days ago | 0.00137449 ETH | ||||
| 16116860 | 2 days ago | 0.00000034 ETH | ||||
| 16116860 | 2 days ago | 0.00137794 ETH | ||||
| 16116832 | 2 days ago | 0.00215834 ETH | ||||
| 16116832 | 2 days ago | 0.00000054 ETH | ||||
| 16116832 | 2 days ago | 0.00216375 ETH | ||||
| 15998573 | 4 days ago | 0.000002 ETH | ||||
| 15998573 | 4 days ago | 0.00198 ETH | ||||
| 15998127 | 4 days ago | 0.00000209 ETH | ||||
| 15998127 | 4 days ago | 0.00207164 ETH | ||||
| 15997790 | 4 days ago | 0.00000139 ETH | ||||
| 15997790 | 4 days ago | 0.00138164 ETH | ||||
| 15940308 | 4 days ago | 0.0068538 ETH | ||||
| 15940308 | 4 days ago | 0.00000692 ETH | ||||
| 15940308 | 4 days ago | 0.00692303 ETH | ||||
| 15940258 | 4 days ago | 0.00717802 ETH | ||||
| 15940258 | 4 days ago | 0.00000725 ETH | ||||
| 15940258 | 4 days ago | 0.00725053 ETH | ||||
| 15939931 | 4 days ago | 0.000007 ETH | ||||
| 15939931 | 4 days ago | 0.00693 ETH | ||||
| 15939866 | 4 days ago | 0.00000735 ETH | ||||
| 15939866 | 4 days ago | 0.00728371 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
RishuSwap
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 200 runs
Other Settings:
prague EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.26; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "./interfaces/IWETH9.sol"; import "./interfaces/IRedSnwapper.sol"; import "./interfaces/IRishuSwap.sol"; import "./interfaces/IRishuReferralTreasury.sol"; /// @title RishuSwap /// @notice A contract for performing swaps through SushiSwap's RedSnwapper aggregator with protocol fees /// @dev Handles both ERC20 and native token swaps with fee collection in WMATIC or USDT /// @custom:security-contact [email protected] contract RishuSwap is Ownable, ReentrancyGuard, Pausable, IRishuSwap { // Allowed systems addresses - using mapping to prevent DOS mapping(address => bool) public systemAddresses; // RedSnwapper contract address - this should be set to the actual RedSnwapper address address public immutable redSnwapper; // Wrapped native token address (WETH, WMATIC, WBNB, etc.) address public immutable WRAPPED_NATIVE; // Multiple stable tokens support mapping(address => bool) public stableTokens; address[] public stableTokenList; // Protocol fee in basis points (e.g., 100 for 1%) uint24 public protocolFeeBps = 100; // 1% protocol fee (100 basis points) uint256 public constant BPS_DENOMINATOR = 10_000; // Basis points denominator // Track protocol fees for each token mapping(address => uint256) internal protocolFeeBalance; // Referral treasury contract address address public referralTreasury; // Referral rewards percentage (out of protocol fee, not total swap) uint256 public referralRewardsPercentage = 1000; // 10% of protocol fee goes to referrals (1000 basis points) using SafeERC20 for IERC20; /// @notice Emitted when a swap is executed event SwapExecuted( address indexed account, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut ); /// @notice Emitted when protocol fees are claimed event FeesClaimed( address indexed owner, address indexed feeToken, uint256 amount ); /// @notice Emitted when protocol fee is collected during swap event ProtocolFeeCollected( address indexed account, // User who performed the swap address tokenIn, // Input token from swap address tokenOut, // Output token from swap address indexed feeToken, // Token used for fee collection (USDT, USDC, WMATIC, etc.) uint256 feeAmount, // Amount of fee collected uint24 feePercentage, // Fee percentage in basis points (3000 = 0.3%) address referralAddress, // Referral address uint256 referralRewardsPercentage, // Referral rewards percentage uint256 referralRewardsAmount // Referral rewards amount ); /// @notice Emitted when a stable token is added event StableTokenAdded(address indexed token); /// @notice Emitted when a stable token is removed event StableTokenRemoved(address indexed token); modifier onlyOwnerOrSystemAddress() { require( systemAddresses[msg.sender] || msg.sender == owner(), "Not an owner or system address" ); _; } /// @notice Contract constructor /// @param _redSnwapper RedSnwapper contract address /// @param _owner Address that will receive protocol fees and own the contract /// @param _wrappedNative Wrapped native token address (WETH, WMATIC, WBNB, etc.) /// @param _initialStableTokens Array of initial stable token addresses (USDT, USDC, etc.) constructor( address _redSnwapper, address _owner, address _wrappedNative, address[] memory _initialStableTokens ) Ownable(_owner) { require(_redSnwapper != address(0), "Invalid redSnwapper address"); require(_owner != address(0), "Invalid owner address"); require(_wrappedNative != address(0), "Invalid wrapped native address"); redSnwapper = _redSnwapper; WRAPPED_NATIVE = _wrappedNative; // Add initial stable tokens for (uint256 i = 0; i < _initialStableTokens.length; i++) { require( _initialStableTokens[i] != address(0), "Invalid stable token address" ); require( _initialStableTokens[i] != _wrappedNative, "Cannot add wrapped native as stable token" ); stableTokens[_initialStableTokens[i]] = true; stableTokenList.push(_initialStableTokens[i]); emit StableTokenAdded(_initialStableTokens[i]); } } /// @notice Allows the contract to receive native token receive() external payable {} /// @notice Adds a system address /// @param systemAddress System address function addSystemAddress(address systemAddress) external onlyOwner { require(systemAddress != address(0), "Invalid system address"); require( !systemAddresses[systemAddress], "System address already exists" ); systemAddresses[systemAddress] = true; } /// @notice Removes a system address /// @param systemAddress System address function removeSystemAddress(address systemAddress) external onlyOwner { require( systemAddresses[systemAddress], "System address does not exist" ); systemAddresses[systemAddress] = false; } /// @notice Sets the referral treasury contract address /// @param _referralTreasury Referral treasury contract address function setReferralTreasury(address _referralTreasury) external onlyOwner { require( _referralTreasury != address(0), "Invalid referral treasury address" ); require(_referralTreasury != address(this), "Cannot set to self"); referralTreasury = _referralTreasury; } /// @notice Sets the referral rewards percentage (out of protocol fee) /// @param _referralRewardsPercentage Referral rewards percentage in basis points function setReferralRewardsPercentage( uint256 _referralRewardsPercentage ) external onlyOwner { require( _referralRewardsPercentage <= BPS_DENOMINATOR, "Referral rewards percentage too high" ); referralRewardsPercentage = _referralRewardsPercentage; } /// @notice Executes a swap using RedSnwapper aggregator /// @param tokenIn Address of input token /// @param tokenOut Address of output token /// @param amountIn Amount of input tokens /// @param amountOutMinimum Minimum amount of output tokens to receive (after fees) /// @param txData The transaction data prepared by SushiSwap API /// @param referralAddress Referral address /// @param deadline Unix timestamp after which the transaction will revert /// @return amountOut The amount of tokens received after the swap and fees function swapWithRedSnwapper( address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutMinimum, bytes calldata txData, address referralAddress, uint256 deadline ) external payable nonReentrant whenNotPaused returns (uint256 amountOut) { // Validate deadline require(block.timestamp <= deadline, "Transaction expired"); // Validate amount require(amountIn > 0, "Amount must be greater than 0"); // Validate addresses require(tokenIn != tokenOut, "Cannot swap same token"); address feeToken = determineFeeToken(tokenIn, tokenOut); bool isInputNativeToken = tokenIn == WRAPPED_NATIVE && msg.value > 0; require( isInputNativeToken ? msg.value == amountIn : msg.value == 0, "Incorrect native token amount" ); // Calculate protocol fee from input if fee token is input uint256 protocolFee = feeToken == tokenIn ? calculateProtocolFee(amountIn) : 0; uint256 amountInToSwap = amountIn - protocolFee; // Store initial balances uint256 initialTokenOutBalance = tokenOut == WRAPPED_NATIVE ? address(this).balance : IERC20(tokenOut).balanceOf(address(this)); // Transfer tokens from user if not native if (!isInputNativeToken) { IERC20(tokenIn).safeTransferFrom( msg.sender, address(this), amountIn ); IERC20(tokenIn).forceApprove(redSnwapper, amountInToSwap); } // Execute the swap through RedSnwapper uint256 ethValue = isInputNativeToken ? amountInToSwap : 0; (bool success, ) = redSnwapper.call{value: ethValue}(txData); require(success, "RedSnwapper swap failed"); // Calculate actual amount received uint256 finalTokenOutBalance = tokenOut == WRAPPED_NATIVE ? address(this).balance : IERC20(tokenOut).balanceOf(address(this)); amountOut = finalTokenOutBalance - initialTokenOutBalance; // Check slippage BEFORE deducting fees (pure swap slippage) require(amountOut >= amountOutMinimum, "Slippage too high"); // Check FIRST // Then deduct protocol fee from output if (feeToken == tokenOut && feeToken != tokenIn) { protocolFee = calculateProtocolFee(amountOut); amountOut -= protocolFee; // Fee deducted AFTER slippage check } // Calculate referral rewards and final protocol fee uint256 finalProtocolFee = protocolFee; uint256 referralRewardsAmount = 0; address validReferralAddress = address(0); if ( referralAddress != address(0) && referralTreasury != address(0) && referralTreasury != address(this) && referralAddress != msg.sender && protocolFee > 0 ) { validReferralAddress = referralAddress; referralRewardsAmount = (protocolFee * referralRewardsPercentage) / BPS_DENOMINATOR; finalProtocolFee -= referralRewardsAmount; } // CRITICAL: Update state BEFORE external calls (reentrancy protection) protocolFeeBalance[feeToken] += finalProtocolFee; // Emit protocol fee collected event if fee > 0 if (protocolFee > 0) { emit ProtocolFeeCollected( msg.sender, tokenIn, tokenOut, feeToken, protocolFee, protocolFeeBps, validReferralAddress, referralRewardsPercentage, referralRewardsAmount ); } // Send referral rewards to treasury contract (after state update) if (referralRewardsAmount > 0) { if (feeToken == WRAPPED_NATIVE) { (bool sent, ) = referralTreasury.call{ value: referralRewardsAmount }(""); require( sent, "Failed to send native token for referral rewards" ); } else { IERC20(feeToken).safeTransfer( referralTreasury, referralRewardsAmount ); } IRishuReferralTreasury(referralTreasury).addRewardsAfterSwap( feeToken, referralRewardsAmount, validReferralAddress ); } // Send tokens to user if (tokenOut == WRAPPED_NATIVE) { (bool sent, ) = msg.sender.call{value: amountOut}(""); require(sent, "Failed to send native token"); } else { IERC20(tokenOut).safeTransfer(msg.sender, amountOut); } emit SwapExecuted(msg.sender, tokenIn, tokenOut, amountIn, amountOut); return amountOut; } /// @notice Claims accumulated protocol fees /// @param token Address of the token to claim fees for function claimFees(address token) external onlyOwner { require( token == WRAPPED_NATIVE || stableTokens[token], "Invalid fee token" ); uint256 amount = protocolFeeBalance[token]; require(amount > 0, "No fees to claim"); protocolFeeBalance[token] = 0; if (token == WRAPPED_NATIVE) { // Check if we have enough native balance first uint256 nativeBalance = address(this).balance; if (nativeBalance >= amount) { // Send directly from native balance (bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Failed to send native token"); } else { // If not enough native balance, unwrap wrapped native tokens uint256 wrappedBalance = IERC20(WRAPPED_NATIVE).balanceOf( address(this) ); require( wrappedBalance >= amount, "Insufficient wrapped native balance" ); IWETH9(WRAPPED_NATIVE).withdraw(amount); (bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Failed to send native token"); } } else { IERC20(token).safeTransfer(msg.sender, amount); } emit FeesClaimed(msg.sender, token, amount); } /// @notice Determines which token will be used to collect protocol fees /// @param tokenIn Input token address /// @param tokenOut Output token address /// @return Address of the token that will be used to collect fees function determineFeeToken( address tokenIn, address tokenOut ) public view returns (address) { if (tokenIn == WRAPPED_NATIVE || stableTokens[tokenIn]) { return tokenIn; } else if (tokenOut == WRAPPED_NATIVE || stableTokens[tokenOut]) { return tokenOut; } else { revert("Fee token must be wrapped native or stable token"); } } /// @notice Calculates protocol fee amount /// @param amount Amount to calculate fee from /// @return Protocol fee amount function calculateProtocolFee( uint256 amount ) public view returns (uint256) { return (amount * protocolFeeBps) / BPS_DENOMINATOR; } /// @notice Gets the protocol fee balance for a token /// @param token Address of the token to check /// @return Current protocol fee balance function getProtocolFeeBalance( address token ) external view returns (uint256) { return protocolFeeBalance[token]; } /// @notice Updates the protocol fee percentage /// @param _protocolFeeBps New protocol fee in basis points function setProtocolFee(uint24 _protocolFeeBps) external onlyOwner { require(_protocolFeeBps <= BPS_DENOMINATOR, "Protocol fee too high"); protocolFeeBps = _protocolFeeBps; } /// @notice Pauses the contract function pause() external onlyOwner { _pause(); } /// @notice Unpauses the contract function unpause() external onlyOwner { _unpause(); } /// @notice Adds a new stable token /// @param token Address of the stable token to add function addStableToken(address token) external onlyOwner { require(token != address(0), "Invalid token address"); require(!stableTokens[token], "Token already added"); require( token != WRAPPED_NATIVE, "Cannot add wrapped native as stable token" ); stableTokens[token] = true; stableTokenList.push(token); emit StableTokenAdded(token); } /// @notice Removes a stable token /// @param token Address of the stable token to remove function removeStableToken(address token) external onlyOwner { require(stableTokens[token], "Token not found"); stableTokens[token] = false; // Remove from array for (uint256 i = 0; i < stableTokenList.length; i++) { if (stableTokenList[i] == token) { stableTokenList[i] = stableTokenList[ stableTokenList.length - 1 ]; stableTokenList.pop(); break; } } emit StableTokenRemoved(token); } /// @notice Checks if a token is a stable token /// @param token Address of the token to check /// @return True if the token is a stable token function isStableToken(address token) external view returns (bool) { return stableTokens[token]; } /// @notice Gets all stable tokens /// @return Array of stable token addresses function getStableTokens() external view returns (address[] memory) { return stableTokenList; } /// @notice Gets the number of stable tokens /// @return Number of stable tokens function getStableTokenCount() external view returns (uint256) { return stableTokenList.length; } /// @notice Emergency function to recover stuck tokens /// @dev RESTRICTED: Only allows withdrawal of protocol fees to prevent rug pulls /// @dev For stuck tokens not tracked as protocol fees, use claimFees after accounting update /// @param token Address of the token to recover (address(0) for native token) function emergencyWithdrawProtocolFees(address token) external onlyOwner { require( token == WRAPPED_NATIVE || stableTokens[token], "Invalid fee token" ); uint256 amount = protocolFeeBalance[token]; require(amount > 0, "No protocol fees to withdraw"); protocolFeeBalance[token] = 0; if (token == WRAPPED_NATIVE) { // Check if we have enough native balance first uint256 nativeBalance = address(this).balance; if (nativeBalance >= amount) { // Send directly from native balance (bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Failed to send native token"); } else { // If not enough native balance, unwrap wrapped native tokens uint256 wrappedBalance = IERC20(WRAPPED_NATIVE).balanceOf( address(this) ); require( wrappedBalance >= amount, "Insufficient wrapped native balance" ); IWETH9(WRAPPED_NATIVE).withdraw(amount); (bool sent, ) = msg.sender.call{value: amount}(""); require(sent, "Failed to send native token"); } } else { IERC20(token).safeTransfer(msg.sender, amount); } } }
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title WETH9 Interface
/// @notice Interface for wrapped native token operations
interface IWETH9 is IERC20 {
/// @notice Deposit native token to get wrapped token
function deposit() external payable;
/// @notice Withdraw native token by burning wrapped token
/// @param wad Amount of wrapped token to burn
function withdraw(uint256 wad) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title IRedSnwapper
/// @notice Interface for SushiSwap's RedSnwapper aggregator contract
/// @dev Based on official SushiSwap documentation
interface IRedSnwapper {
/// @notice Single token swap function
/// @param tokenIn Input token contract
/// @param amountIn Amount of input tokens
/// @param recipient Address to receive output tokens
/// @param tokenOut Output token contract
/// @param amountOutMin Minimum amount of output tokens to receive
/// @param executor Executor contract to handle swap logic
/// @param executorData Data to pass to executor
/// @return amountOut Amount of output tokens received
function snwap(
IERC20 tokenIn,
uint256 amountIn,
address recipient,
IERC20 tokenOut,
uint256 amountOutMin,
address executor,
bytes calldata executorData
) external payable returns (uint256 amountOut);
struct InputToken {
IERC20 token;
uint256 amount;
}
struct OutputToken {
IERC20 token;
uint256 amountMin;
address recipient;
}
struct Executor {
address target;
bytes data;
}
/// @notice Multiple token swap function
/// @param inputTokens Array of input tokens and amounts
/// @param outputTokens Array of output tokens and minimum amounts
/// @param executors Array of executors to handle swap logic
/// @return amountOut Array of output amounts received
function snwapMultiple(
InputToken[] calldata inputTokens,
OutputToken[] calldata outputTokens,
Executor[] calldata executors
) external payable returns (uint256[] memory amountOut);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;
interface IRishuSwap {
function WRAPPED_NATIVE() external view returns (address);
function getStableTokens() external view returns (address[] memory);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;
interface IRishuReferralTreasury {
function addRewardsAfterSwap(
address token,
uint256 amount,
address referralAddress
) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"remappings": [
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"solidity-bytes-utils/=lib/solidity-bytes-utils/contracts/",
"ds-test/=lib/solidity-bytes-utils/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "prague",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_redSnwapper","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_wrappedNative","type":"address"},{"internalType":"address[]","name":"_initialStableTokens","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"feeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesClaimed","type":"event"},{"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":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":true,"internalType":"address","name":"feeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint24","name":"feePercentage","type":"uint24"},{"indexed":false,"internalType":"address","name":"referralAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"referralRewardsPercentage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"referralRewardsAmount","type":"uint256"}],"name":"ProtocolFeeCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"StableTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"StableTokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"SwapExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WRAPPED_NATIVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"addStableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"systemAddress","type":"address"}],"name":"addSystemAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateProtocolFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"claimFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"determineFeeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"emergencyWithdrawProtocolFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getProtocolFeeBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStableTokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStableTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isStableToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"protocolFeeBps","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redSnwapper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralRewardsPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"removeStableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"systemAddress","type":"address"}],"name":"removeSystemAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"_protocolFeeBps","type":"uint24"}],"name":"setProtocolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_referralRewardsPercentage","type":"uint256"}],"name":"setReferralRewardsPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referralTreasury","type":"address"}],"name":"setReferralTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stableTokenList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"stableTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"},{"internalType":"bytes","name":"txData","type":"bytes"},{"internalType":"address","name":"referralAddress","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapWithRedSnwapper","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"systemAddresses","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c06040523461042c576122928038038061001981610430565b92833981019060808183031261042c5761003281610455565b9061003f60208201610455565b61004b60408301610455565b606083015190926001600160401b03821161042c57019380601f8601121561042c578451946001600160401b038611610278578560051b90602080610091818501610430565b80998152019282010192831161042c57602001905b828210610414575050506001600160a01b03168015610401575f80546001600160a01b031981168317825560405192916001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3600180556006805462ffffff191660641790556103e86009556001600160a01b038316156103bf57506001600160a01b03811691821561037a5760805260a0525f5b8251811015610328576001600160a01b036101638285610469565b5116156102e357816001600160a01b0361017d8386610469565b51161461028c576001600160a01b036101968285610469565b51165f908152600460205260409020805460ff191660011790556001600160a01b036101c28285610469565b51169060055491680100000000000000008310156102785760018301806005558310156102645760055f527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db090920180546001600160a01b0319169092179091556001906001600160a01b036102388286610469565b51167fde716bd3579dfb42433ce078125ac4e8774aae153fc4e7434b4f1d2c2460d2335f80a201610148565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74206164642077726170706564206e617469766520617320737461604482015268313632903a37b5b2b760b91b6064820152608490fd5b60405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420737461626c6520746f6b656e2061646472657373000000006044820152606490fd5b604051611e14908161047e82396080518181816102170152818161051b01526109a7015260a05181818161035a0152818161046601528181611180015281816113900152818161183f0152611bec0152f35b60405162461bcd60e51b815260206004820152601e60248201527f496e76616c69642077726170706564206e6174697665206164647265737300006044820152606490fd5b62461bcd60e51b815260206004820152601b60248201527f496e76616c696420726564536e776170706572206164647265737300000000006044820152606490fd5b631e4fbdf760e01b5f525f60045260245ffd5b6020809161042184610455565b8152019101906100a6565b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761027857604052565b51906001600160a01b038216820361042c57565b80518210156102645760209160051b01019056fe608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c90816303fe714314611a165750806315a0ea6a1461180f57806323da74b8146117d0578063315af6361461175357806335659fb8146117305780633f4ba83a146116c857806342b60b031461164557806348406a0b146116845780634e34f26b14611645578063506af8fc1461160657806358430b191461152a5780635c975abb146115075780635e6b57dd14611347578063690b91ac14611150578063715018a6146110f65780637cdea7bf146110bd5780637feedaa1146110395780638456cb5914610fde57806384e96ec414610fb55780638da5cb5b14610f8e5780639c7c270c14610f5b5780639e9f5e2d14610dc0578063a195c25314610cf8578063a494003e14610c5d578063af9d19a9146103a7578063c111d2e614610389578063d999984d14610344578063e1a4521814610327578063e65052ad14610246578063f1281c3f146102015763f2fde38b0361000f57346101fe5760203660031901126101fe57610192611a30565b61019a611d07565b6001600160a01b031680156101ea5781546001600160a01b03198116821783556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b631e4fbdf760e01b82526004829052602482fd5b80fd5b50346101fe57806003193601126101fe576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346101fe5760203660031901126101fe57610260611a30565b610268611d07565b6001600160a01b031680156102e957808252600360205260ff6040832054166102a4578152600360205260408120805460ff1916600117905580f35b60405162461bcd60e51b815260206004820152601d60248201527f53797374656d206164647265737320616c7265616479206578697374730000006044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642073797374656d206164647265737360501b6044820152606490fd5b50346101fe57806003193601126101fe5760206040516127108152f35b50346101fe57806003193601126101fe576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346101fe57806003193601126101fe576020600554604051908152f35b5060e03660031901126101fe576103bc611a30565b6103c4611a46565b608435919060443567ffffffffffffffff8411610c595736602385011215610c595783600401359367ffffffffffffffff85116106cf5736602486830101116106cf5760a435906001600160a01b03821690818303610c5557600260015414610c46576002600155610434611d6b565b60c4354211610c0b578315610bc6576001600160a01b038581169690811695868814610b885761046391611be1565b927f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031686811480610b7f575b8015610b78578634145b15610b3357889560018060a01b031693878c8a87149c8d5f14610b2c576127106104d262ffffff6006541685611cd3565b04945b6104df8685611cfa565b908d888d149c8d5f14610a955750918495969160249347985b821561096b575b50501561096357925b80604051938493018337810184815203917f00000000000000000000000000000000000000000000000000000000000000005af1610544611b56565b501561091e5786156108a75761055a9047611cfa565b996064358b1061086e578985149081610865575b5061083f575b808b938c96801515908161082a575b81610814575b81610809575b5080610800575b6107d8575b50848c52600760205260408c2080549182018092116107c4575583908061075b575b50508161063a575b50505050946020955f14610629578080806105ec9388335af16105e6611b56565b50611b95565b60405190815283858201527f764f0dc063c06f32d89a3f3af80c0db4be8a090901f589a478b447e0a51f09f160403392a460018055604051908152f35b50610635843385611d2d565b6105ec565b89908303610740578080808460018060a01b03600854165af161065b611b56565b50156106e25788915b6008546001600160a01b031690813b156106de57836064926040519687958694638d7ce9cf60e01b86526004860152602485015260018060a01b031660448401525af180156106d3576106ba575b8080806105c5565b6106c5878092611ac8565b6106cf575f6106b2565b8580fd5b6040513d89823e3d90fd5b8380fd5b60405162461bcd60e51b815260206004820152603060248201527f4661696c656420746f2073656e64206e617469766520746f6b656e20666f722060448201526f726566657272616c207265776172647360801b6064820152608490fd5b916107568260018060a01b036008541683611d2d565b610664565b62ffffff6006541660095490604051928b84528c60208501526040840152606083015260018060a01b038716608083015260a08201528360c08201527f6b26910d1859e08aec2ccd54c64c4cb23688558e3a0747da0136bef6d7a1d11260e03392a3825f6105bd565b634e487b7160e01b8d52601160045260248dfd5b929550509150926127106107ee60095484611cd3565b04916107fa8382611cfa565b5f61059b565b50821515610596565b90503314155f61058f565b6008546001600160a01b03163014159150610589565b6008546001600160a01b031615159150610583565b5061085f61271061085762ffffff600654168c611cd3565b04809a611cfa565b98610574565b9050155f61056e565b60405162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b6044820152606490fd5b6040516370a0823160e01b8152306004820152906020826024818e5afa8015610913578d906108db575b61055a9250611cfa565b506020823d60201161090b575b816108f560209383611ac8565b810103126109075761055a91516108d1565b5f80fd5b3d91506108e8565b6040513d8f823e3d90fd5b60405162461bcd60e51b815260206004820152601760248201527f526564536e7761707065722073776170206661696c65640000000000000000006044820152606490fd5b508392610508565b6109a590604051906323b872dd60e01b6020830152338883015230604483015260648201526064815261099f608482611ac8565b82611d86565b7f0000000000000000000000000000000000000000000000000000000000000000906040519060208981840163095ea7b360e01b8152610a0f85610a018a898e840160209093929193604081019460018060a01b031681520152565b03601f198101875286611ac8565b84519082855af189513d82610a79575b505015610a30575b9150508f6104ff565b60405163095ea7b360e01b60208201526001600160a01b039093168784015260448084018a90528352610a7192610a6c9061099f606482611ac8565b611d86565b8f5f81610a27565b909150610a8d5750803b15155b5f80610a1f565b600114610a86565b6040516370a0823160e01b8152306004820152965060209150869060249082905afa948515610b21578d958f918691610ad9575b50916024939186979893986104f8565b939650505092506020813d602011610b19575b81610af960209383611ac8565b81010312610907578f93948c9585948f6024945191939897509193610ac9565b3d9150610aec565b6040513d86823e3d90fd5b81946104d5565b60405162461bcd60e51b815260206004820152601d60248201527f496e636f7272656374206e617469766520746f6b656e20616d6f756e740000006044820152606490fd5b34156104a1565b50341515610497565b60405162461bcd60e51b815260206004820152601660248201527521b0b73737ba1039bbb0b81039b0b6b2903a37b5b2b760511b6044820152606490fd5b60405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606490fd5b60405162461bcd60e51b8152602060048201526013602482015272151c985b9cd858dd1a5bdb88195e1c1a5c9959606a1b6044820152606490fd5b633ee5aeb560e01b8852600488fd5b8780fd5b8480fd5b50346101fe5760203660031901126101fe57610c77611a30565b610c7f611d07565b6001600160a01b03168082526003602052604082205460ff1615610cb3578152600360205260408120805460ff1916905580f35b60405162461bcd60e51b815260206004820152601d60248201527f53797374656d206164647265737320646f6573206e6f742065786973740000006044820152606490fd5b50346101fe57806003193601126101fe5760405180602060055491828152018091600585527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db090855b818110610da15750505082610d57910383611ac8565b604051928392602084019060208552518091526040840192915b818110610d7f575050500390f35b82516001600160a01b0316845285945060209384019390920191600101610d71565b82546001600160a01b0316845260209093019260019283019201610d41565b50346101fe5760203660031901126101fe57610dda611a30565b610de2611d07565b6001600160a01b03168082526004602052604082205460ff1615610f2457808252600460205260408220805460ff19169055815b60055480821015610f1d5782610e2b83611a5c565b905460039190911b1c6001600160a01b031614610e4b5750600101610e16565b5f198101908111610f095790610e7e610e66610ea293611a5c565b905460039190911b1c6001600160a01b031691611a5c565b81546001600160a01b0393841660039290921b91821b9390911b1916919091179055565b6005548015610ef5575f1901610eb781611a5c565b81549060018060a01b039060031b1b191690556005555b7f01a0e3c9070d37feb67c0b9056c01cd57c5f438cd4380dfb46de4c2fe389e0ca8280a280f35b634e487b7160e01b83526031600452602483fd5b634e487b7160e01b84526011600452602484fd5b5050610ece565b60405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881b9bdd08199bdd5b99608a1b6044820152606490fd5b50346101fe5760203660031901126101fe576020612710610f8562ffffff60065416600435611cd3565b04604051908152f35b50346101fe57806003193601126101fe57546040516001600160a01b039091168152602090f35b50346101fe57806003193601126101fe576008546040516001600160a01b039091168152602090f35b50346101fe57806003193601126101fe57610ff7611d07565b610fff611d6b565b600160ff1960025416176002557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b50346101fe5760203660031901126101fe5760043562ffffff81168091036110b957611063611d07565b612710811161107c5762ffffff19600654161760065580f35b60405162461bcd60e51b81526020600482015260156024820152740a0e4dee8dec6ded840cccaca40e8dede40d0d2ced605b1b6044820152606490fd5b5080fd5b50346101fe5760203660031901126101fe576020906040906001600160a01b036110e5611a30565b168152600783522054604051908152f35b50346101fe57806003193601126101fe5761110f611d07565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101fe5760203660031901126101fe5761116a611a30565b611172611d07565b6001600160a01b03908116907f00000000000000000000000000000000000000000000000000000000000000001681811490818015611331575b6111b590611a88565b828452600760205260408420549283156112ec57849281845260076020528360408120555f146112de57504783116111fd57508080806111fa94335af16105e6611b56565b80f35b6040516370a0823160e01b8152306004820152602081602481855afa80156112d35784918491611298575b5090611235911015611afe565b803b156110b957818091602460405180948193632e1a7d4d60e01b83528860048401525af1801561128d57611278575b508080806111fa94335af16105e6611b56565b611283828092611ac8565b6101fe575f611265565b6040513d84823e3d90fd5b935050506020823d6020116112cb575b816112b560209383611ac8565b8101031261090757611235838593519091611228565b3d91506112a8565b6040513d85823e3d90fd5b6111fa939250339150611d2d565b60405162461bcd60e51b815260206004820152601c60248201527f4e6f2070726f746f636f6c206665657320746f207769746864726177000000006044820152606490fd5b508284526004602052604084205460ff166111ac565b50346101fe5760203660031901126101fe57611361611a30565b611369611d07565b6001600160a01b0381169081156114ca57818352600460205260ff60408420541661148f577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316821461143857818352600460205260408320805460ff19166001179055600554680100000000000000008110156114245790610e7e8260016113fd9401600555611a5c565b7fde716bd3579dfb42433ce078125ac4e8774aae153fc4e7434b4f1d2c2460d2338280a280f35b634e487b7160e01b84526041600452602484fd5b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74206164642077726170706564206e617469766520617320737461604482015268313632903a37b5b2b760b91b6064820152608490fd5b60405162461bcd60e51b8152602060048201526013602482015272151bdad95b88185b1c9958591e481859191959606a1b6044820152606490fd5b60405162461bcd60e51b8152602060048201526015602482015274496e76616c696420746f6b656e206164647265737360581b6044820152606490fd5b50346101fe57806003193601126101fe57602060ff600254166040519015158152f35b50346101fe5760203660031901126101fe57611544611a30565b61154c611d07565b6001600160a01b031680156115b75730811461157d576bffffffffffffffffffffffff60a01b600854161760085580f35b60405162461bcd60e51b815260206004820152601260248201527121b0b73737ba1039b2ba103a379039b2b63360711b6044820152606490fd5b60405162461bcd60e51b815260206004820152602160248201527f496e76616c696420726566657272616c207472656173757279206164647265736044820152607360f81b6064820152608490fd5b50346101fe5760403660031901126101fe576020611633611625611a30565b61162d611a46565b90611be1565b6040516001600160a01b039091168152f35b50346101fe5760203660031901126101fe5760209060ff906040906001600160a01b03611670611a30565b168152600484522054166040519015158152f35b50346101fe5760203660031901126101fe57600435906005548210156101fe5760206116af83611a5c565b905460405160039290921b1c6001600160a01b03168152f35b50346101fe57806003193601126101fe576116e1611d07565b60025460ff8116156117215760ff19166002557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a180f35b638dfc202b60e01b8252600482fd5b50346101fe57806003193601126101fe57602062ffffff60065416604051908152f35b50346101fe5760203660031901126101fe57600435611770611d07565b612710811161177f5760095580f35b60405162461bcd60e51b8152602060048201526024808201527f526566657272616c20726577617264732070657263656e7461676520746f6f206044820152630d0d2ced60e31b6064820152608490fd5b50346101fe5760203660031901126101fe5760209060ff906040906001600160a01b036117fb611a30565b168152600384522054166040519015158152f35b503461090757602036600319011261090757611829611a30565b611831611d07565b6001600160a01b03908116907f000000000000000000000000000000000000000000000000000000000000000016818114908180156119ff575b61187490611a88565b825f52600760205260405f20549182156119c7575f84815260076020526040812055156119bb574782116118e557506118b68380808085335af16105e6611b56565b6040519081527ffe3464cd748424446c37877c28ce5b700222c5bc9f90d908afcc4e5cb22707ff60203392a380f35b6040516370a0823160e01b8152306004820152602081602481855afa801561197a5783905f90611985575b61191c92501015611afe565b803b15610907575f8091602460405180948193632e1a7d4d60e01b83528760048401525af1801561197a57611965575b506119608380808085335af16105e6611b56565b6118b6565b6119729193505f90611ac8565b5f915f61194c565b6040513d5f823e3d90fd5b50506020813d6020116119b3575b816119a060209383611ac8565b81010312610907578261191c9151611910565b3d9150611993565b50611960813384611d2d565b60405162461bcd60e51b815260206004820152601060248201526f4e6f206665657320746f20636c61696d60801b6044820152606490fd5b505f8381526004602052604090205460ff1661186b565b34610907575f366003190112610907576020906009548152f35b600435906001600160a01b038216820361090757565b602435906001600160a01b038216820361090757565b600554811015611a745760055f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b15611a8f57565b60405162461bcd60e51b815260206004820152601160248201527024b73b30b634b2103332b2903a37b5b2b760791b6044820152606490fd5b90601f8019910116810190811067ffffffffffffffff821117611aea57604052565b634e487b7160e01b5f52604160045260245ffd5b15611b0557565b60405162461bcd60e51b815260206004820152602360248201527f496e73756666696369656e742077726170706564206e61746976652062616c616044820152626e636560e81b6064820152608490fd5b3d15611b90573d9067ffffffffffffffff8211611aea5760405191611b85601f8201601f191660200184611ac8565b82523d5f602084013e565b606090565b15611b9c57565b60405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2073656e64206e617469766520746f6b656e00000000006044820152606490fd5b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316808214908115611cbc575b5015611c2657505090565b9091506001600160a01b038216908114908115611ca5575b5015611c475790565b60405162461bcd60e51b815260206004820152603060248201527f46656520746f6b656e206d7573742062652077726170706564206e617469766560448201526f1037b91039ba30b13632903a37b5b2b760811b6064820152608490fd5b90505f52600460205260ff60405f2054165f611c3e565b90505f52600460205260ff60405f2054165f611c1b565b81810292918115918404141715611ce657565b634e487b7160e01b5f52601160045260245ffd5b91908203918211611ce657565b5f546001600160a01b03163303611d1a57565b63118cdaa760e01b5f523360045260245ffd5b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152611d6991610a6c606483611ac8565b565b60ff60025416611d7757565b63d93c066560e01b5f5260045ffd5b905f602091828151910182855af11561197a575f513d611dd557506001600160a01b0381163b155b611db55750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b60011415611dae56fea2646970667358221220d97cf4451f8aec431ed0b9f1e29a0dc93f47e44880f8904a24642186cf539d1264736f6c634300081e0033000000000000000000000000ac4c6e212a361c968f1725b4d055b47e63f80b75000000000000000000000000c272fa7d73e8ed66e65a6281570d3788bea5e7a4000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab62000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000002dca96907fde857dd3d816880a0df407eeb2d2f2000000000000000000000000203a662b0bd271a6ed5a60edfbd04bfce608fd36
Deployed Bytecode
0x608080604052600436101561001c575b50361561001a575f80fd5b005b5f905f3560e01c90816303fe714314611a165750806315a0ea6a1461180f57806323da74b8146117d0578063315af6361461175357806335659fb8146117305780633f4ba83a146116c857806342b60b031461164557806348406a0b146116845780634e34f26b14611645578063506af8fc1461160657806358430b191461152a5780635c975abb146115075780635e6b57dd14611347578063690b91ac14611150578063715018a6146110f65780637cdea7bf146110bd5780637feedaa1146110395780638456cb5914610fde57806384e96ec414610fb55780638da5cb5b14610f8e5780639c7c270c14610f5b5780639e9f5e2d14610dc0578063a195c25314610cf8578063a494003e14610c5d578063af9d19a9146103a7578063c111d2e614610389578063d999984d14610344578063e1a4521814610327578063e65052ad14610246578063f1281c3f146102015763f2fde38b0361000f57346101fe5760203660031901126101fe57610192611a30565b61019a611d07565b6001600160a01b031680156101ea5781546001600160a01b03198116821783556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b631e4fbdf760e01b82526004829052602482fd5b80fd5b50346101fe57806003193601126101fe576040517f000000000000000000000000ac4c6e212a361c968f1725b4d055b47e63f80b756001600160a01b03168152602090f35b50346101fe5760203660031901126101fe57610260611a30565b610268611d07565b6001600160a01b031680156102e957808252600360205260ff6040832054166102a4578152600360205260408120805460ff1916600117905580f35b60405162461bcd60e51b815260206004820152601d60248201527f53797374656d206164647265737320616c7265616479206578697374730000006044820152606490fd5b60405162461bcd60e51b8152602060048201526016602482015275496e76616c69642073797374656d206164647265737360501b6044820152606490fd5b50346101fe57806003193601126101fe5760206040516127108152f35b50346101fe57806003193601126101fe576040517f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab626001600160a01b03168152602090f35b50346101fe57806003193601126101fe576020600554604051908152f35b5060e03660031901126101fe576103bc611a30565b6103c4611a46565b608435919060443567ffffffffffffffff8411610c595736602385011215610c595783600401359367ffffffffffffffff85116106cf5736602486830101116106cf5760a435906001600160a01b03821690818303610c5557600260015414610c46576002600155610434611d6b565b60c4354211610c0b578315610bc6576001600160a01b038581169690811695868814610b885761046391611be1565b927f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab626001600160a01b031686811480610b7f575b8015610b78578634145b15610b3357889560018060a01b031693878c8a87149c8d5f14610b2c576127106104d262ffffff6006541685611cd3565b04945b6104df8685611cfa565b908d888d149c8d5f14610a955750918495969160249347985b821561096b575b50501561096357925b80604051938493018337810184815203917f000000000000000000000000ac4c6e212a361c968f1725b4d055b47e63f80b755af1610544611b56565b501561091e5786156108a75761055a9047611cfa565b996064358b1061086e578985149081610865575b5061083f575b808b938c96801515908161082a575b81610814575b81610809575b5080610800575b6107d8575b50848c52600760205260408c2080549182018092116107c4575583908061075b575b50508161063a575b50505050946020955f14610629578080806105ec9388335af16105e6611b56565b50611b95565b60405190815283858201527f764f0dc063c06f32d89a3f3af80c0db4be8a090901f589a478b447e0a51f09f160403392a460018055604051908152f35b50610635843385611d2d565b6105ec565b89908303610740578080808460018060a01b03600854165af161065b611b56565b50156106e25788915b6008546001600160a01b031690813b156106de57836064926040519687958694638d7ce9cf60e01b86526004860152602485015260018060a01b031660448401525af180156106d3576106ba575b8080806105c5565b6106c5878092611ac8565b6106cf575f6106b2565b8580fd5b6040513d89823e3d90fd5b8380fd5b60405162461bcd60e51b815260206004820152603060248201527f4661696c656420746f2073656e64206e617469766520746f6b656e20666f722060448201526f726566657272616c207265776172647360801b6064820152608490fd5b916107568260018060a01b036008541683611d2d565b610664565b62ffffff6006541660095490604051928b84528c60208501526040840152606083015260018060a01b038716608083015260a08201528360c08201527f6b26910d1859e08aec2ccd54c64c4cb23688558e3a0747da0136bef6d7a1d11260e03392a3825f6105bd565b634e487b7160e01b8d52601160045260248dfd5b929550509150926127106107ee60095484611cd3565b04916107fa8382611cfa565b5f61059b565b50821515610596565b90503314155f61058f565b6008546001600160a01b03163014159150610589565b6008546001600160a01b031615159150610583565b5061085f61271061085762ffffff600654168c611cd3565b04809a611cfa565b98610574565b9050155f61056e565b60405162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b6044820152606490fd5b6040516370a0823160e01b8152306004820152906020826024818e5afa8015610913578d906108db575b61055a9250611cfa565b506020823d60201161090b575b816108f560209383611ac8565b810103126109075761055a91516108d1565b5f80fd5b3d91506108e8565b6040513d8f823e3d90fd5b60405162461bcd60e51b815260206004820152601760248201527f526564536e7761707065722073776170206661696c65640000000000000000006044820152606490fd5b508392610508565b6109a590604051906323b872dd60e01b6020830152338883015230604483015260648201526064815261099f608482611ac8565b82611d86565b7f000000000000000000000000ac4c6e212a361c968f1725b4d055b47e63f80b75906040519060208981840163095ea7b360e01b8152610a0f85610a018a898e840160209093929193604081019460018060a01b031681520152565b03601f198101875286611ac8565b84519082855af189513d82610a79575b505015610a30575b9150508f6104ff565b60405163095ea7b360e01b60208201526001600160a01b039093168784015260448084018a90528352610a7192610a6c9061099f606482611ac8565b611d86565b8f5f81610a27565b909150610a8d5750803b15155b5f80610a1f565b600114610a86565b6040516370a0823160e01b8152306004820152965060209150869060249082905afa948515610b21578d958f918691610ad9575b50916024939186979893986104f8565b939650505092506020813d602011610b19575b81610af960209383611ac8565b81010312610907578f93948c9585948f6024945191939897509193610ac9565b3d9150610aec565b6040513d86823e3d90fd5b81946104d5565b60405162461bcd60e51b815260206004820152601d60248201527f496e636f7272656374206e617469766520746f6b656e20616d6f756e740000006044820152606490fd5b34156104a1565b50341515610497565b60405162461bcd60e51b815260206004820152601660248201527521b0b73737ba1039bbb0b81039b0b6b2903a37b5b2b760511b6044820152606490fd5b60405162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e20300000006044820152606490fd5b60405162461bcd60e51b8152602060048201526013602482015272151c985b9cd858dd1a5bdb88195e1c1a5c9959606a1b6044820152606490fd5b633ee5aeb560e01b8852600488fd5b8780fd5b8480fd5b50346101fe5760203660031901126101fe57610c77611a30565b610c7f611d07565b6001600160a01b03168082526003602052604082205460ff1615610cb3578152600360205260408120805460ff1916905580f35b60405162461bcd60e51b815260206004820152601d60248201527f53797374656d206164647265737320646f6573206e6f742065786973740000006044820152606490fd5b50346101fe57806003193601126101fe5760405180602060055491828152018091600585527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db090855b818110610da15750505082610d57910383611ac8565b604051928392602084019060208552518091526040840192915b818110610d7f575050500390f35b82516001600160a01b0316845285945060209384019390920191600101610d71565b82546001600160a01b0316845260209093019260019283019201610d41565b50346101fe5760203660031901126101fe57610dda611a30565b610de2611d07565b6001600160a01b03168082526004602052604082205460ff1615610f2457808252600460205260408220805460ff19169055815b60055480821015610f1d5782610e2b83611a5c565b905460039190911b1c6001600160a01b031614610e4b5750600101610e16565b5f198101908111610f095790610e7e610e66610ea293611a5c565b905460039190911b1c6001600160a01b031691611a5c565b81546001600160a01b0393841660039290921b91821b9390911b1916919091179055565b6005548015610ef5575f1901610eb781611a5c565b81549060018060a01b039060031b1b191690556005555b7f01a0e3c9070d37feb67c0b9056c01cd57c5f438cd4380dfb46de4c2fe389e0ca8280a280f35b634e487b7160e01b83526031600452602483fd5b634e487b7160e01b84526011600452602484fd5b5050610ece565b60405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881b9bdd08199bdd5b99608a1b6044820152606490fd5b50346101fe5760203660031901126101fe576020612710610f8562ffffff60065416600435611cd3565b04604051908152f35b50346101fe57806003193601126101fe57546040516001600160a01b039091168152602090f35b50346101fe57806003193601126101fe576008546040516001600160a01b039091168152602090f35b50346101fe57806003193601126101fe57610ff7611d07565b610fff611d6b565b600160ff1960025416176002557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b50346101fe5760203660031901126101fe5760043562ffffff81168091036110b957611063611d07565b612710811161107c5762ffffff19600654161760065580f35b60405162461bcd60e51b81526020600482015260156024820152740a0e4dee8dec6ded840cccaca40e8dede40d0d2ced605b1b6044820152606490fd5b5080fd5b50346101fe5760203660031901126101fe576020906040906001600160a01b036110e5611a30565b168152600783522054604051908152f35b50346101fe57806003193601126101fe5761110f611d07565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b50346101fe5760203660031901126101fe5761116a611a30565b611172611d07565b6001600160a01b03908116907f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab621681811490818015611331575b6111b590611a88565b828452600760205260408420549283156112ec57849281845260076020528360408120555f146112de57504783116111fd57508080806111fa94335af16105e6611b56565b80f35b6040516370a0823160e01b8152306004820152602081602481855afa80156112d35784918491611298575b5090611235911015611afe565b803b156110b957818091602460405180948193632e1a7d4d60e01b83528860048401525af1801561128d57611278575b508080806111fa94335af16105e6611b56565b611283828092611ac8565b6101fe575f611265565b6040513d84823e3d90fd5b935050506020823d6020116112cb575b816112b560209383611ac8565b8101031261090757611235838593519091611228565b3d91506112a8565b6040513d85823e3d90fd5b6111fa939250339150611d2d565b60405162461bcd60e51b815260206004820152601c60248201527f4e6f2070726f746f636f6c206665657320746f207769746864726177000000006044820152606490fd5b508284526004602052604084205460ff166111ac565b50346101fe5760203660031901126101fe57611361611a30565b611369611d07565b6001600160a01b0381169081156114ca57818352600460205260ff60408420541661148f577f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab626001600160a01b0316821461143857818352600460205260408320805460ff19166001179055600554680100000000000000008110156114245790610e7e8260016113fd9401600555611a5c565b7fde716bd3579dfb42433ce078125ac4e8774aae153fc4e7434b4f1d2c2460d2338280a280f35b634e487b7160e01b84526041600452602484fd5b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74206164642077726170706564206e617469766520617320737461604482015268313632903a37b5b2b760b91b6064820152608490fd5b60405162461bcd60e51b8152602060048201526013602482015272151bdad95b88185b1c9958591e481859191959606a1b6044820152606490fd5b60405162461bcd60e51b8152602060048201526015602482015274496e76616c696420746f6b656e206164647265737360581b6044820152606490fd5b50346101fe57806003193601126101fe57602060ff600254166040519015158152f35b50346101fe5760203660031901126101fe57611544611a30565b61154c611d07565b6001600160a01b031680156115b75730811461157d576bffffffffffffffffffffffff60a01b600854161760085580f35b60405162461bcd60e51b815260206004820152601260248201527121b0b73737ba1039b2ba103a379039b2b63360711b6044820152606490fd5b60405162461bcd60e51b815260206004820152602160248201527f496e76616c696420726566657272616c207472656173757279206164647265736044820152607360f81b6064820152608490fd5b50346101fe5760403660031901126101fe576020611633611625611a30565b61162d611a46565b90611be1565b6040516001600160a01b039091168152f35b50346101fe5760203660031901126101fe5760209060ff906040906001600160a01b03611670611a30565b168152600484522054166040519015158152f35b50346101fe5760203660031901126101fe57600435906005548210156101fe5760206116af83611a5c565b905460405160039290921b1c6001600160a01b03168152f35b50346101fe57806003193601126101fe576116e1611d07565b60025460ff8116156117215760ff19166002557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a180f35b638dfc202b60e01b8252600482fd5b50346101fe57806003193601126101fe57602062ffffff60065416604051908152f35b50346101fe5760203660031901126101fe57600435611770611d07565b612710811161177f5760095580f35b60405162461bcd60e51b8152602060048201526024808201527f526566657272616c20726577617264732070657263656e7461676520746f6f206044820152630d0d2ced60e31b6064820152608490fd5b50346101fe5760203660031901126101fe5760209060ff906040906001600160a01b036117fb611a30565b168152600384522054166040519015158152f35b503461090757602036600319011261090757611829611a30565b611831611d07565b6001600160a01b03908116907f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab6216818114908180156119ff575b61187490611a88565b825f52600760205260405f20549182156119c7575f84815260076020526040812055156119bb574782116118e557506118b68380808085335af16105e6611b56565b6040519081527ffe3464cd748424446c37877c28ce5b700222c5bc9f90d908afcc4e5cb22707ff60203392a380f35b6040516370a0823160e01b8152306004820152602081602481855afa801561197a5783905f90611985575b61191c92501015611afe565b803b15610907575f8091602460405180948193632e1a7d4d60e01b83528760048401525af1801561197a57611965575b506119608380808085335af16105e6611b56565b6118b6565b6119729193505f90611ac8565b5f915f61194c565b6040513d5f823e3d90fd5b50506020813d6020116119b3575b816119a060209383611ac8565b81010312610907578261191c9151611910565b3d9150611993565b50611960813384611d2d565b60405162461bcd60e51b815260206004820152601060248201526f4e6f206665657320746f20636c61696d60801b6044820152606490fd5b505f8381526004602052604090205460ff1661186b565b34610907575f366003190112610907576020906009548152f35b600435906001600160a01b038216820361090757565b602435906001600160a01b038216820361090757565b600554811015611a745760055f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b15611a8f57565b60405162461bcd60e51b815260206004820152601160248201527024b73b30b634b2103332b2903a37b5b2b760791b6044820152606490fd5b90601f8019910116810190811067ffffffffffffffff821117611aea57604052565b634e487b7160e01b5f52604160045260245ffd5b15611b0557565b60405162461bcd60e51b815260206004820152602360248201527f496e73756666696369656e742077726170706564206e61746976652062616c616044820152626e636560e81b6064820152608490fd5b3d15611b90573d9067ffffffffffffffff8211611aea5760405191611b85601f8201601f191660200184611ac8565b82523d5f602084013e565b606090565b15611b9c57565b60405162461bcd60e51b815260206004820152601b60248201527f4661696c656420746f2073656e64206e617469766520746f6b656e00000000006044820152606490fd5b906001600160a01b037f000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab628116908316808214908115611cbc575b5015611c2657505090565b9091506001600160a01b038216908114908115611ca5575b5015611c475790565b60405162461bcd60e51b815260206004820152603060248201527f46656520746f6b656e206d7573742062652077726170706564206e617469766560448201526f1037b91039ba30b13632903a37b5b2b760811b6064820152608490fd5b90505f52600460205260ff60405f2054165f611c3e565b90505f52600460205260ff60405f2054165f611c1b565b81810292918115918404141715611ce657565b634e487b7160e01b5f52601160045260245ffd5b91908203918211611ce657565b5f546001600160a01b03163303611d1a57565b63118cdaa760e01b5f523360045260245ffd5b60405163a9059cbb60e01b60208201526001600160a01b03929092166024830152604480830193909352918152611d6991610a6c606483611ac8565b565b60ff60025416611d7757565b63d93c066560e01b5f5260045ffd5b905f602091828151910182855af11561197a575f513d611dd557506001600160a01b0381163b155b611db55750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b60011415611dae56fea2646970667358221220d97cf4451f8aec431ed0b9f1e29a0dc93f47e44880f8904a24642186cf539d1264736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ac4c6e212a361c968f1725b4d055b47e63f80b75000000000000000000000000c272fa7d73e8ed66e65a6281570d3788bea5e7a4000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab62000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000002dca96907fde857dd3d816880a0df407eeb2d2f2000000000000000000000000203a662b0bd271a6ed5a60edfbd04bfce608fd36
-----Decoded View---------------
Arg [0] : _redSnwapper (address): 0xAC4c6e212A361c968F1725b4d055b47E63F80b75
Arg [1] : _owner (address): 0xC272Fa7D73e8ed66E65a6281570D3788BEA5E7A4
Arg [2] : _wrappedNative (address): 0xEE7D8BCFb72bC1880D0Cf19822eB0A2e6577aB62
Arg [3] : _initialStableTokens (address[]): 0x2DCa96907fde857dd3D816880A0df407eeB2D2F2,0x203A662b0BD271A6ed5a60EdFbd04bFce608FD36
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000ac4c6e212a361c968f1725b4d055b47e63f80b75
Arg [1] : 000000000000000000000000c272fa7d73e8ed66e65a6281570d3788bea5e7a4
Arg [2] : 000000000000000000000000ee7d8bcfb72bc1880d0cf19822eb0a2e6577ab62
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [5] : 0000000000000000000000002dca96907fde857dd3d816880a0df407eeb2d2f2
Arg [6] : 000000000000000000000000203a662b0bd271a6ed5a60edfbd04bfce608fd36
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| KATANA | 100.00% | $3,243.18 | 0.00032764 | $1.06 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.