Transfer an ERC721 from a contract to a wallet

When the borrower accepts the loan agreement, is there a reason why your logic contract would not directly mint the token to the borrower wallet?

Yeah, this is not possible (mint the token into the user wallet) because of previous platform requirements that are not changeable now.

The problem is that I have no idea how your business flow & contract flow looks like, so its impossible to say which action/approval you need to provide at which location.

As I've told you before this is under NDA so I can't share so many details.
One thing that I can say is the tokens to loan needs to be fully minted from the beginning and this makes impossible to follow the way that you proposed (despite I know that this is the way to go for this type of things).

Take your code, and extract out of it an MVP (minimal viable product) which allows reproducing the problem that you're experiencing.

This hopefully-short piece of code would naturally mask out any commercial or technical detail which you are prohibited from disclosing.

However, the primary purpose of this MVP is in fact to allow the readers of your question to help you with it as best as possible, which is why providing it on your behalf is not a "nice to have" thing, but an actual requirement when posting questions here.

Lets try it with a simplified flow, hopefully that helps :slight_smile:
Assuming that the ERC721/NFT contract is external (not part of your logic contract) and borrower has to transfer Tokens or NFT's to your logic contract.

Mint all Mirror NFT's with the Logic contract as the owner.

  • Borrower -> Approve Logic contract for transfer (borrower calls approve on the ERC721 contract, NFTcontract.approve(logiccontract,tokenid) )
  • Borrower -> Accept Borrow Terms (Borrower calls the "Loan" function (or what you want to call it) on your Logic contract. (logiccontract.Loan())
  • Logic contract -> Transfer tokens/NFT from Borrower to logic contract. (Logic contract calls transfer function from ERC721 contract, as Borrower approved Logic contract this is allowed (this is called from inside the Loan function IERC721(NFTcontract).transferFrom(msg.sender, address(this),tokenid))
  • Logic contract -> Transfer Mirror NFT to Borrower (Logic contract calls transfer function from the mirror erc721 contract, as logic contract is owner, no approval is needed. IERC721(mirrorcontract).transferFrom(address(this),msg.sender,tokenid)

As a side note:
This requires the Logic Contract to implement IERC721Receiver to be able to be the owner of a NFT

And a short solidity explanation:
If you make an external call from inside your smart contract like:
IERC721(someaddress).approve(..) or IERC20(someaddress).transfer(..) << external call then the msg.sender will be the contract that called it (so your own contract address / this)

1 Like

Hey CryptoWorld! Thank you, this was the step that I was missing. The difference between transferFrom and safeTransferFrom is the key to my process.
I totally missed the possibility to use the transferFrom so I was not able to solve easily my problem.
Thank you again!

I know that this was not a easy to solve task since I've not provided complete information about the case.
The next time I'll prepare an MVP to test out for public feedback.
Thank you for your availability!

IERC721(mirrorcontract).transferFrom(address(this),msg.sender,tokenid)
and
IERC721(mirrorcontract).safeTransferFrom(address(this),msg.sender,tokenid)

Both should work, However technically safeTransferFrom should be used. The difference is that safeTransferFrom checks if the receiver implemented IERC721Receiver which you should implement in your logic contract. The safe version checks if your contract supports ERC721 and reverts otherwise to prevent NFT's from being "lost"

Small warning: ERC721 safeTransferFrom will perform an external call to the recipient of the the NFT token. As it will call address(receiver).onERC721Received(..) to verify that the receiver can work with NFT's

Anytime you call an external function make sure to adhere to the "Checks Effects Interactions" pattern https://fravoll.github.io/solidity-patterns/checks_effects_interactions.html
Any function that calls an external smart contract should make sure there is no re-entrancy vulnerability. This includes making calls to IERC(token).transfer() (as the token is the external contract).

Normally this is pretty straightforward, however it is easily overlooked when the ERC721 NFT contract is your contract. As you think the external contract call is on something you created and is not vulnerability. However your ERC721 safeTransferFrom does another external call to the recipient.

1 Like