-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/invariants #41
Feat/invariants #41
Conversation
I simplified these tests until they just track the management of Eth by the protocol, and found what could be a bug.
However, it is possible to drain eth from the protocol, the sequence:
Doesn't guarantee that the eth balance in Next steps are to build a unit test file, where that specific scenario can be reproduced and debugged. |
feat: moved enum and events to USM.sol
Whoa, interesting! Off the top of my head... I have no idea what's going on here? So I guess that's pretty cool. Will look |
This tool looks like it's going to be really powerful for us... just need to get it to work |
Added a test file to debug the scenarios found by echidna:
With this we can get a detailed output of the scenario, and use
I can track this to |
Try unifying Proxy.mint() and Proxy.mintWithEth() into just Proxy.mint(). (Etc)
Had a quick look... Very interesting! Short version: It comes down to the edge case where the last FUM holder withdraws all their FUM. The simplest fix is probably to change this sketchy
Long version: In the current code, if there's no USM in the pool, and the last FUM holder calls This is only possible because Changing it to This is definitely a strong start for the fuzzer! |
Having said that I won't be too surprised if my proposed change to |
Yup! Broke some stuff. Nothing serious I think... I'll follow up tomorrow. |
(Feel free to toss out ideas about this stuff, the case where the user withdraws all their FUM and "unclaimed" ETH is left is an interesting one, I had thought about it. The fact is we could probably leave the behavior flagged by the fuzzer as is: I strongly doubt all FUM will ever be redeemed, and if it was and some ETH was left and someone claimed it, no real harm done.) |
Thanks @jacob-eliosoff, that was really useful. I can confirm that by adding a |
I split and simplified those fuzzing tests, to make them crystal clear. I'm not too worried if after burning all FUM someone refloats the contracts and gets a little bonus, tbh. If it has an easy fix then let's do it, for robustness, otherwise we can let it be. I'm more interested on other invariant testing, such as managing the ethBuffer and the sliding prices. Let's merge this PR and work on those. Also @jacob-eliosoff, any properties of the system that you can think of in terms of invariants, please let me know and I'll implement them. This is fun. |
This was my original thought too (well, I had In general I think it's cleaner to return numbers that avoid error scenarios, than to add explicit |
I will spend some time today thinking of more invariants! |
Unfortunately,
I'm not sure if there is a fix for this. I think that you would need the That might even be reasonable, to calculate prices on the resulting balances, what do you think? |
Fascinating! I'll have to dig in a bit. |
OK, we were looking at the right edge case (user withdraws last remaining FUM), but I had made TWO simple mistakes in my reasoning here:
So I think we should add back the explicit See my commit I just pushed - please retry the fuzzer... Sorry for the silly mistakes above! Let's see what my next one is... |
Btw my latest commit here breaks the fuzzing test: by design, since that test |
Different approach, instead of disallowing retrieving the last FUM wei, which is rude, we just mint one wei FUM on deployment and lock it away. One less external contract call in the code :D |
The 1 wei thing is clever, but it could have weird effects: if all that's left in the pool is 10 ETH and 1e-18 FUM, then the implied FUM price is 1 FUM = 10^19 ETH... And then next time a user passes ETH to I think the big picture here is these are edge cases that are extremely unlikely to happen and basically harmless if they do, so we should just keep the code maximally simple:
But if any of this seems worse to you feel free to add back your change! |
First pass of fuzzing tests.
To run you need to install echidna and execute: