Boa. Vou comentar sobre a parte tecnica do código para os curiosos.
Esse é o código do contrato padrão ERC721, utilizado pela gigante maioria dos NFTs:
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.solUma de suas funções é a
transferFrom (linha 149). Ela aceita 3 parâmetros bem nomeados:
- from = um endereço, de quem transferir o token.
- to = um endereço, para quem transferir o token.
- tokenId = o id do token NFT.
function transferFrom(
address from,
address to,
uint256 tokenId
) public virtual override {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved");
_transfer(from, to, tokenId);
}
Podemos ver que ela contém um require (requer um retorno igual a "true") que chama a função
_isApprovedOrOwner passando o endereço de quem está chamando a função e o tokenId como parâmetros.
A função
_isApprovedOrOwner recebe 2 parâmetros, spender (de quem enviar o token) e tokenId, e retorna uma boleana (true ou false).
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
E ela retorna true caso pelo menos UMA das três seguintes afirmações forem verdadeiras:
1. spender é igual a constante owner.
2. o retorno de
isApprovedForAll, passando a constante owner e spender, é true.
3. o retorno de
getApproved, passando o token Id, é igual a spender.
[spender = quem está chamando a função; owner = quem detém do token]
A função
isApprovedForAll, do número 2, é a seguinte:
function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
return _operatorApprovals[owner][operator];
}
Ela retorna o conteúdo (uma boleana) do mapping
_operatorApprovals com o index
owner e seu subsequente index
operator.
Esse mapping é modificado na função citada pelo @lucasgabd,
_setApprovalForAll:
function _setApprovalForAll(
address owner,
address operator,
bool approved
) internal virtual {
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
Que apenas define o index citado acima como true ou false.
O site malicioso vai pedir que você assine uma tx chamando a tal função:
_setApprovalForAll(você, hacker, true)
Que vai definir: _operatorApprovals[você][hacker] = true
Fazendo com que
isApprovedForAll(você, hacker) retorne true, liberando a transação.