diff --git a/src/access/accesscontrol/accesscontrol.cairo b/src/access/accesscontrol/accesscontrol.cairo index c97afb258..e4a2b0d6c 100644 --- a/src/access/accesscontrol/accesscontrol.cairo +++ b/src/access/accesscontrol/accesscontrol.cairo @@ -91,7 +91,7 @@ mod AccessControlComponent { /// /// Requirements: /// - /// - the caller must have `role`'s admin role. + /// - The caller must have `role`'s admin role. fn grant_role( ref self: ComponentState, role: felt252, account: ContractAddress ) { @@ -106,7 +106,7 @@ mod AccessControlComponent { /// /// Requirements: /// - /// - the caller must have `role`'s admin role. + /// - The caller must have `role`'s admin role. fn revoke_role( ref self: ComponentState, role: felt252, account: ContractAddress ) { @@ -126,7 +126,7 @@ mod AccessControlComponent { /// /// Requirements: /// - /// - the caller must be `account`. + /// - The caller must be `account`. fn renounce_role( ref self: ComponentState, role: felt252, account: ContractAddress ) { diff --git a/src/access/ownable/ownable.cairo b/src/access/ownable/ownable.cairo index 78ec49fe9..9f7ad5dd6 100644 --- a/src/access/ownable/ownable.cairo +++ b/src/access/ownable/ownable.cairo @@ -48,6 +48,13 @@ mod OwnableComponent { } /// Transfers ownership of the contract to a new address. + /// + /// Requirements: + /// + /// - `new_owner` is not the zero address. + /// - The caller is the contract owner. + /// + /// Emits an `OwnershipTransferred` event. fn transfer_ownership( ref self: ComponentState, new_owner: ContractAddress ) { @@ -58,6 +65,12 @@ mod OwnableComponent { /// Leaves the contract without owner. It will not be possible to call `assert_only_owner` /// functions anymore. Can only be called by the current owner. + /// + /// Requirements: + /// + /// - The caller is the contract owner. + /// + /// Emits an `OwnershipTransferred` event. fn renounce_ownership(ref self: ComponentState) { self.assert_only_owner(); self._transfer_ownership(Zeroable::zero()); @@ -101,6 +114,8 @@ mod OwnableComponent { /// Transfers ownership of the contract to a new address. /// /// Internal function without access restriction. + /// + /// Emits an `OwnershipTransferred` event. fn _transfer_ownership( ref self: ComponentState, new_owner: ContractAddress ) { diff --git a/src/account/account.cairo b/src/account/account.cairo index 8223ae999..07a991335 100644 --- a/src/account/account.cairo +++ b/src/account/account.cairo @@ -56,6 +56,11 @@ mod AccountComponent { +Drop > of interface::ISRC6> { /// Executes a list of calls from the account. + /// + /// Requirements: + /// + /// - The transaction version must be `TRANSACTION_VERSION` for actual transactions. + /// For simulations, the version must be `QUERY_VERSION`. fn __execute__( self: @ComponentState, mut calls: Array ) -> Array> { @@ -140,6 +145,12 @@ mod AccountComponent { } /// Sets the public key of the account to `new_public_key`. + /// + /// Requirements: + /// + /// - The caller must be the contract itself. + /// + /// Emits an `OwnerRemoved` event. fn set_public_key(ref self: ComponentState, new_public_key: felt252) { self.assert_only_self(); self.emit(OwnerRemoved { removed_owner_guid: self.Account_public_key.read() }); @@ -213,6 +224,8 @@ mod AccountComponent { /// Sets the public key without validating the caller. /// The usage of this method outside the `set_public_key` function is discouraged. + /// + /// Emits an `OwnerAdded` event. fn _set_public_key(ref self: ComponentState, new_public_key: felt252) { self.Account_public_key.write(new_public_key); self.emit(OwnerAdded { new_owner_guid: new_public_key }); diff --git a/src/introspection/src5.cairo b/src/introspection/src5.cairo index fa47feb1b..1b5b1f79f 100644 --- a/src/introspection/src5.cairo +++ b/src/introspection/src5.cairo @@ -51,6 +51,10 @@ mod SRC5Component { } /// Deregisters the given interface as supported by the contract. + /// + /// Requirements: + /// + /// - `interface_id` is not `ISRC5_ID` fn deregister_interface(ref self: ComponentState, interface_id: felt252) { assert(interface_id != interface::ISRC5_ID, Errors::INVALID_ID); self.SRC5_supported_interfaces.write(interface_id, false); diff --git a/src/security/initializable.cairo b/src/security/initializable.cairo index 43bf4cd4a..1aa9310f6 100644 --- a/src/security/initializable.cairo +++ b/src/security/initializable.cairo @@ -34,6 +34,10 @@ mod InitializableComponent { TContractState, +HasComponent > of InternalTrait { /// Ensures the calling function can only be called once. + /// + /// Requirements: + /// + /// - `initialize` was not previously called. fn initialize(ref self: ComponentState) { assert(!self.is_initialized(), Errors::INITIALIZED); self.Initializable_initialized.write(true); diff --git a/src/security/pausable.cairo b/src/security/pausable.cairo index 8d833407c..c6442509d 100644 --- a/src/security/pausable.cairo +++ b/src/security/pausable.cairo @@ -67,7 +67,12 @@ mod PausableComponent { } /// Triggers a stopped state. - /// The contract must not already be paused. + /// + /// Requirements: + /// + /// - The contract is not paused. + /// + /// Emits a `Paused` event. fn _pause(ref self: ComponentState) { self.assert_not_paused(); self.Pausable_paused.write(true); @@ -75,7 +80,12 @@ mod PausableComponent { } /// Lifts the pause on the contract. - /// The contract must already be paused. + /// + /// Requirements: + /// + /// - The contract is paused. + /// + /// Emits an `Unpaused` event. fn _unpause(ref self: ComponentState) { self.assert_paused(); self.Pausable_paused.write(false); diff --git a/src/tests/mocks/upgrades_mocks.cairo b/src/tests/mocks/upgrades_mocks.cairo index 689a385ec..e5d154f4b 100644 --- a/src/tests/mocks/upgrades_mocks.cairo +++ b/src/tests/mocks/upgrades_mocks.cairo @@ -22,7 +22,6 @@ trait UpgradesV1Trait { mod UpgradesV1 { use openzeppelin::upgrades::UpgradeableComponent; use starknet::ClassHash; - use starknet::ContractAddress; component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); @@ -81,7 +80,6 @@ trait UpgradesV2Trait { mod UpgradesV2 { use openzeppelin::upgrades::UpgradeableComponent; use starknet::ClassHash; - use starknet::ContractAddress; component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent); diff --git a/src/token/erc20/erc20.cairo b/src/token/erc20/erc20.cairo index e4d1e3c67..2198b130f 100644 --- a/src/token/erc20/erc20.cairo +++ b/src/token/erc20/erc20.cairo @@ -83,8 +83,7 @@ mod ERC20Component { /// Returns the remaining number of tokens that `spender` is /// allowed to spend on behalf of `owner` through `transfer_from`. /// This is zero by default. - /// This value changes when `approve` or `transfer_from` - /// are called. + /// This value changes when `approve` or `transfer_from` are called. fn allowance( self: @ComponentState, owner: ContractAddress, spender: ContractAddress ) -> u256 { @@ -92,6 +91,12 @@ mod ERC20Component { } /// Moves `amount` tokens from the caller's token balance to `to`. + /// + /// Requirements: + /// + /// - `recipient` is not the zero address. + /// - The caller has a balance of at least `amount`. + /// /// Emits a `Transfer` event. fn transfer( ref self: ComponentState, recipient: ContractAddress, amount: u256 @@ -103,6 +108,14 @@ mod ERC20Component { /// Moves `amount` tokens from `from` to `to` using the allowance mechanism. /// `amount` is then deducted from the caller's allowance. + /// + /// Requirements: + /// + /// - `sender` is not the zero address. + /// - `sender` must have a balance of at least `amount`. + /// - `recipient` is not the zero address. + /// - The caller has an allowance of `sender`'s tokens of at least `amount`. + /// /// Emits a `Transfer` event. fn transfer_from( ref self: ComponentState, @@ -117,6 +130,12 @@ mod ERC20Component { } /// Sets `amount` as the allowance of `spender` over the caller’s tokens. + /// + /// Requirements: + /// + /// - `spender` is not the zero address. + /// + /// Emits an `Approval` event. fn approve( ref self: ComponentState, spender: ContractAddress, amount: u256 ) -> bool { @@ -151,6 +170,11 @@ mod ERC20Component { TContractState, +HasComponent > of interface::ISafeAllowance> { /// Increases the allowance granted from the caller to `spender` by `added_value`. + /// + /// Requirements: + /// + /// - `spender` is not the zero address. + /// /// Emits an `Approval` event indicating the updated allowance. fn increase_allowance( ref self: ComponentState, spender: ContractAddress, added_value: u256 @@ -159,6 +183,12 @@ mod ERC20Component { } /// Decreases the allowance granted from the caller to `spender` by `subtracted_value`. + /// + /// Requirements: + /// + /// - `spender` is not the zero address. + /// - `spender` must have at least an allowance of `subtracted_value`. + /// /// Emits an `Approval` event indicating the updated allowance. fn decrease_allowance( ref self: ComponentState, @@ -228,6 +258,13 @@ mod ERC20Component { } /// Internal method that moves an `amount` of tokens from `from` to `to`. + /// + /// Requirements: + /// + /// - `sender` is not the zero address. + /// - `sender` must have at least a balance of `amount`. + /// - `recipient` is not the zero address. + /// /// Emits a `Transfer` event. fn _transfer( ref self: ComponentState, @@ -244,6 +281,12 @@ mod ERC20Component { /// Internal method that sets `amount` as the allowance of `spender` over the /// `owner`s tokens. + /// + /// Requirements: + /// + /// - `owner` is not the zero address. + /// - `spender` is not the zero address. + /// /// Emits an `Approval` event. fn _approve( ref self: ComponentState, @@ -258,6 +301,11 @@ mod ERC20Component { } /// Creates a `value` amount of tokens and assigns them to `account`. + /// + /// Requirements: + /// + /// - `recipient` is not the zero address. + /// /// Emits a `Transfer` event with `from` set to the zero address. fn _mint( ref self: ComponentState, recipient: ContractAddress, amount: u256 @@ -268,7 +316,13 @@ mod ERC20Component { self.emit(Transfer { from: Zeroable::zero(), to: recipient, value: amount }); } - /// Destroys a `value` amount of tokens from `account`. + /// Destroys `amount` of tokens from `account`. + /// + /// Requirements: + /// + /// - `account` is not the zero address. + /// - `account` must have at least a balance of `amount`. + /// /// Emits a `Transfer` event with `to` set to the zero address. fn _burn(ref self: ComponentState, account: ContractAddress, amount: u256) { assert(!account.is_zero(), Errors::BURN_FROM_ZERO); @@ -291,6 +345,11 @@ mod ERC20Component { } /// Internal method for the external `decrease_allowance`. + /// + /// Requirements: + /// + /// - `spender` must have at least an allowance of `subtracted_value` from caller. + /// /// Emits an `Approval` event indicating the updated allowance. fn _decrease_allowance( ref self: ComponentState, @@ -309,6 +368,11 @@ mod ERC20Component { /// Updates `owner`s allowance for `spender` based on spent `amount`. /// Does not update the allowance value in case of infinite allowance. + /// + /// Requirements: + /// + /// - `spender` must have at least an allowance of `amount` from `owner`. + /// /// Possibly emits an `Approval` event. fn _spend_allowance( ref self: ComponentState, diff --git a/src/token/erc721/erc721.cairo b/src/token/erc721/erc721.cairo index 95535891f..e47e8f468 100644 --- a/src/token/erc721/erc721.cairo +++ b/src/token/erc721/erc721.cairo @@ -226,8 +226,11 @@ mod ERC721Component { } /// Returns the Uniform Resource Identifier (URI) for the `token_id` token. - /// /// If the URI is not set for the `token_id`, the return value will be `0`. + /// + /// Requirements: + /// + /// - `token_id` exists. fn token_uri(self: @ComponentState, token_id: u256) -> felt252 { assert(self._exists(token_id), Errors::INVALID_TOKEN_ID); self.ERC721_token_uri.read(token_id) @@ -390,9 +393,13 @@ mod ERC721Component { } /// Mints `token_id` and transfers it to `to`. - /// /// Internal function without access restriction. /// + /// Requirements: + /// + /// - `to` is not the zero address. + /// - `token_id` does not exist. + /// /// Emits a `Transfer` event. fn _mint(ref self: ComponentState, to: ContractAddress, token_id: u256) { assert(!to.is_zero(), Errors::INVALID_RECEIVER); diff --git a/src/upgrades/upgradeable.cairo b/src/upgrades/upgradeable.cairo index 312a45821..075a295bf 100644 --- a/src/upgrades/upgradeable.cairo +++ b/src/upgrades/upgradeable.cairo @@ -31,6 +31,13 @@ mod UpgradeableComponent { impl InternalImpl< TContractState, +HasComponent > of InternalTrait { + /// Replaces the contract's class hash with `new_class_hash`. + /// + /// Requirements: + /// + /// - `new_class_hash` is not the zero address. + /// + /// Emits an `Upgraded` event. fn _upgrade(ref self: ComponentState, new_class_hash: ClassHash) { assert(!new_class_hash.is_zero(), Errors::INVALID_CLASS); starknet::replace_class_syscall(new_class_hash).unwrap();