It would be nice to have a standardized format for comments which can be used for docs, frontend UX in dapps, block explorers etc. We can take inspiration from NatSpec for solidity and vyper. https://docs.soliditylang.org/en/v0.8.11/natspec-format.html
I do not have a strict solution to follow at this moment, but wanted to start this discussion. Like solidity, we can use something in this format:
# @notice Transfer `amount` tokens from caller to `recipient`
# @dev _transfer has all the checks and logic
# @param recipient The address to transfer to
# @param amount The amount to be transferred
# @return success If the transfer was successful or not
@external
func transfer{
syscall_ptr : felt*,
pedersen_ptr : HashBuiltin*,
range_check_ptr
}(recipient: felt, amount: Uint256) -> (success: felt):
let (sender) = get_caller_address()
_transfer(sender, recipient, amount)
# Cairo equivalent to 'return (true)'
return (1)
end
I agree with this and I just visited the forum to suggest exactly this!
I think natspec like solidity (epytext in python?) is quite easy to learn and I would use that over one of the many formats used in Python (numpy-style, google-style, sphinx-style).
In the future it would be nice for tools to display the documentation alongside functions (e.g. in the explorer or wallet)
The following standard provides a consistent way for Cairo contracts and their functionality to be documented. I propose that initially this should just be informational, however in future it could be integrated into the Cairo compiler to allow automated documentation generation.
Motivation
A comment standard increases the readibility of contracts which makes it easier to ensure their correct functionality.
Specification
All tags are optional. The following table explains the purpose of each tag and where it may be used.
A header comment is a comment block that can be placed at the top of each cairo file, immediately following the imports. The header contains general information about the contents of the file including a brief description and an author.
Arrays
When working with arrays, @param and @return tags should only be applied to the pointer variable and not for the length. One can document the contents of the array in this single tag.
Example Contract
# SPDX-License-Identifier: MIT
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.starknet.common.syscalls import get_caller_address
#
# @title Simple Savings Account
# @author Vitalik Buterin - vitalik.buterin@ethereum.org
# @notice A contract to track users' savings in various pots
#
# @dev Stores the balances of each pot
# @param address: Address of the user
# @param pot_index: Index of the pot
# @return amount: The amount stored
@storage_var
func balance(address : felt, pot_index : felt) -> (amount : felt):
end
# @dev Updates a user's balance in a specified pot
# @param amount: Amount to increase the balance by
# @param pot_index: Index of the pot
@external
func increase_balance{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
amount : felt, pot_index : felt
):
let (address) = get_caller_address()
let (current) = balance.read(address, pot_index)
balance.write(address, pot_index, current + amount)
return ()
end
Starting to use it I think it could be useful to also add implicit arguments and types
struct Structure:
member m1: felt
member m2: felt
end
# @dev Updates a user's balance in a specified pot
# @implicit syscall_ptr (felt*)
# @implicit pedersen_ptr (HashBuiltin*)
# @implicit range_check_ptr (felt)
# @param value (felt): A value to do something
# @param structure (Structure*): A pointer to a Structure
# @return res (Structure): A Structure which is not a pointer
@external
func useful_function{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
value : felt, structure : Structure*
) -> (res : Structure):
# code #
return (res)
end
Documenting Implicit arguments would get very repetitive as the same few of them get passed to virtually every function. Also as they are implicit, I don’t see them as necessary for documenting functionality/usage.
Types are specified in the function arguments already so seems redundant to do so again in my opinion. Within the description of the parameter, one can add information about the type if deemed necessary.
Yeah, I agree I went a bit overboard with typing everything, we can definitely infer felt type by default.
Regarding implicit arguments, the idea behind was to have easy access to which implicit args are required (even though, as you said, they are usually the same 3 to 4 ones) and not have to go look into the library’s code everytime. But I guess an improved vscode extension could display the function implicit arguments without the need for them to be described in the docstring.
The following standard provides a consistent way for Cairo contracts and their functionality to be documented. I propose that initially this should just be informational, however in future it could be integrated into the Cairo compiler to allow automated documentation generation.
Motivation
A documentation comment standard increases the readability of contracts which makes it easier to ensure their correct functionality.
Specification
All tags are optional. The following table explains the purpose of each tag and where it may be used. Three slashes (///) should be used to mark each documentation comment instead of the two (//) used for standard comments. For multi-line documentation comments, the tag should only be used on the first line and there should be no tabulation on latter lines.
A header comment is a comment block that can be placed at the top of each cairo file, immediately following the imports. The header contains general information about the contents of the file including a brief description and an author.
Arrays
When working with arrays, @param and @return tags should only be applied to the pointer variable and not for the length. One can document the contents of the array in this single tag.
Example Contract
// SPDX-License-Identifier: MIT
%lang starknet
from starkware.cairo.common.cairo_builtins import HashBuiltin
from starkware.starknet.common.syscalls import get_caller_address
///
/// @title Simple Savings Account
/// @author Vitalik Buterin - vitalik.buterin@ethereum.org
/// @notice A contract to track users' savings in various pots
///
/// @dev Stores the balances of each pot
/// @param address Address of the user
/// @param pot_index Index of the pot
/// @return amount The amount stored
@storage_var
func balance(address : felt, pot_index : felt) -> (amount : felt):
end
/// @dev Updates a user's balance in a specified pot
/// @param amount Amount to increase the balance by
/// @param pot_index Index of the pot
@external
func increase_balance{syscall_ptr : felt*, pedersen_ptr : HashBuiltin*, range_check_ptr}(
amount : felt, pot_index : felt
):
let (address) = get_caller_address()
let (current) = balance.read(address, pot_index)
balance.write(address, pot_index, current + amount)
return ()
end