Forkchoice Ethereum Mainnet

Address Contract Verified

Address 0x16BCbaCB2F9A2FbD8C825d3c3Da41961Fb6213B7
Balance 0 ETH
Nonce 1
Code Size 3606 bytes
Indexed Transactions 0 (1 on-chain, 1.2% indexed)
External Etherscan · Sourcify

Contract Bytecode

3606 bytes
0x60806040526004361061003f5760003560e01c80630c888d6914610044578063454594081461007557806384796caf146100a0578063c9fbfbfa146100cb575b600080fd5b61005e60048036038101906100599190610933565b610109565b60405161006c929190610a81565b60405180910390f35b34801561008157600080fd5b5061008a6102ff565b6040516100979190610ac0565b60405180910390f35b3480156100ac57600080fd5b506100b5610323565b6040516100c29190610ac0565b60405180910390f35b3480156100d757600080fd5b506100f260048036038101906100ed9190610adb565b610347565b604051610100929190610a81565b60405180910390f35b60006060600034141561014e57610122853330866104a8565b61014d857f000000000000000000000000216b4b4ba9f3e719726886d34a177484278bfcae85610547565b5b7f000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5773ffffffffffffffffffffffffffffffffffffffff16348989604051610196929190610ba2565b60006040518083038185875af1925050503d80600081146101d3576040519150601f19603f3d011682016040523d82523d6000602084013e6101d8565b606091505b5080925081935050508161022357806040517f113ab42700000000000000000000000000000000000000000000000000000000815260040161021a9190610bbb565b60405180910390fd5b6102b684878673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016102619190610ac0565b60206040518083038186803b15801561027957600080fd5b505afa15801561028d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b19190610bf2565b6105df565b600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16146102f4576102f385610677565b5b965096945050505050565b7f000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5781565b7f000000000000000000000000216b4b4ba9f3e719726886d34a177484278bfcae81565b60006060610357843330866104a8565b610382847f000000000000000000000000216b4b4ba9f3e719726886d34a177484278bfcae85610547565b7f000000000000000000000000def171fe48cf0115b1d80b88dc8eab59176fee5773ffffffffffffffffffffffffffffffffffffffff1687876040516103c9929190610ba2565b6000604051808303816000865af19150503d8060008114610406576040519150601f19603f3d011682016040523d82523d6000602084013e61040b565b606091505b5080925081935050508161045657806040517f113ab42700000000000000000000000000000000000000000000000000000000815260040161044d9190610bbb565b60405180910390fd5b610460854761079f565b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461049e5761049d84610677565b5b9550959350505050565b60006040517f23b872dd0000000000000000000000000000000000000000000000000000000081528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610540576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053790610c7c565b60405180910390fd5b5050505050565b60006040517f095ea7b3000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806105d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d090610ce8565b60405180910390fd5b50505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080610671576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161066890610d54565b60405180910390fd5b50505050565b60008173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016106b29190610ac0565b60206040518083038186803b1580156106ca57600080fd5b505afa1580156106de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107029190610bf2565b111561079c5761079b81338373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016107469190610ac0565b60206040518083038186803b15801561075e57600080fd5b505afa158015610772573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107969190610bf2565b6105df565b5b50565b600080600080600085875af19050806107ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107e490610dc0565b60405180910390fd5b505050565b600080fd5b600080fd5b600080fd5b600080fd5b600080fd5b60008083601f840112610821576108206107fc565b5b8235905067ffffffffffffffff81111561083e5761083d610801565b5b60208301915083600182028301111561085a57610859610806565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061088c82610861565b9050919050565b61089c81610881565b81146108a757600080fd5b50565b6000813590506108b981610893565b92915050565b60006108ca82610881565b9050919050565b6108da816108bf565b81146108e557600080fd5b50565b6000813590506108f7816108d1565b92915050565b6000819050919050565b610910816108fd565b811461091b57600080fd5b50565b60008135905061092d81610907565b92915050565b60008060008060008060a087890312156109505761094f6107f2565b5b600087013567ffffffffffffffff81111561096e5761096d6107f7565b5b61097a89828a0161080b565b9650965050602061098d89828a016108aa565b945050604061099e89828a016108e8565b93505060606109af89828a016108e8565b92505060806109c089828a0161091e565b9150509295509295509295565b60008115159050919050565b6109e2816109cd565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610a22578082015181840152602081019050610a07565b83811115610a31576000848401525b50505050565b6000601f19601f8301169050919050565b6000610a53826109e8565b610a5d81856109f3565b9350610a6d818560208601610a04565b610a7681610a37565b840191505092915050565b6000604082019050610a9660008301856109d9565b8181036020830152610aa88184610a48565b90509392505050565b610aba81610881565b82525050565b6000602082019050610ad56000830184610ab1565b92915050565b600080600080600060808688031215610af757610af66107f2565b5b600086013567ffffffffffffffff811115610b1557610b146107f7565b5b610b218882890161080b565b95509550506020610b34888289016108aa565b9350506040610b45888289016108e8565b9250506060610b568882890161091e565b9150509295509295909350565b600081905092915050565b82818337600083830152505050565b6000610b898385610b63565b9350610b96838584610b6e565b82840190509392505050565b6000610baf828486610b7d565b91508190509392505050565b60006020820190508181036000830152610bd58184610a48565b905092915050565b600081519050610bec81610907565b92915050565b600060208284031215610c0857610c076107f2565b5b6000610c1684828501610bdd565b91505092915050565b600082825260208201905092915050565b7f5452414e534645525f46524f4d5f4641494c4544000000000000000000000000600082015250565b6000610c66601483610c1f565b9150610c7182610c30565b602082019050919050565b60006020820190508181036000830152610c9581610c59565b9050919050565b7f415050524f56455f4641494c4544000000000000000000000000000000000000600082015250565b6000610cd2600e83610c1f565b9150610cdd82610c9c565b602082019050919050565b60006020820190508181036000830152610d0181610cc5565b9050919050565b7f5452414e534645525f4641494c45440000000000000000000000000000000000600082015250565b6000610d3e600f83610c1f565b9150610d4982610d08565b602082019050919050565b60006020820190508181036000830152610d6d81610d31565b9050919050565b7f4554485f5452414e534645525f4641494c454400000000000000000000000000600082015250565b6000610daa601383610c1f565b9150610db582610d74565b602082019050919050565b60006020820190508181036000830152610dd981610d9d565b905091905056fea264697066735822122051b44dde03ba77d7567181d4a437b840a4e086af1b9b2b39671376c42f466e1264736f6c63430008090033

Verified Source Code Full Match

Compiler: v0.8.9+commit.e5eed63a EVM: london Optimization: No
Wrapper.sol 83 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import {ERC20} from "@rari-capital/solmate/src/tokens/ERC20.sol";
import {SafeTransferLib} from "@rari-capital/solmate/src/utils/SafeTransferLib.sol";

contract ParaswapWrapperV2 {
    address public immutable PARASWAP_V5;
    address public immutable PARASWAP_TRANSFER_PROXY;

    /// @notice Thrown when swap fails.
    error swapFailed(bytes output);

    constructor(address _paraswapV5, address _paraswapTransferProxy) {
        PARASWAP_V5 = _paraswapV5;
        PARASWAP_TRANSFER_PROXY = _paraswapTransferProxy;
    }

    function swapToTokens(
        bytes calldata _txData,
        address _receiver,
        ERC20 _fromToken,
        ERC20 _toToken,
        uint256 _inputAmount
    ) external payable returns (bool success, bytes memory output) {
        if (msg.value == 0) {
            SafeTransferLib.safeTransferFrom(
                _fromToken,
                msg.sender,
                address(this),
                _inputAmount
            );
            SafeTransferLib.safeApprove(
                _fromToken,
                PARASWAP_TRANSFER_PROXY,
                _inputAmount
            );
        }
        (success, output) = PARASWAP_V5.call{value: msg.value}(_txData);
        if (!success) revert swapFailed(output);

        SafeTransferLib.safeTransfer(
            _toToken,
            _receiver,
            _toToken.balanceOf(address(this))
        );
        if (address(_fromToken) != address(0)) checkTokenRefund(_fromToken);
    }

    function swapToEth(
        bytes calldata _txData,
        address _receiver,
        ERC20 _fromToken,
        uint256 _inputAmount
    ) external returns (bool success, bytes memory output) {
        SafeTransferLib.safeTransferFrom(
            _fromToken,
            msg.sender,
            address(this),
            _inputAmount
        );
        SafeTransferLib.safeApprove(
            _fromToken,
            PARASWAP_TRANSFER_PROXY,
            _inputAmount
        );
        (success, output) = PARASWAP_V5.call(_txData);
        if (!success) revert swapFailed(output);

        SafeTransferLib.safeTransferETH(_receiver, address(this).balance);
        if (address(_fromToken) != address(0)) checkTokenRefund(_fromToken);
    }

    function checkTokenRefund(ERC20 _fromToken) internal {
        if (_fromToken.balanceOf(address(this)) > 0) {
            SafeTransferLib.safeTransfer(
                _fromToken,
                msg.sender,
                _fromToken.balanceOf(address(this))
            );
        }
    }
}
ERC20.sol 206 lines
// 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/Rari-Capital/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);
    }
}
SafeTransferLib.sol 124 lines
// 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/Rari-Capital/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;

        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;

        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), from) // Append the "from" argument.
            mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument.

            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;

        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), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            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;

        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), to) // Append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument.

            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");
    }
}

Read Contract

PARASWAP_TRANSFER_PROXY 0x84796caf → address
PARASWAP_V5 0x45459408 → address

Write Contract 2 functions

These functions modify contract state and require a wallet transaction to execute.

swapToEth 0xc9fbfbfa
bytes _txData
address _receiver
address _fromToken
uint256 _inputAmount
returns: bool, bytes
swapToTokens 0x0c888d69
bytes _txData
address _receiver
address _fromToken
address _toToken
uint256 _inputAmount
returns: bool, bytes

Recent Transactions

This address has 1 on-chain transactions, but only 1.2% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →