ERC-721 Wrapper

Extension of the ERC-721 token contract to support token wrapping.

Users can deposit and withdraw "underlying tokens" and receive a matching number of "wrapped tokens". This is useful in conjunction with other modules.

Usage

In order to make ERC721Wrapper methods “external” so that other contracts can call them, you need to implement them by yourself for your final contract as follows:

use openzeppelin_stylus::{
    token::erc721::{
        self,
        extensions::{wrapper, Erc721Wrapper, IErc721Wrapper},
        Erc721, IErc721,
    },
    utils::introspection::erc165::IErc165,
};

#[entrypoint]
#[storage]
struct Erc721WrapperExample {
    erc721: Erc721,
    erc721_wrapper: Erc721Wrapper,
}

#[public]
#[implements(IErc721<Error = erc721::Error>, IErc721Wrapper<Error = wrapper::Error>, IErc165)]
impl Erc721WrapperExample {
    #[constructor]
    fn constructor(&mut self, underlying_token: Address) {
        self.erc721_wrapper.constructor(underlying_token);
    }
}

#[public]
impl IErc721 for Erc721WrapperExample {
    type Error = erc721::Error;

    fn balance_of(&self, owner: Address) -> Result<U256, Self::Error> {
        self.erc721.balance_of(owner)
    }

    fn owner_of(&self, token_id: U256) -> Result<Address, Self::Error> {
        self.erc721.owner_of(token_id)
    }

    fn safe_transfer_from(
        &mut self,
        from: Address,
        to: Address,
        token_id: U256,
    ) -> Result<(), Self::Error> {
        self.erc721.safe_transfer_from(from, to, token_id)
    }

    fn safe_transfer_from_with_data(
        &mut self,
        from: Address,
        to: Address,
        token_id: U256,
        data: Bytes,
    ) -> Result<(), Self::Error> {
        self.erc721.safe_transfer_from_with_data(from, to, token_id, data)
    }

    fn transfer_from(
        &mut self,
        from: Address,
        to: Address,
        token_id: U256,
    ) -> Result<(), Self::Error> {
        self.erc721.transfer_from(from, to, token_id)
    }

    fn approve(
        &mut self,
        to: Address,
        token_id: U256,
    ) -> Result<(), Self::Error> {
        self.erc721.approve(to, token_id)
    }

    fn set_approval_for_all(
        &mut self,
        to: Address,
        approved: bool,
    ) -> Result<(), Self::Error> {
        self.erc721.set_approval_for_all(to, approved)
    }

    fn get_approved(&self, token_id: U256) -> Result<Address, Self::Error> {
        self.erc721.get_approved(token_id)
    }

    fn is_approved_for_all(&self, owner: Address, operator: Address) -> bool {
        self.erc721.is_approved_for_all(owner, operator)
    }
}

#[public]
impl IErc721Wrapper for Erc721WrapperExample {
    type Error = wrapper::Error;

    fn underlying(&self) -> Address {
        self.erc721_wrapper.underlying()
    }

    fn deposit_for(
        &mut self,
        account: Address,
        token_ids: Vec<U256>,
    ) -> Result<bool, Self::Error> {
        self.erc721_wrapper.deposit_for(account, token_ids, &mut self.erc721)
    }

    fn withdraw_to(
        &mut self,
        account: Address,
        token_ids: Vec<U256>,
    ) -> Result<bool, Self::Error> {
        self.erc721_wrapper.withdraw_to(account, token_ids, &mut self.erc721)
    }

    fn on_erc721_received(
        &mut self,
        operator: Address,
        from: Address,
        token_id: U256,
        data: Bytes,
    ) -> Result<FixedBytes<4>, Self::Error> {
        self.erc721_wrapper.on_erc721_received(
            operator,
            from,
            token_id,
            &data,
            &mut self.erc721,
        )
    }
}

#[public]
impl IErc165 for Erc721WrapperExample {
    fn supports_interface(&self, interface_id: FixedBytes<4>) -> bool {
        self.erc721.supports_interface(interface_id)
    }
}