Skip to content

Commit

Permalink
feat(docs): document Ownable (#207)
Browse files Browse the repository at this point in the history
Resolves #206 & #12
  • Loading branch information
alexfertel authored Jul 23, 2024
1 parent 1c23e10 commit 4b07d68
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 55 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,12 @@ a `Cargo.toml`, like so:
openzeppelin-stylus = { git = "https://github.com/OpenZeppelin/rust-contracts-stylus" }
```

We recommend pinning to a specific version -- expect rapid iteration. Also note
that the library's name has yet to be decided.
We recommend pinning to a specific version -- expect rapid iteration.

Once defined as a dependency, use one of our pre-defined implementations by
importing them:

```rust,ignore
```rust
use openzeppelin_stylus::token::erc20::Erc20;

sol_storage! {
Expand Down Expand Up @@ -85,4 +84,4 @@ Refer to our [Security Policy](SECURITY.md) for more details.

## License

OpenZeppelin Contracts for Stylus is released under the [MIT License](LICENSE).
OpenZeppelin Contracts for Stylus is released under the [MIT License](./LICENSE).
8 changes: 4 additions & 4 deletions contracts/src/access/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
//!
//! ```rust,ignore
//! pub fn foo() {
//! assert!(self.has_role(MY_ROLE.into(), msg::sender());
//! ...
//! assert!(self.has_role(MY_ROLE.into(), msg::sender()));
//! // ...
//! }
//! ```
//!
Expand All @@ -42,7 +42,7 @@
//! `AccessControlDefaultAdminRules` to enforce additional security measures for
//! this role.
//!
//! [enumerable ext]: TBD
//! [enumerable ext]: ./TODO
use alloy_primitives::{Address, B256};
use alloy_sol_types::sol;
use stylus_proc::SolidityError;
Expand Down Expand Up @@ -153,7 +153,7 @@ impl AccessControl {
/// Returns the admin role that controls `role`. See [`Self::grant_role`]
/// and [`Self::revoke_role`].
///
/// To change a role's admin, use [`Self::set_role_admin`].
/// To change a role's admin, use [`Self::_set_role_admin`].
///
/// # Arguments
///
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/access/ownable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl Ownable {
/// # Errors
///
/// If `new_owner` is the zero address, then the error
/// [`Error::OwnableInvalidOwner`] is returned.
/// [`OwnableInvalidOwner`] is returned.
pub fn transfer_ownership(
&mut self,
new_owner: Address,
Expand All @@ -108,7 +108,7 @@ impl Ownable {
}

/// Leaves the contract without owner. It will not be possible to call
/// [`only_owner`] functions. Can only be called by the current owner.
/// [`Self::only_owner`] functions. Can only be called by the current owner.
///
/// NOTE: Renouncing ownership will leave the contract without an owner,
/// thereby disabling any functionality that is only available to the owner.
Expand Down
46 changes: 45 additions & 1 deletion contracts/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
#![doc = include_str!("../../README.md")]
/*!
# OpenZeppelin Contracts for Stylus
A library for secure smart contract development written in Rust for
[Arbitrum Stylus](https://docs.arbitrum.io/stylus/stylus-gentle-introduction).
This library offers common smart contract primitives and affordances that take
advantage of the nature of Stylus.
> This project is still in a very early and experimental phase. It has never
> been audited nor thoroughly reviewed for security vulnerabilities. Do not use
> in production.
## Usage
To start using it, add `openzeppelin-stylus` to your `Cargo.toml`, or simply run
`cargo add openzeppelin-stylus`.
```toml
[dependencies]
openzeppelin-stylus = "x.x.x"
```
We recommend pinning to a specific version -- expect rapid iteration.
Once defined as a dependency, use one of our pre-defined implementations by
importing them:
```ignore
use openzeppelin_stylus::token::erc20::Erc20;
sol_storage! {
#[entrypoint]
struct MyContract {
#[borrow]
Erc20 erc20;
}
}
#[external]
#[inherit(Erc20)]
impl MyContract { }
```
*/

#![allow(clippy::pub_underscore_fields, clippy::module_name_repetitions)]
#![cfg_attr(not(feature = "std"), no_std, no_main)]
#![deny(rustdoc::broken_intra_doc_links)]
extern crate alloc;

#[global_allocator]
Expand Down
12 changes: 6 additions & 6 deletions contracts/src/token/erc20/extensions/burnable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use crate::token::erc20::{Erc20, Error};
/// their own tokens and those that they have an allowance for,
/// in a way that can be recognized off-chain (via event analysis).
pub trait IErc20Burnable {
/// Destroys a `value` amount of tokens from the caller.
/// lowering the total supply.
/// Destroys a `value` amount of tokens from the caller. lowering the total
/// supply.
///
/// Relies on the `update` mechanism.
///
Expand All @@ -25,11 +25,11 @@ pub trait IErc20Burnable {
///
/// # Events
///
/// Emits a [`Transfer`] event.
/// Emits a [`super::super::Transfer`] event.
fn burn(&mut self, value: U256) -> Result<(), Error>;

/// Destroys a `value` amount of tokens from `account`,
/// lowering the total supply.
/// Destroys a `value` amount of tokens from `account`, lowering the total
/// supply.
///
/// Relies on the `update` mechanism.
///
Expand All @@ -49,7 +49,7 @@ pub trait IErc20Burnable {
///
/// # Events
///
/// Emits a [`Transfer`] event.
/// Emits a [`super::super::Transfer`] event.
fn burn_from(&mut self, account: Address, value: U256)
-> Result<(), Error>;
}
Expand Down
5 changes: 3 additions & 2 deletions contracts/src/token/erc20/extensions/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub const DEFAULT_DECIMALS: u8 = 18;
use crate::utils::Metadata;

sol_storage! {
/// Metadata of the [`Erc20`] token.
/// Metadata of the [`super::super::Erc20`] token.
///
/// It has hardcoded `decimals` to [`DEFAULT_DECIMALS`].
pub struct Erc20Metadata {
Expand Down Expand Up @@ -51,7 +51,8 @@ pub trait IErc20Metadata {
///
/// NOTE: This information is only used for *display* purposes: in
/// no way it affects any of the arithmetic of the contract, including
/// [`Erc20::balance_of`] and [`Erc20::transfer`].
/// [`super::super::IErc20::balance_of`] and
/// [`super::super::IErc20::transfer`].
fn decimals(&self) -> u8;
}

Expand Down
20 changes: 11 additions & 9 deletions contracts/src/token/erc721/extensions/burnable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ use crate::token::erc721::{Erc721, Error};
/// An [`Erc721`] token that can be burned (destroyed).
pub trait IErc721Burnable {
/// Burns `token_id`.
/// The approval is cleared when the token is burned.
/// Relies on the `_burn` mechanism.
///
/// The approval is cleared when the token is burned. Relies on the `_burn`
/// mechanism.
///
/// # Arguments
///
/// * `value` - Amount to be burnt.
///
/// # Errors
///
/// If token does not exist, then the error
/// [`Error::NonexistentToken`] is returned.
/// If token does not exist, then the error [`Error::NonexistentToken`] is
/// returned.
/// If the caller does not have the right to approve, then the error
/// [`Error::InsufficientApproval`] is returned.
///
Expand All @@ -29,17 +30,18 @@ pub trait IErc721Burnable {
///
/// # Events
///
/// Emits a [`Transfer`] event.
/// Emits a [`super::super::Transfer`] event.
fn burn(&mut self, token_id: U256) -> Result<(), Error>;
}

impl IErc721Burnable for Erc721 {
fn burn(&mut self, token_id: U256) -> Result<(), Error> {
// Setting an "auth" arguments enables the [`Erc721::_is_authorized`]
// check which verifies that the token exists (from != `Address::ZERO`).
// Setting an "auth" arguments enables the
// [`super::super::Erc721::_is_authorized`] check which verifies that
// the token exists (from != `Address::ZERO`).
//
// Therefore, it is not needed to verify
// that the return value is not 0 here.
// Therefore, it is not needed to verify that the return value is not 0
// here.
self._update(Address::ZERO, token_id, msg::sender())?;
Ok(())
}
Expand Down
36 changes: 20 additions & 16 deletions contracts/src/token/erc721/extensions/enumerable.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
//! Optional `Enumerable` extension of the ERC-721 standard.
//!
//! This implements an optional extension of [`Erc721`] defined in the EIP
//! that adds enumerability of all the token ids in the contract
//! as well as all token ids owned by each account.
//! This implements an optional extension of [`super::super::Erc721`] defined in
//! the EIP that adds enumerability of all the token ids in the contract as well
//! as all token ids owned by each account.
//!
//! CAUTION: [`Erc721`] extensions that implement custom
//! [`Erc721::balance_of`] logic, such as [`Erc721Consecutive`], interfere with
//! enumerability and should not be used together with [`Erc721Enumerable`].
//! CAUTION: [`super::super::Erc721`] extensions that implement custom
//! [`super::super::Erc721::balance_of`] logic, such as `Erc721Consecutive`,
//! interfere with enumerability and should not be used together with
//! [`Erc721Enumerable`].
// TODO: Add link for `Erc721Consecutive` to module docs.

use alloy_primitives::{uint, Address, U256};
use alloy_sol_types::sol;
use stylus_proc::{external, sol_storage, SolidityError};
Expand Down Expand Up @@ -63,20 +66,20 @@ sol_storage! {
pub trait IErc721Enumerable {
// TODO: fn supports_interface (#33)

/// Returns a token ID owned by `owner`
/// at a given `index` of its token list.
/// Returns a token ID owned by `owner` at a given `index` of its token
/// list.
///
/// Use along with [`Erc721::balance_of`]
/// to enumerate all of `owner`'s tokens.
/// Use along with [`super::super::Erc721::balance_of`] to enumerate all of
/// `owner`'s tokens.
///
/// # Arguments
///
/// * `&self` - Read access to the contract's state.
///
/// # Errors
///
/// * If an `owner`'s token query is out of bounds for `index`,
/// then the error [`Error::OutOfBoundsIndex`] is returned.
/// * If an `owner`'s token query is out of bounds for `index`, then the
/// error [`Error::OutOfBoundsIndex`] is returned.
fn token_of_owner_by_index(
&self,
owner: Address,
Expand All @@ -93,7 +96,8 @@ pub trait IErc721Enumerable {
/// Returns a token ID at a given `index` of all the tokens
/// stored by the contract.
///
/// Use along with [`Erc721::total_supply`] to enumerate all tokens.
/// Use along with [`Self::total_supply`] to
/// enumerate all tokens.
///
/// # Arguments
///
Expand Down Expand Up @@ -149,7 +153,7 @@ impl Erc721Enumerable {
/// # Errors
///
/// If owner address is `Address::ZERO`, then the error
/// [`Error::InvalidOwner`] is returned.
/// [`crate::token::erc721::Error::InvalidOwner`] is returned.
pub fn _add_token_to_owner_enumeration(
&mut self,
to: Address,
Expand Down Expand Up @@ -200,7 +204,7 @@ impl Erc721Enumerable {
/// # Errors
///
/// If owner address is `Address::ZERO`, then the error
/// [`Error::InvalidOwner`] is returned.
/// [`crate::token::erc721::Error::InvalidOwner`] is returned.
pub fn _remove_token_from_owner_enumeration(
&mut self,
from: Address,
Expand Down Expand Up @@ -283,7 +287,7 @@ impl Erc721Enumerable {
self._all_tokens.pop();
}

/// See [`Erc721::_increase_balance`].
/// See [`crate::token::erc721::Erc721::_increase_balance`].
/// Check if tokens can be minted in batch.
///
/// Mechanism to be consistent with [Solidity version](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.0/contracts/token/ERC721/extensions/ERC721Enumerable.sol#L163-L171)
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/token/erc721/extensions/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use stylus_proc::{external, sol_storage};
use crate::utils::Metadata;

sol_storage! {
/// Metadata of the [`Erc721`] token.
/// Metadata of an [`crate::token::erc721::Erc721`] token.
pub struct Erc721Metadata {
/// Common Metadata.
Metadata _metadata;
/// Base URI for tokens
/// Base URI for tokens.
string _base_uri;
}
}
Expand Down
10 changes: 5 additions & 5 deletions contracts/src/token/erc721/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ pub trait IErc721 {
/// * `to` - Account of the recipient.
/// * `token_id` - Token id as a number.
/// * `data` - Additional data with no specified format, sent in the call to
/// [`Self::_check_on_erc721_received`].
/// [`Erc721::_check_on_erc721_received`].
///
/// # Errors
///
Expand All @@ -293,7 +293,7 @@ pub trait IErc721 {
/// * `to` cannot be the zero address.
/// * The `token_id` token must exist and be owned by `from`.
/// * If the caller is not `from`, it must be approved to move this token by
/// either [`Self::_approve`] or [`Self::set_approval_for_all`].
/// either [`Erc721::_approve`] or [`Erc721::set_approval_for_all`].
/// * If `to` refers to a smart contract, it must implement
/// [`IERC721Receiver::on_erc_721_received`], which is called upon a
/// `safe_transfer`.
Expand Down Expand Up @@ -369,7 +369,7 @@ pub trait IErc721 {
///
/// If the token does not exist, then the error
/// [`Error::NonexistentToken`] is returned.
/// If `auth` (param of [`Self::_approve`]) does not have a right to
/// If `auth` (param of [`Erc721::_approve`]) does not have a right to
/// approve this token, then the error
/// [`Error::InvalidApprover`] is returned.
///
Expand Down Expand Up @@ -845,7 +845,7 @@ impl Erc721 {
/// If `to` is `Address::ZERO`, then the error
/// [`Error::InvalidReceiver`] is returned.
/// If `token_id` does not exist, then the error
/// [`Error::ERC721NonexistentToken`] is returned.
/// [`ERC721NonexistentToken`] is returned.
/// If the previous owner is not `from`, then the error
/// [`Error::IncorrectOwner`] is returned.
///
Expand Down Expand Up @@ -909,7 +909,7 @@ impl Erc721 {
/// If `to` is `Address::ZERO`, then the error
/// [`Error::InvalidReceiver`] is returned.
/// If `token_id` does not exist, then the error
/// [`Error::ERC721NonexistentToken`] is returned.
/// [`ERC721NonexistentToken`] is returned.
/// If the previous owner is not `from`, then the error
/// [`Error::IncorrectOwner`] is returned.
///
Expand Down
1 change: 1 addition & 0 deletions docs/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
* xref:index.adoc[Overview]
* xref:access-control.adoc[Access Control]
* xref:crypto.adoc[Cryptography]
Loading

0 comments on commit 4b07d68

Please sign in to comment.