contract Wallet {
    bool public isInitialized;
    address public creator;
    address public owner;
    bytes public swthAddress;

    function initialize(address _owner, bytes calldata _swthAddress) external {
        require(isInitialized == false, "Contract already initialized");
        isInitialized = true;
        creator = msg.sender;
        owner = _owner;
        swthAddress = _swthAddress;
    }

    /// @dev Allow this contract to receive Ethereum
    receive() external payable {}

    /// @dev Allow this contract to receive ERC223 tokens
    // An empty implementation is required so that the ERC223 token will not
    // throw an error on transfer
    function tokenFallback(address, uint, bytes calldata) external {}

    /// @dev send ETH from this contract to its creator
    function sendETHToCreator(uint256 _amount) external {
        require(msg.sender == creator, "Sender must be creator");
        // we use `call` here following the recommendation from
        // https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/
        (bool success,  ) = creator.call{value: _amount}("");
        require(success, "Transfer failed");
    }

    /// @dev send tokens from this contract to its creator
    function sendERC20ToCreator(address _assetId, uint256 _amount) external {
        require(msg.sender == creator, "Sender must be creator");

        ERC20 token = ERC20(_assetId);
        _callOptionalReturn(
            token,
            abi.encodeWithSelector(
                token.transfer.selector,
                creator,
                _amount
            )
        );
    }

    /**
     * @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).
     */
    function _callOptionalReturn(ERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(_isContract(address(token)), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }

    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `_isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function _isContract(address account) private view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }
}
/// @title The Wallet contract for Switcheo TradeHub
/// @author Switcheo Network
/// @notice This contract faciliates deposits for Switcheo TradeHub.
/// @dev This contract is used together with the LockProxy contract to allow users
/// to deposit funds without requiring them to have ETH
function sendERC20ToCreator(address _assetId, uint256 _amount) external {
    require(msg.sender == creator, "Sender must be creator");

    ERC20 token = ERC20(_assetId);
    _callOptionalReturn(
        token,
        abi.encodeWithSelector(
            token.transfer.selector,
            creator,
            _amount
        )
    );
}

/// @dev send tokens from this contract to its creator