You're exploring a classic problem in Solidity: how to generate random numbers -on-chain?
Given there's no entropy, it's hard to get unguessable random numbers. Let's check the sources of randomness you use:
msg.sender: not random, for obvious reasons that you mentionned
block.number: not random: an attacker could just compute which block would produce a favorable outcome, and send his transaction at this exact block, with enough gas to be sure to be included in it.
newItemId: unless there's a lot of transactions on your contract at each block, it's quite easy to guess it as it won't be random. Even if there was a lot of transactions at each block, making it hard to guess which Id was used for the draw, a miner could just manipulate the ordering to get a favorable outcome.
Any other value, such as
block.coinbase for instance, would encounter more or less the same problems.
Bear in mind that a max prize of 300 dollars may be enough for many people - actually, hacking is often fun by itself. Do not underestimate this parameter. Additionally, if the hack can be repeated easily, it may be much more overtime.
Safer ways of generating random numbers:
blockhash(block.number + x): In this case, you use a 2-fold scheme: the first transaction records the future block number whose hash will be used to create the RNG. In a second transaction, you reveal this value and use this RNG.
This solution has the advantage of being quite straightforward and "cheap" as it doesn't need an oracle.
It has the disadvantage of needing a node which monitors the contract and sends a transaction to reveal the RNG. You can ask the user to do it, but beware - it has to be done in the next 256 blocks, as the blockchain only remembers the last 256 block hashes. Moreover, you give this way the miner an opportunity to manipulate the block hash until he gets a favourable outcome.
- Use a node to bring RNG on-chain.
You mentioned that you know this solution. I won't advertise any services here, but if you find it expensive, i may recommend the following:
- Either contact their sales team and negociate. I know from experience the prices can get very low, as their marginal cost is near 0 (except the gas).
- Make one yourself, which is a lot of fun, if you're into this kind of fun.