Two important concepts should be considered:
1 - Agile Principle #11:
"The best architectures, requirements, and designs emerge from self-organizing teams."
That means that the best way of work should be discovered by the team. That means experimenting, even with practices that seems efficient. Learning and mistakes walking side-by-side and improve the value-delivering as a whole.
2 - Generalizing Specialist:
The member of an Agile project is usually a Generalizing Specialist - someone who has understanding of the whole, is able to talk and discuss all aspects of the software development process. It doesn't mean that this person doesn't have an area of interest (QA, backend, etc), but that he knows how each piece fits on the puzzle.
Considering it, for improving the velocity as a whole, the tasks should be performed by the members who are able to do it (or will learn how to do it), regardless of roles and titles. If in your team the devs are the best people to write some type of test, do it. Teach others to do it as well, so the roles can be changed in the future. The best task-assignment strategy is volatile, since people are learning and changing interest all the time, distributedly.
Regarding the four-eyes-principle, code review helps to spread knowledge, making the work packages more visible to others, including QA.
One strategy that I have find to be very effective is to use planning time to brainstorm what and how things will be test ("Scenario X is for integration using the tool Z, scenario Y needs E2E"). At code review, different people can take a look on how different levels of testing were implementing, enabling them to take similar future tasks in the future.