How to call approve() of an ERC20 contract in ERC721Upgradeable contract

In an ERC721Upgradeable contract I need to call approve() of another ERC20 contract. I do this with a delegate call in the ERC721 function in order to keep the context ( msg.sender() ).

(status, result) = erc20Contract.delegatecall(abi.encodePacked(bytes4(keccak256("approve(address, uint256)")), address(this), price));

At migration time I get the following error:

Error: Contract erc721contract is not upgrade safe erc721contract sol:45: Use of delegatecall is not allowed https://zpl.in/upgrades/error-002

How can I call the ERC20 approve(recipient, amount) in ERC721Upgradeable in order to give the ERC721 contract the allowance of msg.sender() over an amount?

In the ERC721Upgradable I want the sender gives the contract the allowance over a certain amount of an ERC20Upgradeable contract to subsequently call burnFrom(sender, amount)
I have a special mint function in place to mint the ERC721 token against a payment of an ERC20 token which needs to be burnt after reception.

function mintByERC20(uint256 tokenId) public { bool status; bytes memory result; (status, result) = erc20address.delegatecall(abi.encodePacked(bytes4(keccak256("approve(address, uint256)")), address(this), amount)); require(status); erc20.burnFrom(_msgSender(), accountPrice); _mint(_msgSender(), tokenId); }

1 Like

Hi @Homer,

Can you not just call approve on the ERC20? I am not sure why you need to do the delegatecall?

Hi @abcoathup

Yes, I am calling the approve() on the ERC20 first (in the web3 script) and call subsequently mintByERC20().

1 Like

Hi @abcoathup ,

Would ERC777 for this use case more suitable with a default operator having the permission to send() on behalf of msg.sender()?

1 Like

Generally speaking, user should call ERC20.approve(YOUR_CONTRACT, APPROVED_AMOUNT) first, and then they can call your function mintByERC20(), this is two steps rather than one.

Yeah, maybe ERC777 can solve your issue.

1 Like