contract DecoProxy {
    using ECDSA for bytes32;

    /// Emitted when incoming ETH funds land into account.
    event Received (address indexed sender, uint value);

    /// Emitted when transaction forwarded to the next destination.
    event Forwarded (
        bytes signature,
        address indexed signer,
        address indexed destination,
        uint value,
        bytes data,
        bytes32 _hash
    );

    /// Emitted when owner is changed
    event OwnerChanged (
        address indexed newOwner
    );

    bool internal isInitialized;

    // Keep track to avoid replay attack.
    uint public nonce;

    /// Proxy owner.
    address public owner;


    /**
     * @dev Initialize the Proxy clone with default values.
     * @param _owner An address that orders forwarding of transactions.
     */
    function initialize(address _owner) public {
        require(!isInitialized, "Clone must be initialized only once.");
        isInitialized = true;
        owner = _owner;
    }

    /**
     * @dev Payable fallback to accept incoming payments.
     */
    function () external payable {
        emit Received(msg.sender, msg.value);
    }

    /**
     * @dev Change the owner of this proxy.  Used when the user forgets their key, and we can recover it via SSSS split key.  This will be the final txn of the forgotten key as it transfers ownership of the proxy to the new replacement key.  Note that this is also callable by the contract itself, which would be used in the case that a user is changing their owner address via a metatxn
     * @param _newOwner An `address` of the new proxy owner.
     */
    function changeOwner(address _newOwner) public {
        require(owner == msg.sender || address(this) == msg.sender, "Only owner can change owner");
        owner = _newOwner;
        emit OwnerChanged(_newOwner);
    }

    /**
     * @dev Forward a regular (non meta) transaction to the destination address.
     * @param _destination An `address` where txn should be forwarded to.
     * @param _value An `uint` of Wei value to be sent out.
     * @param _data A `bytes` data array of the given transaction.
     */
    function forwardFromOwner(address _destination, uint _value, bytes memory _data) public {
        require(owner == msg.sender, "Only owner can use forwardFromOwner method");
        require(executeCall(_destination, _value, _data), "Call must be successfull.");
        emit Forwarded("", owner, _destination, _value, _data, "");
    }

    /**
     * @dev Returns hash for the given transaction.
     * @param _signer An `address` of transaction signer.
     * @param _destination An `address` where txn should be forwarded to.
     * @param _value An `uint` of Wei value to be sent out.
     * @param _data A `bytes` data array of the given transaction.
     * @return A `bytes32` hash calculated for all incoming parameters.
     */
    function getHash(
        address _signer,
        address _destination,
        uint _value,
        bytes memory _data
    )
        public
        view
        returns(bytes32)
    {
        return keccak256(abi.encodePacked(address(this), _signer, _destination, _value, _data, nonce));
    }

    /**
     * @dev Forward a meta transaction to the destination address.
     * @param _signature A `bytes` array cotaining signature generated by owner.
     * @param _signer An `address` of transaction signer.
     * @param _destination An `address` where txn should be forwarded to.
     * @param _value An `uint` of Wei value to be sent out.
     * @param _data A `bytes` data array of the given transaction.
     */
    function forward(bytes memory _signature, address _signer, address _destination, uint _value, bytes memory _data) public {
        bytes32 hash = getHash(_signer, _destination, _value, _data);
        nonce++;
        require(owner == hash.toEthSignedMessageHash().recover(_signature), "Signer must be owner.");
        require(executeCall(_destination, _value, _data), "Call must be successfull.");
        emit Forwarded(_signature, _signer, _destination, _value, _data, hash);
    }

    /**
     * @dev Withdraw given amount of wei to the specified address.
     * @param _to An `address` of where to send the wei.
     * @param _value An `uint` amount to withdraw from the contract balance.
     */
    function withdraw(address _to, uint _value) public {
        require(owner == msg.sender || address(this) == msg.sender, "Only owner can withdraw");
        _to.transfer(_value);
    }

    /**
     * @dev Withdraw any ERC20 tokens from the contract balance to owner's address.
     * @param _tokenAddress An `address` of an ERC20 token.
     * @param _to An `address` of where to send the tokens.
     * @param _tokens An `uint` tokens amount.
     */
    function withdrawERC20Token(address _tokenAddress, address _to, uint _tokens) public {
        require(owner == msg.sender || address(this) == msg.sender, "Only owner can withdraw");
        IERC20 token = IERC20(_tokenAddress);
        require(token.transfer(_to, _tokens), "Tokens transfer must complete successfully.");
    }

    /**
     * @dev Forward txn by executing a call.
     * @param _to Destination `address`.
     * @param _value An `uint256` Wei value to be sent out.
     * @param _data A `bytes` array with txn data.
     * @return A `bool` completion status.
     */
    function executeCall(address _to, uint256 _value, bytes memory _data) internal returns (bool success) {
        assembly {
            let x := mload(0x40)
            success := call(gas, _to, _value, add(_data, 0x20), mload(_data), 0, 0)
        }
    }
}
function withdraw(address _to, uint _value) public {
    require(owner == msg.sender || address(this) == msg.sender, "Only owner can withdraw");
    _to.transfer(_value);
}

/**
 * @dev Withdraw given amount of wei to the specified address.
 * @param _to An `address` of where to send the wei.
 * @param _value An `uint` amount to withdraw from the contract balance.
 */