TokenChwomper
0x2ec2560cba6aeb2fe13bdb381700b505f5e9e4e8
Verification
Verified
v0.8.20+commit.a1b79de6
Type
Contract
6,374 bytes
ABI entries
22
5 read · 10 write
License
none
Contract information
- Address
- 0x2ec2560cba6aeb2fe13bdb381700b505f5e9e4e8
- Chain
- Robinhood Chain (4663)
- Compiler
- v0.8.20+commit.a1b79de6
- Optimization
- Enabled
- Creator
- 0x6219D85BB1…1a2aa63318
- Creation tx
- 0xd5e9d9cecf…82641111fa
Token
Not a token
This contract does not expose ERC-20 metadata.
Read contract (5)
owner() → address
pendingOwner() → address
redSnwapper() → address
trusted(address) → bool
weth() → address
Events (3)
OwnershipTransferStartedOwnershipTransferredSetTrusted
ABI
[
{
"inputs": [
{
"internalType": "address",
"name": "_operator",
"type": "address"
},
{
"internalType": "address",
"name": "_redSnwapper",
"type": "address"
},
{
"internalType": "address",
"name": "_weth",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "OnlyTrusted",
"type": "error"
},
{
"inputs": [],
"name": "TransferFailed",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferStarted",
"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": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "isTrusted",
"type": "bool"
}
],
"name": "SetTrusted",
"type": "event"
},
{
"inputs": [],
"name": "acceptOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_value",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "doAction",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pendingOwner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "redSnwapper",
"outputs": [
{
"internalType": "contract IRedSnwapper",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "user",
"type": "address"
},
{
"internalType": "bool",
"name": "isTrusted",
"type": "bool"
}
],
"name": "setTrusted",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "tokenIn",
"type": "address"
},
{
"internalType": "uint256",
"name": "amountIn",
"type": "uint256"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "address",
"name": "tokenOut",
"type": "address"
},
{
"internalType": "uint256",
"name": "amountOutMin",
"type": "uint256"
},
{
"internalType": "address",
"name": "executor",
"type": "address"
},
{
"internalType": "bytes",
"name": "executorData",
"type": "bytes"
}
],
"name": "snwap",
"outputs": [
{
"internalType": "uint256",
"name": "amountOut",
"type": "uint256"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "uint256",
"name": "amountIn",
"type": "uint256"
},
{
"internalType": "address",
"name": "transferTo",
"type": "address"
}
],
"internalType": "struct IRedSnwapper.InputToken[]",
"name": "inputTokens",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amountOutMin",
"type": "uint256"
}
],
"internalType": "struct IRedSnwapper.OutputToken[]",
"name": "outputTokens",
"type": "tuple[]"
},
{
"components": [
{
"internalType": "address",
"name": "executor",
"type": "address"
},
{
"internalType": "uint256",
"name": "value",
"type": "uint256"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"internalType": "struct IRedSnwapper.Executor[]",
"name": "executors",
"type": "tuple[]"
}
],
"name": "snwapMultiple",
"outputs": [
{
"internalType": "uint256[]",
"name": "amountOut",
"type": "uint256[]"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "transferOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "trusted",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_redSnwapper",
"type": "address"
}
],
"name": "updateRedSnwapper",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "weth",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
},
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "_value",
"type": "uint256"
}
],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "wrapEth",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
]Source code
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;
import "interfaces/IRedSnwapper.sol";
import "interfaces/IERC20.sol";
import "./Auth.sol";
/// @title TokenChwomper for selling accumulated tokens for weth or other base assets
/// @notice This contract will be used for fee collection and breakdown
/// @dev Uses Auth contract for 2-step owner process and trust operators to guard functions
contract TokenChwomper is Auth {
address public immutable weth;
IRedSnwapper public redSnwapper;
address private constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
bytes4 private constant TRANSFER_SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
error TransferFailed();
constructor(
address _operator,
address _redSnwapper,
address _weth
) Auth(_operator) {
// initial owner is msg.sender
redSnwapper = IRedSnwapper(_redSnwapper);
weth = _weth;
}
/// @notice Updates the RedSnwapper to be used for swapping tokens
/// @dev make sure new RedSnwapper is backwards compatiable (should be)
/// @param _redSnwapper The address of the new route processor
function updateRedSnwapper(address _redSnwapper) external onlyOwner {
redSnwapper = IRedSnwapper(_redSnwapper);
}
/// @notice Swaps tokens via the configured RedSnwapper
/// @dev Must be called by a trusted operator
/// @param tokenIn Address of the input token
/// @param amountIn Amount of the input token to swap
/// @param recipient Address to receive the output tokens
/// @param tokenOut Address of the output token
/// @param amountOutMin Minimum acceptable amount of output tokens (slippage protection)
/// @param executor Address of the executor contract to perform the swap logic
/// @param executorData Encoded data for the executor call
/// @return amountOut The actual amount of output tokens received
function snwap(
address tokenIn,
uint256 amountIn,
address recipient,
address tokenOut,
uint256 amountOutMin,
address executor,
bytes calldata executorData
) external onlyTrusted returns (uint256 amountOut) {
if (tokenIn == NATIVE_TOKEN) {
amountOut = redSnwapper.snwap{ value: amountIn }(
tokenIn,
amountIn,
recipient,
tokenOut,
amountOutMin,
executor,
executorData
);
} else {
// Pre-fund RedSnwapper with input tokens
_safeTransfer(tokenIn, address(redSnwapper), amountIn);
// Execute snwap with zero amountIn
amountOut = redSnwapper.snwap(
tokenIn,
0,
recipient,
tokenOut,
amountOutMin,
executor,
executorData
);
}
}
/// @notice Performs multiple swaps via the configured RedSnwapper
/// @dev Must be called by a trusted operator
/// @param inputTokens Array of input token parameters
/// @param outputTokens Array of output token requirements
/// @param executors Array of executor calls to perform
/// @return amountOut Array of actual amounts of output tokens received
function snwapMultiple(
IRedSnwapper.InputToken[] calldata inputTokens,
IRedSnwapper.OutputToken[] calldata outputTokens,
IRedSnwapper.Executor[] calldata executors
) external onlyTrusted returns (uint256[] memory amountOut) {
uint256 length = inputTokens.length;
IRedSnwapper.InputToken[] memory _inputTokens = new IRedSnwapper.InputToken[](length);
uint256 value = 0;
for (uint256 i = 0; i < length; ++i) {
if (inputTokens[i].token == NATIVE_TOKEN) {
value += inputTokens[i].amountIn;
_inputTokens[i] = inputTokens[i];
} else {
// Pre-fund RedSnwapper with input tokens
_safeTransfer(
inputTokens[i].token,
address(redSnwapper),
inputTokens[i].amountIn
);
// Build _inputTokens with zero amountIn
_inputTokens[i] = IRedSnwapper.InputToken({
token: inputTokens[i].token,
amountIn: 0,
transferTo: inputTokens[i].transferTo
});
}
}
// Execute snwapMultiple
amountOut = redSnwapper.snwapMultiple{value: value}(
_inputTokens,
outputTokens,
executors
);
}
/// @notice Withdraw any token or eth from the contract
/// @dev can only be called by owner
/// @param token The address of the token to be withdrawn, 0x0 for eth
/// @param to The address to send the token to
/// @param _value The amount of the token to be withdrawn
function withdraw(address token, address to, uint256 _value) onlyOwner external {
if (token != address(0)) {
_safeTransfer(token, to, _value);
}
else {
(bool success, ) = to.call{value: _value}("");
require(success);
}
}
function _safeTransfer(address token, address to, uint value) internal {
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(TRANSFER_SELECTOR, to, value));
if (!success || (data.length != 0 && !abi.decode(data, (bool)))) revert TransferFailed();
}
/// @notice In case we receive any unwrapped eth (native token) we can call this
/// @dev operators can call this
function wrapEth() onlyTrusted external {
weth.call{value: address(this).balance}("");
}
/// @notice Available function in case we need to do any calls that aren't supported by the contract (unwinding lp positions, etc.)
/// @dev can only be called by owner
/// @param to The address to send the call to
/// @param _value The amount of eth to send with the call
/// @param data The data to be sent with the call
function doAction(address to, uint256 _value, bytes memory data) onlyOwner external {
(bool success, ) = to.call{value: _value}(data);
require(success);
}
receive() external payable {}
}Chain explorer1573msChain node75ms