2

I know that owner should call approve in advance then allowed spender call transferfrom to make transaction. We need two steps(tx). Iam curious is it possible to make it by single tx! single step.

2

3 Answers 3

1

The purpose of the approve() -> transferFrom() flow is that you want a different account to do the transfer than the one that is allowed to approve it. If it's a single account, you'd normally just do a transfer().

If you wanted to make both these in the same transaction you'd need the approver and the approved user to both be contracts, with logic that allowed them to be called from as part of a transaction from a third contract. You could send a single transaction to the third contract, and that would tell the owner contract to call approve(), then tell the approved contract to call transferFrom(). It's not immediately obvious what use-case would be served by a setup like this, but it's technically possible.

3
  • "You could send a single transaction to the third contract, and that would tell the owner contract to call approve()" Who must be "YOU"? Is approver(owner) can be YOU?
    – lagoiz
    Apr 29, 2019 at 10:45
  • And also is it possible contract makes EOA call function?
    – lagoiz
    Apr 29, 2019 at 10:58
  • And also is it possible contract makes EOA call function?
    – lagoiz
    Apr 29, 2019 at 11:03
1

Yes, this is possible, but token holder has to be a smart contract, e.g. wallet. Such contract should implement a function similar to this one:

function approveAndCall (IERC20 _token, address _to, uint256 _value, bytes memory _data)
public payable returns (bytes memory _returnData) {
  require (_token.approve (_to, _value));
  bool success;
  (success, _returnData) = _to.call.value (msg.value) (_data); // Supposed to call transferFrom
  require (success);
  require (_token.approve (_to, 0)); // Wipe out any unspent allowance
}
2
  • wallet is not a smart contract right?
    – lagoiz
    Apr 29, 2019 at 9:28
  • Terminology is not strict, but here by "wallet" I meant wallet smart contract, either multisig, or with single owner. Apr 29, 2019 at 9:33
1

I kind of had the same question but in a slightly different scenario:

I wanted to make a "burn4token" contract where an user burns one ERC1155 collection's token in order to mint another in a different ERC721 collection; all in the same transaction but I had to get my "burn4token" contract approved as operator in order to do this;

I sorted it out changing my flow

I implemented the IERC115Receiver interface into my ERC721 contract; then in the "onERC1155Received" hook I put a burn and mint steps; So now the user can transfer an old ERC1155 token to the ERC721 contract and get a new nft :)

I hope this gives you ideas!

function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external override(IERC1155Receiver) returns (bytes4){
        //burn
        (bool burned,bytes memory burnedData) = address(erc1155contract.address).call(
            abi.encodeWithSignature("burn(address,uint256,uint256)", address(this), 1, 1)
        );
        //you can use this to handle or print errors
        require(burned, string(burnedData));
        //then mint here
        mint(1);

        return bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"));
    }

It works because after the user sends the ERC1155 to the 721 contract; the 721 contract calls the ERC1155 contract burn function as the owner of the token so no "setApprovalForAll" is required

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.