Prepare all the vegetables to start: chop the onion, carrots, tomatoes, and the basil leaves. Mince the garlic, and set everything aside.
Place a large pot over medium heat. Once the pot has heated, add the oil and then the onions and the garlic.
Saute the onions and garlic until the onions begin to soften. Add the carrots, tomatoes, basil leaves and salt and pepper, and stir. Let everything cook for a few minutes, stirring often. You'll notice the tomatoes begin to fall apart as they cook and the carrot pieces will begin to soften slightly. After about 5-6 minutes, add the vegetable stock and tomato paste and stir to combine.
Add a lid to the pot and let the soup come to a slow boil. Once it reaches a boil, turn the heat to low and let the soup simmer for about 20 minutes, stirring every 3-5 minutes or so.
Once the soup has finished simmering and the carrots have softened, remove the pot from the heat and puree the soup using an immersion blender. If you have a high-powered blender, feel free to use that instead. I like my immersion blender because it creates far fewer dishes to wash! After you've pureed the soup put it through a strainer to catch any little bits of tomato seeds or tomato skin that are still floating around in there. There won't be much to strain out, but no one likes little strands of tomato skin in tomato soup!
Once you've strained the soup, add the milk (or dairy-free milk alternative, if you wish) and stir to combine.
Ladle the soup into bowls, add a few fresh basil leaves as a garnish, and serve!