The Fuel Network ran an Immunefi contest for the entire network. From their custom VM to compilers to the bridge... lots of attack surface. The author of this post dove into the compiler and contract runtime.
When contract A calls contract B, there is an ABI to preform type safety. The arguments are encoded into raw bytes in order to make the actual call in the contract. In the bytecode of the callee contract, there is implicit type information based upon the source code. One has compile time checks and the other has runtime verification on the values.
In the EVM, extra data at the end or in the middle of a structure is ignored. If the type is completely incorrect (like a string where an integer should be), then it reverts. This is more a Solidity compiler added protection than an actual protection added by the VM.
In Fuel, if an extra value is added to a struct it's not ignored - it corrupts the next value! For instance, if a struct only had a value called key with 32 bytes but we passed in an extra u8. The value of the u8 is just added to the next type instead of being ignored. All types keep their size but can be changed to unexpected values. I'm guessing that this corruption happening after the verification of the type but I'm not entirely sure from the post.
Why is this useful? The boolean type is usually guaranteed to either be a 0 or a 1. Given that the compiler knows this, it will do checks in weird ways that may be bypassable. The author provides an if statement with two options: option == true and option == false without an else clause. Since a boolean value of 100 wouldn't fall into either of these, we can break logic that assumes a binary value for a boolean.
An additional impact is that a boolean could be stored with a non-zero value in storage. This could cause a DoS when loading the value or cause more corruption as well. An interesting impact is that since this happened in the compiled code, all deployed code would have to be redeployed with a new version of the compiler.
I'm slightly confused on why the corruption must happen. From my end, it appears that we could just make a boolean any value. My guess is that there is verification in the compiled code that happens first then the decoding happens that corrupts the values. Interesting bug and thanks for sharing!