Padrão Multi-Token ERC-1155
Última edição: @borja_reverter(opens in a new tab), 15 de agosto de 2023
Introdução
Uma interface padrão para contratos que gerenciam vários tipos de tokens. Um único contrato implementado pode incluir qualquer combinação de tokens fungíveis, tokens não fungíveis ou outras configurações, por exemplo, tokens semifungíveis.
O que se entende por padrão Multi-Token?
A ideia é simples e trata-se de criar uma interface de contratos inteligentes que possa representar e controlar qualquer número de tipos de token, fungíveis ou não fungíveis. Dessa forma, o token ERC-1155 pode fazer as mesmas funções que um token ERC-20 ou um token ERC-721, ou ainda as duas funções simultaneamente. Ele melhora a funcionalidade de ambos os padrões ERC-20 e ERC-721, tornando-os mais eficientes e corrigindo erros óbvios de implementação.
O token ERC-1155 é descrito com profundidade em EIP-1155(opens in a new tab).
Pré-requisitos
Para entender melhor esta página, recomendamos ler primeiro sobre padrões de token, ERC-20 e ERC-721.
Funções e características do ERC-1155:
- Transferências em lote: transfira vários ativos em uma única chamada.
- Saldo em lote: obtenha os saldos de vários ativos em uma única chamada.
- Aprovação em lote: aprove todos os tokens de um endereço.
- Hooks: receba hook de tokens.
- Suporte para NFT: se a cunhagem for de apenas 1, tratar como NFT.
- Regras de transferência segura: conjunto de regras para transferências seguras.
Transferências em lote
As transferências em lote funcionam de forma muito semelhante às transferências regulares do ERC-20. Vejamos a função transferFrom
da ERC-20 habitual:
1// ERC-202function transferFrom(address from, address to, uint256 value) external returns (bool);34// ERC-11555function safeBatchTransferFrom(6 address _from,7 address _to,8 uint256[] calldata _ids,9 uint256[] calldata _values,10 bytes calldata _data11) external;Exibir tudoCopiar
A única diferença no ERC-1155 é que passamos os valores como um array e também passamos um array de ‘ids’. Por exemplo, dadas as matrizes ids=[3, 6, 13]
e values=[100, 200, 5]
, as transferências resultantes serão
- Transferir 100 tokens da ID 3 de
_from
para_to
. - Transferir 200 tokens da ID 6 de
_from
para_to
. - Transferir 5 tokens da ID 13 de
_from
to_to
.
No ERC-1155, só temos transferFrom
, ou seja, não há transfer
. Para usá-lo como uma transferência regular, ou transfer
, defina o endereço de origem como o endereço que está chamando a função.
Saldo em lote
A respectiva chamada balanceOf
do ERC-20 também tem sua função parceira com suporte para lotes. Como lembrete, esta é a versão do ERC-20:
1// ERC-202function balanceOf(address owner) external view returns (uint256);34// ERC-11555function balanceOfBatch(6 address[] calldata _owners,7 uint256[] calldata _ids8) external view returns (uint256[] memory);Copiar
Ainda mais simples para a chamada de saldo, podemos recuperar saldos múltiplos em uma única chamada. Passamos a matriz de proprietários, seguida pela matriz dos IDs dos tokens.
Por exemplo, dado _ids=[3, 6, 13]
e _owners=[0xbeef..., 0x1337..., 0x11...]
, o valor de retorno será
1[2 balanceOf(0xbeef...),3 balanceOf(0x1337...),4 balanceOf(0x1111...)5]Copiar
Aprovação em lote
1// ERC-11552function setApprovalForAll(3 address _operator,4 bool _approved5) external;67function isApprovedForAll(8 address _owner,9 address _operator10) external view returns (bool);Exibir tudoCopiar
As aprovações são um pouco diferentes do ERC-20. Em vez de aprovar valores específicos, você define um operador para aprovados ou não aprovados via setApprovalForAll
.
Ler o status atual pode ser feito via isApprovedForAll
. Como você pode ver, é uma operação de tudo ou nada. Você não pode definir quantos tokens aprovar ou mesmo quais classes de token.
Isto é intencionalmente concebido pensando na simplicidade. Você só pode aprovar tudo para um endereço.
Receber hooks
1function onERC1155BatchReceived(2 address _operator,3 address _from,4 uint256[] calldata _ids,5 uint256[] calldata _values,6 bytes calldata _data7) external returns(bytes4);Copiar
Dado o suporte da EIP-165(opens in a new tab), o ERC-1155 pode receber hooks apenas por contratos inteligentes. A função de hook deve retornar um valor mágico predefinido de 4 bytes que é dado como:
1bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))Copiar
Quando o contrato de recebimento devolve este valor, assume-se que o contrato aceita a transferência e sabe como lidar com os tokens ERC-1155. Ótimo, nenhum token bloqueados em um contrato!
Suporte para NFTs
Quando a oferta é apenas uma, o token é essencialmente um token não-fungível (NFT, pela sigla em inglês) E como é padrão para o ERC-721, você pode definir um URL de metadados. Esse URL pode ser lido e modificado pelos clientes; veja aqui(opens in a new tab).
Regra de transferência segura
Já abordamos algumas regras de transferência segura nas explicações anteriores. Mas vamos analisar as regras mais importantes:
- O chamador deve ser aprovado para gastar os tokens para o endereço
_from
ou o chamador deve ser igual ao endereço_from
. - A chamada de transferência deve ser revertida caso
- o enderaço
_to
seja 0. - o comprimento dos
_ids
não seja o mesmo que o comprimento dos_values
. - qualquer um do saldos dos titulares dos tokens em
_ids
seja menor que as respectivas quantidades em_values
enviados para o destinatário. - ocorra qualquer outro erro.
- o enderaço
Nota: Todas as funções por lotes, incluindo o hook, também existem como versões sem lotes. Isto é feito para fins de eficiência do gás, já que é provável que a transferência de apenas um ativo continue sendo a maneira habitualmente mais utilizada. Por simplificar as explicações, as deixamos de lado, incluindo as regras de transferência segura. Os nomes são idênticos, basta eliminar a palavra "lote".
Leitura adicional
- EIP-1155: Padrão Multi-Token(opens in a new tab)
- ERC-1155: Documentos da Openzeppelin(opens in a new tab)
- ERC-1155: Repositório no GitHub(opens in a new tab)
- NFT API do Alchemy(opens in a new tab)