Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: ERC721Wrapper extension #461

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions contracts/src/token/erc721/extensions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod consecutive;
pub mod enumerable;
pub mod metadata;
pub mod uri_storage;
pub mod wrapper;

pub use burnable::IErc721Burnable;
pub use enumerable::{Erc721Enumerable, IErc721Enumerable};
Expand Down
85 changes: 85 additions & 0 deletions contracts/src/token/erc721/extensions/wrapper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//! Extension of the ERC-721 token contract to support token wrapping.
//!
//! Users can deposit and withdraw an "underlying token" and receive a "wrapped
//! token" with a matching tokenId. This is useful in conjunction with other
//! modules.
use alloc::{vec, vec::Vec};

use alloy_primitives::{Address, U256};
use stylus_sdk::{contract, prelude::storage, stylus_proc::SolidityError};

use crate::token::{
erc721,
erc721::{ERC721IncorrectOwner, Erc721, IErc721},
};

/// State of an [`Erc721Wrapper`] token.
#[storage]
pub struct Erc721Wrapper {
/// Erc721 contract storage.
pub _underlying: Erc721,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bidzyyys What should the type of _underlying be?

/// The ERC-721 token.
pub erc721: Erc721,
}

pub use sol::*;
#[cfg_attr(coverage_nightly, coverage(off))]
mod sol {
use alloy_sol_macro::sol;

sol! {
/// The received ERC-721 token couldn't be wrapped.
#[derive(Debug)]
#[allow(missing_docs)]
error ERC721UnsupportedToken(uint256 token_id);
}
}

/// An [`Erc721Wrapper`] error.
#[derive(SolidityError, Debug)]
pub enum Error {
/// Error type from [`Erc721`] contract [`erc721::Error`].
Erc721(erc721::Error),
/// The received ERC-721 token couldn't be wrapped.
ERC721UnsupportedToken(ERC721UnsupportedToken),
}

impl Erc721Wrapper {
/// Wraps an ERC-721 token.
pub fn deposit_for(
&mut self,
account: Address,

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / wasm32-unknown-unknown

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / stable / clippy

[clippy] reported by reviewdog 🐶 warning: unused variable: `account` --> contracts/src/token/erc721/extensions/wrapper.rs:51:9 | 51 | account: Address, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_account` Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:51:9:w:warning: unused variable: `account` --> contracts/src/token/erc721/extensions/wrapper.rs:51:9 | 51 | account: Address, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_account` __END__

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / beta / clippy

[clippy] reported by reviewdog 🐶 warning: unused variable: `account` --> contracts/src/token/erc721/extensions/wrapper.rs:51:9 | 51 | account: Address, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_account` Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:51:9:w:warning: unused variable: `account` --> contracts/src/token/erc721/extensions/wrapper.rs:51:9 | 51 | account: Address, | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_account` __END__

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / macos-latest / stable

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Check WASM binary

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Gas usage report

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Gas usage report

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / tests

unused variable: `account`

Check warning on line 51 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / tests

unused variable: `account`
token_ids: Vec<U256>,

Check warning on line 52 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / stable / clippy

[clippy] reported by reviewdog 🐶 warning: this argument is passed by value, but not consumed in the function body --> contracts/src/token/erc721/extensions/wrapper.rs:52:20 | 52 | token_ids: Vec<U256>, | ^^^^^^^^^ help: consider changing the type to: `&[U256]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value = note: `-W clippy::needless-pass-by-value` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::needless_pass_by_value)]` Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:52:20:w:warning: this argument is passed by value, but not consumed in the function body --> contracts/src/token/erc721/extensions/wrapper.rs:52:20 | 52 | token_ids: Vec<U256>, | ^^^^^^^^^ help: consider changing the type to: `&[U256]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value = note: `-W clippy::needless-pass-by-value` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::needless_pass_by_value)]` __END__

Check warning on line 52 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / beta / clippy

[clippy] reported by reviewdog 🐶 warning: this argument is passed by value, but not consumed in the function body --> contracts/src/token/erc721/extensions/wrapper.rs:52:20 | 52 | token_ids: Vec<U256>, | ^^^^^^^^^ help: consider changing the type to: `&[U256]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value = note: `-W clippy::needless-pass-by-value` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::needless_pass_by_value)]` Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:52:20:w:warning: this argument is passed by value, but not consumed in the function body --> contracts/src/token/erc721/extensions/wrapper.rs:52:20 | 52 | token_ids: Vec<U256>, | ^^^^^^^^^ help: consider changing the type to: `&[U256]` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_pass_by_value = note: `-W clippy::needless-pass-by-value` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::needless_pass_by_value)]` __END__
) -> bool {
let length = token_ids.len();

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / wasm32-unknown-unknown

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / stable / clippy

[clippy] reported by reviewdog 🐶 warning: unused variable: `length` --> contracts/src/token/erc721/extensions/wrapper.rs:54:13 | 54 | let length = token_ids.len(); | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_length` | = note: `#[warn(unused_variables)]` on by default Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:54:13:w:warning: unused variable: `length` --> contracts/src/token/erc721/extensions/wrapper.rs:54:13 | 54 | let length = token_ids.len(); | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_length` | = note: `#[warn(unused_variables)]` on by default __END__

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / beta / clippy

[clippy] reported by reviewdog 🐶 warning: unused variable: `length` --> contracts/src/token/erc721/extensions/wrapper.rs:54:13 | 54 | let length = token_ids.len(); | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_length` | = note: `#[warn(unused_variables)]` on by default Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:54:13:w:warning: unused variable: `length` --> contracts/src/token/erc721/extensions/wrapper.rs:54:13 | 54 | let length = token_ids.len(); | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_length` | = note: `#[warn(unused_variables)]` on by default __END__

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / macos-latest / stable

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Check WASM binary

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / ubuntu / stable / features

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Gas usage report

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / Gas usage report

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / tests

unused variable: `length`

Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / tests

unused variable: `length`

true
}

/// Returns the underlying token.
pub fn underlying(&self) -> &Erc721 {

Check warning on line 60 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / stable / clippy

[clippy] reported by reviewdog 🐶 warning: this method could have a `#[must_use]` attribute --> contracts/src/token/erc721/extensions/wrapper.rs:60:5 | 60 | pub fn underlying(&self) -> &Erc721 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn underlying(&self) -> &Erc721` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate = note: `-W clippy::must-use-candidate` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::must_use_candidate)]` Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:60:5:w:warning: this method could have a `#[must_use]` attribute --> contracts/src/token/erc721/extensions/wrapper.rs:60:5 | 60 | pub fn underlying(&self) -> &Erc721 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn underlying(&self) -> &Erc721` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate = note: `-W clippy::must-use-candidate` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::must_use_candidate)]` __END__

Check warning on line 60 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / beta / clippy

[clippy] reported by reviewdog 🐶 warning: this method could have a `#[must_use]` attribute --> contracts/src/token/erc721/extensions/wrapper.rs:60:5 | 60 | pub fn underlying(&self) -> &Erc721 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn underlying(&self) -> &Erc721` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate = note: `-W clippy::must-use-candidate` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::must_use_candidate)]` Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:60:5:w:warning: this method could have a `#[must_use]` attribute --> contracts/src/token/erc721/extensions/wrapper.rs:60:5 | 60 | pub fn underlying(&self) -> &Erc721 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn underlying(&self) -> &Erc721` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate = note: `-W clippy::must-use-candidate` implied by `-W clippy::pedantic` = help: to override `-W clippy::pedantic` add `#[allow(clippy::must_use_candidate)]` __END__
&self._underlying

Check warning on line 61 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / stable / clippy

[clippy] reported by reviewdog 🐶 warning: used underscore-prefixed binding --> contracts/src/token/erc721/extensions/wrapper.rs:61:10 | 61 | &self._underlying | ^^^^^^^^^^^^^^^^ | note: binding is defined here --> contracts/src/token/erc721/extensions/wrapper.rs:20:5 | 20 | pub _underlying: Erc721, | ^^^^^^^^^^^^^^^^^^^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:61:10:w:warning: used underscore-prefixed binding --> contracts/src/token/erc721/extensions/wrapper.rs:61:10 | 61 | &self._underlying | ^^^^^^^^^^^^^^^^ | note: binding is defined here --> contracts/src/token/erc721/extensions/wrapper.rs:20:5 | 20 | pub _underlying: Erc721, | ^^^^^^^^^^^^^^^^^^^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding __END__

Check warning on line 61 in contracts/src/token/erc721/extensions/wrapper.rs

View workflow job for this annotation

GitHub Actions / beta / clippy

[clippy] reported by reviewdog 🐶 warning: used underscore-prefixed binding --> contracts/src/token/erc721/extensions/wrapper.rs:61:10 | 61 | &self._underlying | ^^^^^^^^^^^^^^^^ | note: binding is defined here --> contracts/src/token/erc721/extensions/wrapper.rs:20:5 | 20 | pub _underlying: Erc721, | ^^^^^^^^^^^^^^^^^^^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding Raw Output: contracts/src/token/erc721/extensions/wrapper.rs:61:10:w:warning: used underscore-prefixed binding --> contracts/src/token/erc721/extensions/wrapper.rs:61:10 | 61 | &self._underlying | ^^^^^^^^^^^^^^^^ | note: binding is defined here --> contracts/src/token/erc721/extensions/wrapper.rs:20:5 | 20 | pub _underlying: Erc721, | ^^^^^^^^^^^^^^^^^^^^^^^ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#used_underscore_binding __END__
}
}

// ************** ERC-721 Internal **************

impl Erc721Wrapper {
fn _recover(
&mut self,
account: Address,
token_id: U256,
) -> Result<U256, Error> {
let owner = self.underlying().owner_of(token_id)?;
if owner != contract::address() {
return Err(erc721::Error::IncorrectOwner(ERC721IncorrectOwner {
sender: contract::address(),
token_id,
owner,
})
.into());
}
self.erc721._safe_mint(account, token_id, &vec![].into())?;
Ok(token_id)
}
}
Loading