mds1 / multicall

Multicall: Aggregate multiple constant function call results into one
https://multicall3.com
MIT License
933 stars 161 forks source link

bubble up errors #145

Closed dbeal-eth closed 1 year ago

dbeal-eth commented 1 year ago

I understand that Multicall3 contracts are immutable, however, this has been a frequent problem and its significant enough that it warrants creation of Multicall4.

A frequent issue that I experience as a web3 developer is establishing the ultimate error that caused a transaction to fail, or perhaps finding the error for a read call that failed unexpectedly. In this way, it is typically most useful if any proxy/intermediate contracts pass through any errors that occur. This particularly more important for larger transactions, such as multicalls.

unfortunately, multicall3 does not have any capability to bubble up errors. rather than returning the original error data, multicall3 will return Multicall3: call failed upon error on the inner transactions, effectively obscuring the result. If I am a developer and am just trying to get an app to work, I now have to either 1) break my transaction into individual calls and find the individual error (defeating the purpose of using a multicall for reads in the first place), or 2) copy my transaction into a trace tool such as tenderly and read the inner failure result. If I am an end user, an unexpected error on a read or write call can make it extremely difficult for developers to immediately pin down the cause.

it turns out its pretty easy to bubble up errors. The revert reason is included in the return data from the call, so a short assembly section can allow for the revert data to be accessed and re-reverted (ex. https://github.com/Synthetixio/synthetix-v3/blob/main/protocol/synthetix/contracts/modules/core/MulticallModule.sol#L31).

Bubbling up errors would also be useful for EIPs which rely on revert values in order to request offchain data, such as EIP-3668 or EIP-7412

BTW, slightly unrelated but if you are looking for another improvement for Multicall4, you could have the contract be deployed with CREATE2 using arachnid https://github.com/Arachnid/deterministic-deployment-proxy

mds1 commented 1 year ago

Yea, agreed that would be ideal. These days for bespoke multicalls I revert with error CallFailed(uint256 callIndex, bytes revertData) so you can easily map it to the call also. Created https://github.com/mds1/multicall/issues/146 to track this

A workaround is to not revert on failure and manually check the Result[] array, and pull out the revert data as soon as you find one where success is false. If you're doing this on-chain, it may get costly depending on how many calls you have and how large the return/revert data is

mds1 commented 1 year ago

Going to close since there's a workaround for the current version and we're now tracking this in #146 :)