If the output value was only constrained by their sum being smaller than that of the inputs, you could e.g. set one output to a negative value and create new money in a second output.
You can also do more creative stuff: I think the rule might have been introduced as a response to the value overflow incident on 2010-08-15. A transaction in a (now invalid) block at height 74638 created outputs that were so large that their sum overflowed into the permitted range. The transaction created 2×92.2 billion bitcoins.
The original code fix for the value overflow incident can be found here: https://github.com/bitcoin/bitcoin/commit/d4c6b90ca3f9b47adb1b2724a0c3514f80635c84#diff-118fcbaaba162ba17933c7893247df3aR1013
main.cpp
was removed since, so I tried looking around in validation.cpp
and bitcoin-tx.cpp
using the search terms MAX_MONEY
and MoneyRange
, but I couldn't find a check that corresponded to rule 4. There is a check for the existence of inputs in validation.cpp
, but it's for mempool acceptance. I'm not sure where else transaction validation happens in Bitcoin Core.