Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
Contract Name:
SwapExecutor
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.17; import {ERC20} from "solmate/src/tokens/ERC20.sol"; import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol"; import {IFeeCollector} from "../interfaces/IFeeCollector.sol"; contract SwapExecutor { using SafeTransferLib for ERC20; error TransferFailed(); address public constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; function executeSwap(address token, uint256 amount, address swapRouter, bytes memory swapPayload) external { ERC20(token).safeApprove(swapRouter, amount); (bool success, ) = swapRouter.call(swapPayload); if (!success) revert(); } function executeSwapWithValue(address swapRouter, bytes memory swapPayload, uint256 msgValue) external { (bool success, ) = swapRouter.call{value: msgValue}(swapPayload); if (!success) revert(); } function collectFeeAndExecuteSwap( address token, uint256 amount, address swapRouter, /// @notice swapPayload should consider (amount - feeAmount) as the swap input bytes memory swapPayload, IFeeCollector feeCollector, address feeTaker, uint256 feeAmount ) external { _collectFee(token, feeAmount, feeTaker, feeCollector); ERC20(token).safeApprove(swapRouter, amount - feeAmount); (bool success, ) = swapRouter.call(swapPayload); if (!success) revert(); } // @todo should there be a function that takes requestHash and registers locked fee as well? /** * @dev collects unlocked fee in input token and registers it with the FeeCollector */ function _collectFee(address token, uint256 amount, address feeTaker, IFeeCollector feeCollector) internal { _sendFundsFromContract(token, amount, address(feeCollector)); feeCollector.registerFee(feeTaker, amount, token); } /** * @dev send funds to the provided address. * @param token address of the token * @param amount hash of the command. * @param to address, funds will be transferred to this address. */ function _sendFundsFromContract(address token, uint256 amount, address to) internal { /// native token case if (token == NATIVE_TOKEN_ADDRESS) { (bool success, ) = to.call{value: amount, gas: 5000}(""); if (!success) revert TransferFailed(); return; } /// ERC20 case ERC20(token).safeTransfer(to, amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol, uint8 _decimals) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom(ERC20 token, address from, address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer(ERC20 token, address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove(ERC20 token, address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.17; interface IFeeCollector { function registerFee(address feeTaker, uint256 feeAmount, address feeToken) external; function registerFee(address feeTaker, uint256 feeAmount, address feeToken, bytes32 requestHash) external; function settleFee(bytes32 requestHash) external; function refundFee(bytes32 requestHash, address to) external; }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"NATIVE_TOKEN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"swapRouter","type":"address"},{"internalType":"bytes","name":"swapPayload","type":"bytes"},{"internalType":"contract IFeeCollector","name":"feeCollector","type":"address"},{"internalType":"address","name":"feeTaker","type":"address"},{"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"collectFeeAndExecuteSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"swapRouter","type":"address"},{"internalType":"bytes","name":"swapPayload","type":"bytes"}],"name":"executeSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"swapRouter","type":"address"},{"internalType":"bytes","name":"swapPayload","type":"bytes"},{"internalType":"uint256","name":"msgValue","type":"uint256"}],"name":"executeSwapWithValue","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061072f806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80630be0eba8146100515780633860eb321461006657806383ff70f014610079578063df2ebdbb1461008c575b600080fd5b61006461005f366004610541565b6100c3565b005b6100646100743660046105ad565b610148565b61006461008736600461064a565b6101e7565b6100a773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6040516001600160a01b03909116815260200160405180910390f35b6100d76001600160a01b0385168385610258565b6000826001600160a01b0316826040516100f191906106a3565b6000604051808303816000865af19150503d806000811461012e576040519150601f19603f3d011682016040523d82523d6000602084013e610133565b606091505b505090508061014157600080fd5b5050505050565b610154878284866102dd565b6101738561016283896106d2565b6001600160a01b038a169190610258565b6000856001600160a01b03168560405161018d91906106a3565b6000604051808303816000865af19150503d80600081146101ca576040519150601f19603f3d011682016040523d82523d6000602084013e6101cf565b606091505b50509050806101dd57600080fd5b5050505050505050565b6000836001600160a01b0316828460405161020291906106a3565b60006040518083038185875af1925050503d806000811461023f576040519150601f19603f3d011682016040523d82523d6000602084013e610244565b606091505b505090508061025257600080fd5b50505050565b600060405163095ea7b360e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806102525760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b60448201526064015b60405180910390fd5b6102e884848361034e565b60405163404e3d4960e01b81526001600160a01b03838116600483015260248201859052858116604483015282169063404e3d4990606401600060405180830381600087803b15801561033a57600080fd5b505af11580156101dd573d6000803e3d6000fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038416016103ec576000816001600160a01b03168361138890604051600060405180830381858888f193505050503d80600081146103c5576040519150601f19603f3d011682016040523d82523d6000602084013e6103ca565b606091505b5050905080610252576040516312171d8360e31b815260040160405180910390fd5b6104006001600160a01b0384168284610405565b505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806102525760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016102d4565b6001600160a01b038116811461049b57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126104c557600080fd5b813567ffffffffffffffff808211156104e0576104e061049e565b604051601f8301601f19908116603f011681019082821181831017156105085761050861049e565b8160405283815286602085880101111561052157600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561055757600080fd5b843561056281610486565b935060208501359250604085013561057981610486565b9150606085013567ffffffffffffffff81111561059557600080fd5b6105a1878288016104b4565b91505092959194509250565b600080600080600080600060e0888a0312156105c857600080fd5b87356105d381610486565b96506020880135955060408801356105ea81610486565b9450606088013567ffffffffffffffff81111561060657600080fd5b6106128a828b016104b4565b945050608088013561062381610486565b925060a088013561063381610486565b8092505060c0880135905092959891949750929550565b60008060006060848603121561065f57600080fd5b833561066a81610486565b9250602084013567ffffffffffffffff81111561068657600080fd5b610692868287016104b4565b925050604084013590509250925092565b6000825160005b818110156106c457602081860181015185830152016106aa565b506000920191825250919050565b818103818111156106f357634e487b7160e01b600052601160045260246000fd5b9291505056fea2646970667358221220d3acbb98417cf0ad100e647aef0cdb2f94a3ea6aa12302f7f49f4fad9055b80064736f6c63430008130033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80630be0eba8146100515780633860eb321461006657806383ff70f014610079578063df2ebdbb1461008c575b600080fd5b61006461005f366004610541565b6100c3565b005b6100646100743660046105ad565b610148565b61006461008736600461064a565b6101e7565b6100a773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6040516001600160a01b03909116815260200160405180910390f35b6100d76001600160a01b0385168385610258565b6000826001600160a01b0316826040516100f191906106a3565b6000604051808303816000865af19150503d806000811461012e576040519150601f19603f3d011682016040523d82523d6000602084013e610133565b606091505b505090508061014157600080fd5b5050505050565b610154878284866102dd565b6101738561016283896106d2565b6001600160a01b038a169190610258565b6000856001600160a01b03168560405161018d91906106a3565b6000604051808303816000865af19150503d80600081146101ca576040519150601f19603f3d011682016040523d82523d6000602084013e6101cf565b606091505b50509050806101dd57600080fd5b5050505050505050565b6000836001600160a01b0316828460405161020291906106a3565b60006040518083038185875af1925050503d806000811461023f576040519150601f19603f3d011682016040523d82523d6000602084013e610244565b606091505b505090508061025257600080fd5b50505050565b600060405163095ea7b360e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806102525760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b60448201526064015b60405180910390fd5b6102e884848361034e565b60405163404e3d4960e01b81526001600160a01b03838116600483015260248201859052858116604483015282169063404e3d4990606401600060405180830381600087803b15801561033a57600080fd5b505af11580156101dd573d6000803e3d6000fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038416016103ec576000816001600160a01b03168361138890604051600060405180830381858888f193505050503d80600081146103c5576040519150601f19603f3d011682016040523d82523d6000602084013e6103ca565b606091505b5050905080610252576040516312171d8360e31b815260040160405180910390fd5b6104006001600160a01b0384168284610405565b505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806102525760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016102d4565b6001600160a01b038116811461049b57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126104c557600080fd5b813567ffffffffffffffff808211156104e0576104e061049e565b604051601f8301601f19908116603f011681019082821181831017156105085761050861049e565b8160405283815286602085880101111561052157600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561055757600080fd5b843561056281610486565b935060208501359250604085013561057981610486565b9150606085013567ffffffffffffffff81111561059557600080fd5b6105a1878288016104b4565b91505092959194509250565b600080600080600080600060e0888a0312156105c857600080fd5b87356105d381610486565b96506020880135955060408801356105ea81610486565b9450606088013567ffffffffffffffff81111561060657600080fd5b6106128a828b016104b4565b945050608088013561062381610486565b925060a088013561063381610486565b8092505060c0880135905092959891949750929550565b60008060006060848603121561065f57600080fd5b833561066a81610486565b9250602084013567ffffffffffffffff81111561068657600080fd5b610692868287016104b4565b925050604084013590509250925092565b6000825160005b818110156106c457602081860181015185830152016106aa565b506000920191825250919050565b818103818111156106f357634e487b7160e01b600052601160045260246000fd5b9291505056fea2646970667358221220d3acbb98417cf0ad100e647aef0cdb2f94a3ea6aa12302f7f49f4fad9055b80064736f6c63430008130033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
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.