Hey guys! I have two smart contracts in two different files: one is an ERC721 (we can call it ContractA) , the other one is a custom one i made(we can call it ContractB). At some point, i have a function in ContractB which attempts to call the safeTransferFrom function in ContractA in a manner like this:
function someFunction() public{
ContractA.safeTransferFrom(from,to,id);
}
thing is, the EVM reverts the transaction since the caller address of safeTransferFrom is not the same as the owner of the token (even if the from,to variables i passed are right).
If I've done my math right, the caller of safeTransferFrom in "someFunction" is the ContractB itself(correct me if i'm wrong), so how can i make the safeTransferFrom be called from the original msg.sender?
Thanks for answering! I tried your solution this way (i added another "address" field since safeTransferFrom requires 3 parameters):
ContractA.delegatecall(abi.encodeWithSignature("safeTransferFrom(address,address,uint256)",msg.sender, to, id));
the transaction successfully goes through but when i go and call the ownerOf method of ContractA, the owner results unchanged. Any idea why?
Let me add some more details about the contracts: ContractB has a constructor which requires the address of ContractA to instantiate a ContractA attribute
It goes without saying, i first deployed ContractA, then deployed ContractB with ContractA's address.
Inside ContractB i have a function which calls safeMint and it successfully creates an NFT on ContractA's instance.
contract ContractB{
address public contractAAddress;
ContractA contractAInstance;
constructor (address _contractAAddress){
contractAAddress=_contractAAddress;
contractAInstance=ContractA(contractAAddress);
}
function someFunction(address to,uint256 id){
ContractA.delegatecall(abi.encodeWithSignature("safeTransferFrom(address,address,uint256)",msg.sender, to, id));
}
}
I'm debugging via remix (on the London Javascript VM), and I call the function via the deployed contracts window. Also, I always make sure the selected account is the owner of the specified NFT.
also, I forgot to mention i edited the ContractA.delegatecall to address(ContractA).delegatecall since the delegatecall method wasn't found in the first one.
This was the error with ContractA.delegatecall
The other error persists tough, the function doesn't execute. I tried even using safeMint which only asks for the to address, so the code shouldn't need any specific address. The function goes through but no token is created.
Interesting/weird fact, with the .delegatecall(safeMint..... function, the transaction output says that a token is generated: in fact if I generate more than one I can see the tokenID incrementing, but if I go back to the ContractA contract and check for ownerOf(0) it says that the token is nonexistent. So i'm kinda confused, where was that token generated? It's like they dont share the same memory space even if on the same address