What are the best practices to prevent reentrancy attacks in Solidity contracts, especially in withdrawal functions?