Hi,
I'm trying to implement a very basic multicall contract such as:
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/Address.sol";
import "hardhat/console.sol";
contract Multicall {
struct Call {
address target;
bytes callData;
}
function multicall(Call[] memory calls) public returns (bytes[] memory results) {
results = new bytes[](calls.length);
for(uint256 i = 0; i < calls.length; i++) {
results[i] = Address.functionDelegateCall(address(calls[i].target), calls[i].callData);
}
return results;
}
}
I have a small test script that creates an ERC20 token and grants wallet "Alice" 1000 tokens. I'm then trying to test the multicall
by simply passing in a single call to transfer
10 tokens from "Alice" to a second wallet "Bob". I've checked that doing a simple transfer by directly calling transfer on the ERC20 token does indeed work and that the balances of both wallets reflect the transferred amounts. However, when I try to do this through the Multicall contract, I'm getting odd errors:
-
The Call struct that I'm passing
multicall
is:- target: ERC20 token contract
-
callData:
transfer(bob.address, "2")
(encoded using ethers populateTransaction on the ERC20 contract) -
The function call reverts, however, saying that the balance of the sender is insufficient. When I check the msg.sender's balance within the multicall function, the returned value is "0" and that the msg.sender is indeed Alice, even though Alice's balance should be however many tokens I granted her at the beginning (minus the minor transfer that I did as checks before the multicall).
I'm clearly missing something fundamentally about how to use multicall / Address.functionDelegateCall. Any suggestions?
Thanks