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 alloc::{vec, vec::Vec};

use alloy_primitives::{Address, FixedBytes, U256};
use openzeppelin_stylus::token::erc721::{
    extensions::{wrapper, Erc721Wrapper, IErc721Wrapper},
    Erc721,
};
use stylus_sdk::{abi::Bytes, prelude::*};

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

#[public]
#[inherit(Erc721)]
impl Erc721WrapperExample {
    fn underlying(&self) -> Address {
        self.erc721_wrapper.underlying()
    }

    fn deposit_for(
        &mut self,
        account: Address,
        token_ids: Vec<U256>,
    ) -> Result<bool, wrapper::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, wrapper::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>, wrapper::Error> {
        self.erc721_wrapper.on_erc721_received(
            operator,
            from,
            token_id,
            data,
            &mut self.erc721,
        )
    }
}

Additionally, you need to ensure proper initialization during contract deployment. Make sure to include the following code in your Solidity Constructor:

contract Erc721WrapperExample {
    mapping(address account => uint256) private _balances;
    mapping(address account => mapping(address spender => uint256))
        private _allowances;
    uint256 private _totalSupply;

    address private _underlyingToken;

    constructor(address underlyingToken_) {
        _underlyingToken = underlyingToken_;
    }
}