# Veridise
## Formalization
1. A RefundableCrowdsale’s `claimRefund` transaction will revert if `goalReached()` or not `isFinalized`
reverted(claimRefund, goalReached() || !isFinalized)
2. After a RefundableCrowdsale `withdraw` transaction, `msg.sender`’s balance should increase by the original value (before the execution of the `withdraw` transaction) of `balanceOf(msg.sender)` and `balanceOf(msg.sender)` should be `0`.
Let `b` be `msg.sender`’s balance.
finished(withdraw, b = old(b) + old(balanceOf(msg.sender)) && balanceOf(msg.sender) = 0)
## Verification
I'm a bit confused by this question - am I to check if these two statements hold, or that if pre does entail post after `attempt`?
If it's the latter then it does entail, because every state with `started && msg.value > cost` does go through the function correctly and its effect is exactly the postcondition.
And if it's the former:
1. Precondition: `started(Game.attempt(guess), started && msg.value > cost)`
This does not always hold. `attempt(guess)` can be called with `msg.value <= cost` where `require(msg.value > cost)` will fail. And, after any time `attempt(guess)` is called with `result == target` and before any `setTarget(t)` is called, `attempt(guess)` can be called with `!started` in which case `require(started)` will fail.
2. Postcondition: `finished(Game.attempt(guess), value = fsum(Game.attempt(guess), guess))`
This always holds. Every time `Game.attempt(guess)` succeeds, `value` equals to the sum of all the `guess`s from all the time it is run.
## Detection
1. Anyone can call `setTarget`.
2. When `value` is too big, it could be that all the correct `guess`s would overflow `value`.
3. Reentrancy attack is possible where attacker guesses right and then drains the fund before `started` is set to `false`.
## Exploit
I think an exploit is possible because the contract does not check what the input `data` contains before executing it. I'm not sure what exactly can it do, but considering arbitrary code is possible, I assume there is an exploit.
## Tooling
I couldn't set up Typescript and Solidity correctly so I ran the `sol-ast-compile --tree` directly on the example program. I reasoned that, the detection script should, during the traversal of the AST, upon meeting a node of type `FunctionCall`, check if it is an "external" call where there should be a pre-determined list of such calls including `msg.sender.call`, and, if it is, mark the current `Block` and continue the traversal until its end or when an `Assignment` is met, in which case it decides that reentrancy is possible.