A contract tells what needs to be known to use the function. It does not tell how the function works. It does not tell what the local variables are used for, why there is a loop, or anything like that.
A contract necessarily tells in what way every parameter affects the function. A contract must discuss every parameter. Always discuss parameters by name, never referring to a parameter called n, for example, as "the number".
If a function returns a value, the contract must explain what is returned.
A function must take credit or blame for the actions of any other functions that it calls. The contract for a function must tell the entire effect of a function, including what happens as a result of functions that it calls.
A contract does not tell how a function fits into the overall program. For example, suppose there is a parameter called n that is passed to function f. When f is used, suppose that n happens to be a number that was typed to the program by the user. That is, the actual parameter was given to the program by the user. When describing f, do not say that n (the formal parameter) is the number typed in by the user. The reason is that it is not function f that has interacted with the user, but some other part of the program. Function f has just been given a number, and it does not care where that number came from. In general, when describing a tool, avoid describing the details of what some other part of the program will do with this tool. Instead, tell what the tool does in general.
Contracts should be written in complete sentences with correct grammar and punctuation. That does not preclude the use of technical terms or mathematical notation. Just make the contact clear.
A contract should not be excessively wordy. Make the contract as concise and to-the-point as possible without sacrificing correctness or completeness.
Avoid margin comments. Instead, use paragraph comments. A paragraph comment consists of a short paragraph describing what the next block of code does, and is followed by a short block of code. Indent the comments to the same level as the code that it describes.
Avoid throw-away comments that simply restate what the code says. Assume that the reader understands the programming language. Instead, describe the intent of a paragraph, and how it fits into the solution of the function.
Sometimes a function body begins with a paragraph that describes the algorithm that the function uses. That is fine. It is also often a good idea to give comments describing what variables are used for, but only if the comment is informative.
Use sensible variable names. Wherever possible, use descriptive names. But do not go to such an extreme that your variable names are too long for convenience.
You may use a global variable when it is appropriate. However, I insist that every global variable be accompanied by a clear paragraph describing, in detail, what it is used for and why it needs to be a global variable. If I disagree with the reasoning, I will grade you down.