To many a tedious chore, documentation is universally understood as being a necessary evil. If one were to ask an engineer why it is important, I posit the first thing they would say is "It helps to onboard new engineers." Ask another engineer, perhaps one well versed in permissionless systems and the answer may differ slightly. They may utter identical words, and perhaps to that, append "In order to fully harness the power of composability present in these open economic structures, documentation is also important to facilitate the integration of protocols!" However, it is hardly the whole picture.
The goal of the documentation is to fill in the gaps and justify design choices that aren't immediately obvious when constructing a mental model of the system. Documentation is the auditor's bible (and an auditor is anyone who performs code reviews).
When an auditor approaches a codebase, it starts off with two premises, "What goals is the system trying to accomplish? How does it try to accomplish them?" A mental model of what the system should be like is then created. Now, the two models shall clash: fiction versus reality!
The auditor is going to hone in on the differences between the two, attempting to find justifications for the various Chesterton's Fences encountered along the way. It is precisely these fences that ought to be documented. Indeed, while documentation must cover the obvious, its true value lies in covering what isn't immediately obvious. What is obvious can be trivially arrived at with minimal effort.
Functions should be accurately described and, in particular, its edge cases and relevant mitigations. If one is unable to formally specify them mathematically, their true purpose must be succinctly described in plain language, and its accounted for behaviors and bounds should be laid out bare for the reader. For example, If one were to write an interest accumulation function, it would be important to document that "this function is positive and monotonic." From this, an auditor can infer that interest accumulation begins at equal or greater than zero and the rate at which it accumulates interest can never be negative. Armed with this knowledge he ventures forth, relentlessly trying to break your shit. The tools and techniques used to protect—unit tests, mutation tests, fuzzing, symbolic execution—are now used to destroy, and destroy they might.
If something was put in place to mitigate a specific consequence, an auditor will try to use the same function to perform different actions to instigate behavior different than what was originally intended. The documentation should list these offshoot behaviors. The auditor will attempt to expand the list and ensure that it strictly adheres to the documented invariants.
I hope this has invigorated you with a newfound appreciation for good documentation.
