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.
-
Depending on your use-case, you might be able to use an ERC-223 token: https://ethereum.stackexchange.com/questions/31643/erc223-gas-savings – Richard Horrocks Apr 29 '19 at 06:06
-
2Does this answer your question? Is it possible to batch approve + transfer an ERC-20 token? – Paul Razvan Berg Oct 12 '22 at 11:19
3 Answers
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
- 648
- 2
- 12
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.
- 16,897
- 1
- 29
- 58
-
"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 '19 at 10:45 -
-
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
}
- 7,313
- 1
- 23
- 38
-
-
Terminology is not strict, but here by "wallet" I meant wallet smart contract, either multisig, or with single owner. – Mikhail Vladimirov Apr 29 '19 at 09:33