Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ETHEREUM-CONTRACTS] Investigate multicall forwarder #1500

Closed
0xdavinchee opened this issue Jul 11, 2023 · 4 comments
Closed

[ETHEREUM-CONTRACTS] Investigate multicall forwarder #1500

0xdavinchee opened this issue Jul 11, 2023 · 4 comments
Assignees
Labels
Team: Protocol Protocol Core, Sentinel, Peripherals, Protocol Infrastructure Tools & DevOps Type: Spike Task that is to be timeboxed

Comments

@0xdavinchee
Copy link
Contributor

0xdavinchee commented Jul 11, 2023

Why?

  1. Reduce maintenance for us (get rid of SDK)
  2. Increase compatibility by using a commonly known and used contract
  3. Best devX and compatibility (multicall is natively supported by viem!)

Background

This is how real account abstraction will be built. Trusted “invoker” contracts which abstract msg.sender.
It’s being EIP’d as we speak, but there’s no consensus yet. We’d be able to announce this with a very strong narrative if we jump the gun

A radical idea on batch calls

  1. Remove batch calls from the protocol (or keep them for compatibility reasons, don’t matter)
  2. Add a new trusted forwarder, that uses multicall3 or multisend (the contract gnosis safe uses) under the hood

Implementation Details

  1. We write a new forwarder contract which
    a. Has identical ABI to multicall3 (to guarantee full compatibility)
    b. Stores the msg.sender in a public batchMsgSender()(this would be the only extra function on the contract)
    c. Makes a delegateCall to the multicall3 contract
    d. Deletes the msg.sender at the end of the call
  2. As the contract is a forwarder, all callAgreement stuff should work out of the box
    a. If we want users to be able to use the existing forwarder style to open streams, we’d need to rewrite the forwarder to accept this new forwarder’s msgSender
  3. In order for ERC20 stuff to work:
    a. we rewrite transfer/approve/send on superTokens to check if caller is the approved multicall contract. If it is, then use the batchMsgSender() function we put on the multicall, which returns the msg.sender for the batch
    b. This is the main change to current batch calls, which use “operationTransfer” etc, which isn’t great for understandability by end users, and requires developers to understand Superfluid specific things / use the SDK to abstract them)
  4. One of the interesting things is that this style of “stateful multicall” could be an immutable contract with no relation to Superfluid. Any contract could be written to accept its msgSender

Caveat: there are probably some footguns here I’m not considering

@0xdavinchee 0xdavinchee added the Team: Protocol Protocol Core, Sentinel, Peripherals, Protocol Infrastructure Tools & DevOps label Jul 11, 2023
@hellwolf hellwolf added Type: Spike Task that is to be timeboxed Tag: Help Me Whelp! extra attention is needed here labels Aug 24, 2023
@hellwolf hellwolf added Type: Enhancement New feature or request and removed Tag: Help Me Whelp! extra attention is needed here Type: Enhancement New feature or request labels Oct 6, 2023
@0xdavinchee 0xdavinchee self-assigned this Oct 6, 2023
@0xdavinchee
Copy link
Contributor Author

0xdavinchee commented Oct 6, 2023

Investigation steps:

  1. Check out the multicall3 contract
  2. Come up w/ rough architecture/spec for what this multicall forwarder would look like

Other considerations

  • how will this contract would integrate w/ downstream tooling (e.g. viem)
  • how will this work with EOAs vs. smart contract accounts (e.g. Safe)

@0xdavinchee
Copy link
Contributor Author

General architecture
Private Zenhub Image

Implementation Details notes
The second point claims that all callAgreement stuff should just work, this is true if we use craft forwardBatchCall call data and use it in the multicall.

Other considerations

  • how will this contract would integrate w/ downstream tooling (e.g. viem)
    • source: https://viem.sh/docs/contract/multicall.html
    • viem supports multicall out of the box, however it seems to only be for reads and not for writes as it goes through the publicClient, not a walletClient, but maybe this exists for the walletClient too
    • there is a multicallAddress property which can be used to override the default multicall3 contract with our own multicall forwarder contract
  • how will this work with EOAs vs. smart contract accounts (e.g. Safe)
    • it should be basically the same, there isn't any immediately obvious issues if using a safe, but it would be best to just test it out on a testnet first
  • might be a good idea to have a reentrancy lock for the batchMsgSender

Basic contract to test assumptions

// SPDX-License-Identifier: AGPLv3

pragma solidity 0.8.19;

import "forge-std/Test.sol";

contract A {

	function b() public {
		console.log("this would be the host contract (target contract)");
	}

}

contract B {

	function ay(address a) public {
	
		(bool success,) = a.call(abi.encodeWithSignature("b()"));
	}
}

contract C {

address public b;

	constructor(address _b) {
		b = _b;
	}
	
	function dCall(address a) public {
		console.log("this would be the multicall forwarder doing delegatecall to multicall3");
		
		(bool success, ) = address(b).delegatecall(abi.encodeWithSignature("ay(address)", a));
	}
}

contract TestC is Test {

	A public a;
	B public b;
	C public c;
	
	function setUp() public {
		a = new A();
		console.log("a", address(a));
		b = new B();
		console.log("b", address(b));
		c = new C(address(b));
		console.log("c", address(c));
	}
	
	function testDat() public {
		vm.startPrank(address(69));
		c.dCall(address(a));
		vm.stopPrank();
	}
}

@0xdavinchee
Copy link
Contributor Author

We might add this to host, but not now, we are just focusing on a forwarder.
Next steps: try doing CFAForwarder txn's via multicall3 via a forked test

@0xdavinchee
Copy link
Contributor Author

here is what the multicall forwarder would resemble without the fees: https://github.com/0xdavinchee/superfluid-multicall-forwarder/blob/main/src/SuperfluidMulticallForwarder.sol

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Team: Protocol Protocol Core, Sentinel, Peripherals, Protocol Infrastructure Tools & DevOps Type: Spike Task that is to be timeboxed
Projects
None yet
Development

No branches or pull requests

2 participants