ERC721 setApprovalForAll by delegateCall

Hello everyone,

I'm developing an NFTStore.

The user should set the NFTStore as operator for transfer, I created a function in the store that call the setApprovalForAll passing the NFTStore address by delegateCall to garantee that msg.sender is the same of the token owner, but I always getting error.

Can anyone give me any advice on how to achieve this?

I don't need to set the NFTStore has ERC721Holder because he only transfer nfts.

Here is the code, where manager is the address of the NFTStore:
bytes memory data = Address.functionDelegateCall(contractAddress, abi.encode("setApprovalForAll(address,bool)", manager, true));

Thanks in advance.

You are making wrong assumptions about what delegateCall does.

Address.functionDelegateCall(contractAddress, abi.encode("setApprovalForAll(address,bool)", manager, true));

Means execute contractAddress.setApprovalForAll(manager, true) using the storage and balance of address(this)

It DOES NOT mean execute contractAddress.setApprovalForAll(manager, true) as if the transaction is coming from msg.sender

NFTStore is the operator. it's the user that needs to call any approval functions, not the contract getting approved

NFTStore is gonna receive NFTs and is a contract, it needs to implement IERC721Receiver, ERC721Holder is provided for that

2 Likes

I'm interested in the same topic, i'm trying to call a SetApprovalForAll from another smart contract in behalf of the msg.sender, is there a way to do that? i tried delegatecall and call but doesn't work for me. Thanks in advance. @helio.rosa

"in behalf of the msg.sender" means impersonating msg.sender. That is not possible.

What would prevent anyone from calling transfer() "in behalf" of someone else?

Using tx.origin is not advised because it makes your contract vulnerable

Let me explain better the situation. I am building contract A that calls setApprovalForAll in contract B. What i want is that the user that calls the contract A is the same that gets approved in the contract B. So i want basically the setApprovalForAll with the user as approved, calling it from another smart contract and not directly from the destination contract. I hope i explained it well, let me know if you can help me. Thanks in advance.

I've understood perfectly

This is what impersonating the caller means.

The ability to do this would be a massive security hole. If you are able to manipulate the value of msg.sender, what do you use to determine who the caller is ?

there is no "calling in behalf of" or "calling as if" or "with the user as the other user". when you call setApprovalForAll on contract B from contract A msg.sender is always the address of A

If you are writing A and B, you can add an extra method to B that can only be called by A, lets call it setApprovalForAllOnlyForA with the same arguments as setApprovalForAll plus an extra address (the original msg.sender). setApprovalForAllOnlyForA would have to check if msg.sender is A and then do the same as setApprovalForAll but with the provided address instead of msg.sender

1 Like