superfluid-finance / protocol-monorepo

Superfluid Protocol Monorepo: the specification, implementations, peripherals and development kits.
https://www.superfluid.finance
Other
874 stars 237 forks source link

[ETHEREUM-CONTRACTS] TrustedMacros: A TrustedForwarder that rules them all #1782

Open hellwolf opened 8 months ago

hellwolf commented 8 months ago

Overview

What?

This is a trusted forwarder with high degree of extensibility through permission-less and user-defined "macro contracts", where:

An example user-defined macro request using eip-712:

image

How?

  1. Upon requested by the TrustedMacro contract, a user-defined macro should return a array of Superfluid batch operations, which will be send to trustedForwardBatchCall by the TrustedMacro.
  2. A user-defined macro is stateless but still can query other external contracts, which eliminates a class of security issues without compromising extensibility completely.

[missing image]

Why?

Deadline:

Technical Design Document (TDD):

Acceptance criteria

Links/Resources

hellwolf commented 8 months ago

An example user-defined macro request using eip-712:

image

hellwolf commented 8 months ago

Work in progress: https://github.com/superfluid-finance/protocol-monorepo/pull/1786

contract TokenBatchStreamerMacro is IUserDefinedMacro {
    function executeMacro(ISuperfluid host, bytes memory params) external view
        returns (ISuperfluid.Operation[] memory operations)
    {
        IConstantFlowAgreementV1 cfa = IConstantFlowAgreementV1(address(host.getAgreementClass(
            keccak256("org.superfluid-finance.agreements.ConstantFlowAgreement.v1")
        )));
        (ISuperToken token, int96 flowRate, address[] memory recipients) =
            abi.decode(params, (ISuperToken, int96, address[]));
        operations = new ISuperfluid.Operation[](recipients.length);
        // Build batch call operations here
        for (uint i = 0; i < recipients.length; ++i) {
            bytes memory callData = abi.encodeCall(cfa.createFlow,
                                                   (token,
                                                    recipients[i],
                                                    flowRate,
                                                    new bytes(0) // placeholder
                                                   ));
            operations[i] = ISuperfluid.Operation({
                operationType : BatchOperation.OPERATION_TYPE_SUPERFLUID_CALL_AGREEMENT, // type
                target: address(cfa),
                data: abi.encode(callData, new bytes(0))
                });
        }
    }

    function hash712Params(bytes memory params) external view returns (bytes32 hash) {
        (ISuperToken token, int96 flowRate, address[] memory recipients) =
            abi.decode(params, (ISuperToken, int96, address[]));
    }
}
hellwolf commented 7 months ago

Scroll transaction breakdown.

Reference: https://docs.scroll.io/en/developers/guides/estimating-gas-and-tx-fees/

Example:

https://scrollscan.com/tx/0xbcf040cf21c27a1cb3b3ee158ee5fd48d6444d139f8aa5898d74f4bedad7029f

Value: 0 ETH ($0.00)
Total Tx Fee: 0.000220640420055117 ETH ($0.49)
Gas Price: 0.0000000006 ETH (0.6 Gwei)
Gas Limit & Usage by Txn: 700,000 | 242,946 (34.71%)
L1 Data Fee 0.000074872820055117 ETH ($0.17)
Execution Fee 0.0001457676 ETH ($0.33)

In this case, the L2 execution fee is still a large portion (60%) of the transaction fee.

Optimism/Arbitrum

They still have significantly lower L2 execution fee.

In case of optimism, it's in tune of Mwei.

While in case of Arbitru, L1+L2 gas fees are mixed together in reporting. It sometimes ends up being 0.1 Gwei.

hellwolf commented 7 months ago

A blurb:

For future reference:

A new builder's tool by Superfluid: Macros.
"Build it in solidity, ship it with ethersca-as-ui or generative-macro-UI (coming soon...)."
From #nocode to #onlysoliditycode .
Benefits:
build less, ship more
gas savings on rollup-centric L2s
readable multi-lingual ERC712 signatures
gasless transactions for end users with ERC712 signatures