-
Notifications
You must be signed in to change notification settings - Fork 39
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
ed85c4c
195ced3
dece90e
55ed546
a44545c
4014c92
8b20d18
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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, | ||
/// 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
|
||
token_ids: Vec<U256>, | ||
Check warning on line 52 in contracts/src/token/erc721/extensions/wrapper.rs
|
||
) -> bool { | ||
let length = token_ids.len(); | ||
Check warning on line 54 in contracts/src/token/erc721/extensions/wrapper.rs
|
||
|
||
true | ||
} | ||
|
||
/// Returns the underlying token. | ||
pub fn underlying(&self) -> &Erc721 { | ||
Check warning on line 60 in contracts/src/token/erc721/extensions/wrapper.rs
|
||
&self._underlying | ||
Check warning on line 61 in contracts/src/token/erc721/extensions/wrapper.rs
|
||
} | ||
} | ||
|
||
// ************** 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) | ||
} | ||
} |
There was a problem hiding this comment.
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?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should probably be using
pub underlying: Address
(no underscore), as this is an external contract, and Stylus currently has no way to represent them as part of structs.You'll then also probably need to define a local sol interface, like in VestingWallet.