0

I'm creating a contract where the user would transfer X amounts of tokens A and B to my smart contract for a task. The problem with this is that in principle, the user would have to sign and send 3 transactions: 2 for approvals of the tokens, and then 1 more for the smart contract that it would call transferFrom(user, address(this), amount). To improve user experience, would it be possible instead to have the user call the function:

function transferFromUser(address token, uint256 value) {
    // 0xa9059cbb = transfer function selector
    (bool success, bytes memory data) = token.delegatecall(abi.encodeWithSelector(0xa9059cbb, address(this), value));
}

This way the context when calling transfer via delegatecall would mark the user address as msg.sender and hence it should work without the need for approval right? The token smart contract would think that the user itself is calling that function so there would be no need to sign on the approval. Is this correct?

There is a similar question being asked here Transfer ERC20 via onother smart contract (call transfer as delegate) but I opened this one because I don't entirely agree with the answer marked as accepted. In my case, contract A is my smart contract and contrat B is the token's contract. If user calls contractA, which calls contractB's transfer() function with delegatecall(), it would be as if the user calls transfer() themselves right?

3
  • 1
    Some add. comments to the solution. Imagine how dangerous it would be if a contract could call underlined contracts on behalf of the tx.origin :) delegatecall - is how the proxies work. And for your case - look into the permits. Collect the permits from the user, and then only 1 transaction is required, instead of 3. If tokens support EIP-2612
    – tenbits
    Commented Nov 21, 2022 at 13:11
  • This is very interesting. I think that many of the top 100 tokens in CMC are not permit compliant, correct? However I see that Uniswap recently released permit2 contract that can be used with all the ERC20 tokens even if they are not permit compliant, although I see on the docs that it says Before integrating contracts can request users’ tokens through Permit2, users must approve the Permit2 contract through the specific token contract. Does this mean that the user should, at least the first time, send a transaction specifically to allow permits for them in that token? Thanks!
    – Hiperfly
    Commented Nov 21, 2022 at 17:05
  • 1
    Correct, a user should allow the permi2 address to spend their tokens. It must be done per token. But this is a cross-contract allowance, which means if the permit2 has wider adoption, then the user would have already approved the tokens before using your service. But anyway, you must handle the case if the user has not set yet the approval for permit2 contract.
    – tenbits
    Commented Nov 22, 2022 at 9:14

1 Answer 1

2

From my understanding, that wouldn't do the job since you are using the storage of contractA (your contract) but not modifying contractB's storage.

ex: https://solidity-by-example.org/delegatecall/ enter image description here

Therefore you wouldn't be transferring the tokens of contractB but a copy of contractB's tokens. And that even implying that the address you're sending from has the appropriate token balance on contractA.

If you want to be transferring tokens of contractB you'd have to use call().

If you wanted to make a copy of contractB's storage you could use staticcall() on the contractB's balanceOf([userAddress]), and assign the encoded return value to balanceOf[userAddress] to contract A. And for that you'd need to have the same state variables of contractB declared in contractA (in the same order!).

enter image description here

And FINALLY, be it on your contract or any for that matters, you cannot transfer tokens from an address ifyou are not that address nor approved by that address.

1
  • Thank you! This is the exact explanation I was looking for. Indeed I was not aware it would use/modify contract A's storage instead of contract B, much appreciated
    – Hiperfly
    Commented Nov 21, 2022 at 13:01

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.