Address Contract Partially Verified
Address
0x609790A65Da38dcb208FC8dA842871d6F85bEB18
Balance
0 ETH
Nonce
1
Code Size
4246 bytes
Creator
0xa9631864...F748 at tx 0x3f8539d1...dc1627
Indexed Transactions
0
Contract Bytecode
4246 bytes
0x608060405234801561000f575f5ffd5b506004361061007a575f3560e01c8063570ca73511610058578063570ca7351461010457806390dfe4651461012b578063a622e6c614610152578063bd0625ab14610187575f5ffd5b806301b60ef21461007e578063186f0354146100c25780633e413bee146100e9575b5f5ffd5b6100a57f0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b381565b6040516001600160a01b0390911681526020015b60405180910390f35b6100a57f000000000000000000000000c89657cc18c66ffc01d758ed42e61f28c6be43aa81565b6100a573a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b6100a57f000000000000000000000000a9631864e69a1132c82ef5beeecd4cac7ff3f74881565b6100a57f000000000000000000000000cf5540fffcdc3d510b18bfca6d2b9987b077255981565b6101797f0000000000000000000000000000000000000000000000000ddb6275b03a400081565b6040519081526020016100b9565b610179610195366004610b0e565b5f336001600160a01b037f000000000000000000000000a9631864e69a1132c82ef5beeecd4cac7ff3f74816146102135760405162461bcd60e51b815260206004820152601760248201527f4e6f7420617574686f72697a6564206f70657261746f7200000000000000000060448201526064015b60405180910390fd5b5f84116102625760405162461bcd60e51b815260206004820152601460248201527f496e76616c696420696e70757420616d6f756e74000000000000000000000000604482015260640161020a565b5f5f61026e85856107e5565b90925090506001600160e01b03198216630ed8d73960e21b146102d35760405162461bcd60e51b815260206004820152601560248201527f496e76616c696420737761702e73656c6563746f720000000000000000000000604482015260640161020a565b5f818060200190518101906102e89190610c87565b50505090507f0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b36001600160a01b0316815f01516001600160a01b0316146103715760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420737761702e696e70757420746f6b656e0000000000000000604482015260640161020a565b60608101516001600160a01b031673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48146103e15760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420737761702e6f757470757420746f6b656e00000000000000604482015260640161020a565b868160200151146104345760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420737761702e696e70757420616d6f756e7400000000000000604482015260640161020a565b7f000000000000000000000000c89657cc18c66ffc01d758ed42e61f28c6be43aa6001600160a01b03168160c001516001600160a01b0316146104b95760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420737761702e6f757470757420726563656976657200000000604482015260640161020a565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000c89657cc18c66ffc01d758ed42e61f28c6be43aa1660048201525f9073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190602401602060405180830381865afa158015610531573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105559190610d68565b90506105a27f0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b37f000000000000000000000000cf5540fffcdc3d510b18bfca6d2b9987b07725598a61084b565b60405163468721a760e01b81525f906001600160a01b037f000000000000000000000000c89657cc18c66ffc01d758ed42e61f28c6be43aa169063468721a790610618907f000000000000000000000000cf5540fffcdc3d510b18bfca6d2b9987b07725599085908d908d908390600401610d9f565b6020604051808303815f875af1158015610634573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106589190610df4565b9050806106955760405162461bcd60e51b815260206004820152600b60248201526a14ddd85c0819985a5b195960aa1b604482015260640161020a565b6106e07f0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b37f000000000000000000000000cf5540fffcdc3d510b18bfca6d2b9987b07725595f61084b565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000c89657cc18c66ffc01d758ed42e61f28c6be43aa1660048201525f9073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48906370a0823190602401602060405180830381865afa158015610758573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077c9190610d68565b90508281116107c05760405162461bcd60e51b815260206004820152601060248201526f139bc81554d110c81c9958d95a5d995960821b604482015260640161020a565b5f6107cb8483610e2e565b90506107d78b82610969565b9a9950505050505050505050565b5f60606107f56004838587610e47565b6107fe91610e6e565b915061080d8360048187610e47565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250949792965091945050505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b179052915163468721a760e01b815290915f917f000000000000000000000000c89657cc18c66ffc01d758ed42e61f28c6be43aa9091169063468721a7906108e1908890859087908290600401610ea6565b6020604051808303815f875af11580156108fd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109219190610df4565b9050806109625760405162461bcd60e51b815260206004820152600f60248201526e105c1c1c9bdd985b0819985a5b1959608a1b604482015260640161020a565b5050505050565b5f7f0000000000000000000000004c9edd5852cd905f086c759e8383e09bff1e68b36001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109c6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109ea9190610f00565b90505f60068260ff1610610a5f575f610a04600684610f20565b610a0f90600a61101c565b9050610a2381670de0b6b3a764000061102a565b610a4d7f0000000000000000000000000000000000000000000000000ddb6275b03a40008761102a565b610a579190611041565b915050610ac4565b5f610a6b836006610f20565b610a7690600a61101c565b9050670de0b6b3a764000081610aac7f0000000000000000000000000000000000000000000000000ddb6275b03a40008861102a565b610ab6919061102a565b610ac09190611041565b9150505b80831015610b085760405162461bcd60e51b815260206004820152601160248201527053776170207261746520746f6f206c6f7760781b604482015260640161020a565b50505050565b5f5f5f60408486031215610b20575f5ffd5b83359250602084013567ffffffffffffffff811115610b3d575f5ffd5b8401601f81018613610b4d575f5ffd5b803567ffffffffffffffff811115610b63575f5ffd5b866020828401011115610b74575f5ffd5b939660209190910195509293505050565b634e487b7160e01b5f52604160045260245ffd5b60405160e0810167ffffffffffffffff81118282101715610bbc57610bbc610b85565b60405290565b6001600160a01b0381168114610bd6575f5ffd5b50565b5f82601f830112610be8575f5ffd5b815167ffffffffffffffff811115610c0257610c02610b85565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610c3157610c31610b85565b604052818152838201602001851015610c48575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b8051610c6f81610bc2565b919050565b805163ffffffff81168114610c6f575f5ffd5b5f5f5f5f848603610140811215610c9c575f5ffd5b60e0811215610ca9575f5ffd5b50610cb2610b99565b8551610cbd81610bc2565b8152602086810151908201526040860151610cd781610bc2565b60408201526060860151610cea81610bc2565b60608201526080868101519082015260a0808701519082015260c0860151610d1181610bc2565b60c082015260e086015190945067ffffffffffffffff811115610d32575f5ffd5b610d3e87828801610bd9565b935050610d4e6101008601610c64565b9150610d5d6101208601610c74565b905092959194509250565b5f60208284031215610d78575f5ffd5b5051919050565b60028110610d9b57634e487b7160e01b5f52602160045260245ffd5b9052565b6001600160a01b038616815284602082015260806040820152826080820152828460a08301375f60a084830101525f60a0601f19601f8601168301019050610dea6060830184610d7f565b9695505050505050565b5f60208284031215610e04575f5ffd5b81518015158114610e13575f5ffd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610e4157610e41610e1a565b92915050565b5f5f85851115610e55575f5ffd5b83861115610e61575f5ffd5b5050820193919092039150565b80356001600160e01b03198116906004841015610e9f576001600160e01b0319600485900360031b81901b82161691505b5092915050565b6001600160a01b0385168152836020820152608060408201525f8351806080840152806020860160a085015e5f60a0828501015260a0601f19601f830116840101915050610ef76060830184610d7f565b95945050505050565b5f60208284031215610f10575f5ffd5b815160ff81168114610e13575f5ffd5b60ff8281168282160390811115610e4157610e41610e1a565b6001815b6001841115610f7457808504811115610f5857610f58610e1a565b6001841615610f6657908102905b60019390931c928002610f3d565b935093915050565b5f82610f8a57506001610e41565b81610f9657505f610e41565b8160018114610fac5760028114610fb657610fd2565b6001915050610e41565b60ff841115610fc757610fc7610e1a565b50506001821b610e41565b5060208310610133831016604e8410600b8410161715610ff5575081810a610e41565b6110015f198484610f39565b805f190482111561101457611014610e1a565b029392505050565b5f610e1360ff841683610f7c565b8082028115828204841417610e4157610e41610e1a565b5f8261105b57634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220402cb20836b6c8c4f4e18f1e321e990474c1478785ce34ce07028632242fadc064736f6c634300081f0033
Verified Source Code Partial Match
Compiler: v0.8.31+commit.fd3a2265
EVM: osaka
Optimization: Yes (300 runs)
SwapForUsdcModule.sol 135 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
interface IGnosisSafe {
enum Operation {
Call,
DelegateCall
}
function execTransactionFromModule(
address to,
uint256 value,
bytes calldata data,
Operation operation
) external returns (bool success);
function enableModule(address module) external;
}
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function decimals() external view returns (uint8);
}
interface IOdos {
struct swapTokenInfo {
address inputToken;
uint256 inputAmount;
address inputReceiver;
address outputToken;
uint256 outputQuote;
uint256 outputMin;
address outputReceiver;
}
function swap(
swapTokenInfo memory tokenInfo,
bytes calldata pathDefinition,
address executor,
uint32 referralCode
) external;
}
contract SwapForUsdcModule {
address public immutable safe;
address public immutable operator;
address public immutable odosSwapRouter;
address public immutable inputToken;
address public constant usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
uint256 public immutable minSwapRate; // e.g., 0.995e18 for 99.5%
constructor(
address safe_,
address operator_,
address odosSwapRouter_,
address inputToken_,
uint256 minSwapRate_ // e.g., 0.995e18 for 99.5%
) {
require(safe_ != address(0), "Invalid Safe address");
require(operator_ != address(0), "Invalid operator address");
require(odosSwapRouter_ != address(0), "Invalid odosSwapRouter address");
require(inputToken_ != address(0), "Invalid input token");
require(inputToken_ != usdc, "Input token cannot be USDC");
safe = safe_;
operator = operator_;
odosSwapRouter = odosSwapRouter_;
inputToken = inputToken_;
minSwapRate = minSwapRate_;
}
modifier onlyOperator() {
require(msg.sender == operator, "Not authorized operator");
_;
}
function swap(uint256 inputAmount, bytes calldata swapData) external onlyOperator returns (uint256) {
require(inputAmount > 0, "Invalid input amount");
(bytes4 selector, bytes memory dataWithoutSelector) = _splitCallData(swapData);
require(selector == IOdos.swap.selector, "Invalid swap.selector");
(IOdos.swapTokenInfo memory tokenInfo, , , ) = abi.decode(
dataWithoutSelector,
(IOdos.swapTokenInfo, bytes, address, uint32)
);
require(tokenInfo.inputToken == inputToken, "Invalid swap.input token");
require(tokenInfo.outputToken == usdc, "Invalid swap.output token");
require(tokenInfo.inputAmount == inputAmount, "Invalid swap.input amount");
require(tokenInfo.outputReceiver == safe, "Invalid swap.output receiver");
uint256 usdcBefore = IERC20(usdc).balanceOf(safe);
_approve(inputToken, odosSwapRouter, inputAmount);
bool success = IGnosisSafe(safe).execTransactionFromModule(
odosSwapRouter,
0,
swapData,
IGnosisSafe.Operation.Call
);
require(success, "Swap failed");
_approve(inputToken, odosSwapRouter, 0);
uint256 usdcAfter = IERC20(usdc).balanceOf(safe);
require(usdcAfter > usdcBefore, "No USDC received");
uint256 actualUsdcReceived = usdcAfter - usdcBefore;
_validateSwapSlippage(inputAmount, actualUsdcReceived);
return actualUsdcReceived;
}
function _approve(address token, address spender, uint256 amount) internal {
bytes memory approveData = abi.encodeWithSelector(IERC20.approve.selector, spender, amount);
bool success = IGnosisSafe(safe).execTransactionFromModule(token, 0, approveData, IGnosisSafe.Operation.Call);
require(success, "Approval failed");
}
function _splitCallData(
bytes calldata data
) internal pure returns (bytes4 selector, bytes memory dataWithoutSelector) {
selector = bytes4(data[:4]);
dataWithoutSelector = data[4:];
}
function _validateSwapSlippage(uint256 inputAmount, uint256 actualUsdcReceived) internal view {
uint8 inputDecimals = IERC20(inputToken).decimals();
uint256 minExpectedUsdc;
if (inputDecimals >= 6) {
uint256 scale = 10 ** (inputDecimals - 6);
minExpectedUsdc = (inputAmount * minSwapRate) / (1e18 * scale);
} else {
uint256 scale = 10 ** (6 - inputDecimals);
minExpectedUsdc = (inputAmount * minSwapRate * scale) / 1e18;
}
require(actualUsdcReceived >= minExpectedUsdc, "Swap rate too low");
}
}
Read Contract
inputToken 0x01b60ef2 → address
minSwapRate 0xa622e6c6 → uint256
odosSwapRouter 0x90dfe465 → address
operator 0x570ca735 → address
safe 0x186f0354 → address
usdc 0x3e413bee → address
Write Contract 1 functions
These functions modify contract state and require a wallet transaction to execute.
swap 0xbd0625ab
uint256 inputAmount
bytes swapData
returns: uint256
Recent Transactions
No transactions found for this address