OpenZeppelin 的 ERC-1155 URI 存储扩展对于管理和存储单个 token 的 URI 是必需的。此扩展允许每个 token 都有其自己唯一的 URI, 它可以指向关于 token 的元数据,例如图像、描述和其他属性。 这对于非同质化 token (NFT) 尤其有用,因为每个 token 都是唯一的,并且可能具有不同的元数据。

用法

为了创建一个具有 URI 存储 特性的 ERC-1155 token, 你的 token 还应该使用 ERC-1155 元数据 URI 扩展来为每个 token 提供额外的 URI 元数据。 你需要创建一个指定的合约,如下所示:

use openzeppelin_stylus::{
    token::{
        erc1155,
        erc1155::{
            extensions::{
                Erc1155MetadataUri, Erc1155UriStorage, IErc1155MetadataUri,
            },
            Erc1155, IErc1155,
        },
    },
    utils::introspection::erc165::IErc165,
};

#[entrypoint]
#[storage]
struct Erc1155MetadataUriExample {
    erc1155: Erc1155,
    metadata_uri: Erc1155MetadataUri,
    uri_storage: Erc1155UriStorage,
}

#[public]
#[implements(IErc1155<Error = erc1155::Error>, IErc1155MetadataUri, IErc165)]
impl Erc1155MetadataUriExample {
    #[constructor]
    fn constructor(&mut self, uri: String) {
        self.metadata_uri.constructor(uri);
    }

    #[selector(name = "setTokenURI")]
    fn set_token_uri(&mut self, token_id: U256, token_uri: String) {
        self.uri_storage.set_token_uri(token_id, token_uri, &self.metadata_uri)
    }

    #[selector(name = "setBaseURI")]
    fn set_base_uri(&mut self, base_uri: String) {
        self.uri_storage.set_base_uri(base_uri)
    }
}

#[public]
impl IErc1155 for Erc1155MetadataUriExample {
    type Error = erc1155::Error;

    fn balance_of(&self, account: Address, id: U256) -> U256 {
        self.erc1155.balance_of(account, id)
    }

    fn balance_of_batch(
        &self,
        accounts: Vec<Address>,
        ids: Vec<U256>,
    ) -> Result<Vec<U256>, Self::Error> {
        self.erc1155.balance_of_batch(accounts, ids)
    }

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

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

    fn safe_transfer_from(
        &mut self,
        from: Address,
        to: Address,
        id: U256,
        value: U256,
        data: Bytes,
    ) -> Result<(), Self::Error> {
        self.erc1155.safe_transfer_from(from, to, id, value, data)
    }

    fn safe_batch_transfer_from(
        &mut self,
        from: Address,
        to: Address,
        ids: Vec<U256>,
        values: Vec<U256>,
        data: Bytes,
    ) -> Result<(), Self::Error> {
        self.erc1155.safe_batch_transfer_from(from, to, ids, values, data)
    }
}

#[public]
impl IErc1155MetadataUri for Erc1155MetadataUriExample {
    fn uri(&self, token_id: U256) -> String {
        self.uri_storage.uri(token_id, &self.metadata_uri)
    }
}

#[public]
impl IErc165 for Erc1155MetadataUriExample {
    fn supports_interface(&self, interface_id: B32) -> bool {
        self.erc1155.supports_interface(interface_id)
            || self.metadata_uri.supports_interface(interface_id)
    }
}