Skip to content

Presentation compoextreme

Miao, ZhiCheng edited this page Aug 2, 2023 · 6 revisions

Composability Extreminists: Callback or No-Callbacks?

⚠ This file is automatically generated from this org file using this script.

The exported presentation can be accessed via this githack link.

REVISIONS:

Date Notes
2022-06-05 Draft for ETHPrague Speech
2022-06-08 Added Super Agreement Forwarder Control Flow per Protocol Workshop
2022-06-19 Added Compatibility with Standard section

What We Have Got Today?

ERC-777 Transaction Event Hooks

Good Idea: single tx of send+tokensReceived

function tokensReceived(
    address operator,
    address from,
    address to,
    uint256 amount,
    bytes calldata data,
    bytes calldata operatorData
) external

Bad Idea: Change the Semantics of ERC20.transfer

  • First Uniswap V1 (~300k $ drained)
  • Then lendf.me (defunct) (~24m $ drained)

Reality: We Are Stuck With approve/transferFrom

// Two ransactions from the EOA
token1.approve(exchange, amount);
exchange.doSomeExchangeOp();

// in Exchange contract:
function doSomeExchangeOp(uint amount) external {
    token1.transferFrom(msg.sender, amount);
    swapSomeToken1ForToken2(amount);
    token2.transfer(msg.sender, amount);
}

Super Token “Dialect”

  • Supports ERC-777 interface.
  • But only invoking tokensReceived callback in ERC777.send.
  • Supports more callbacks…

History of ERC-777

More details at https://github.com/superfluid-finance/protocol-monorepo/wiki/About-ERC-777 §Reference (Kudos to Didi/@d10r)

Super Token Agreement Life Cycle Events Hooks

Superfluid Agreements

  • Representing ongoing relationships between accounts.
  • Providing real time balances to related accounts.
    balanceOfAccountAt holderAccount t = foldr -- (js) reduce
        ((+) . (`providedBalanceOfAnyAgreement` t))
        def -- initial balance: def(ault) value/zero
        (agreementsOfAccount holderAccount)
        
  • Implemented agreements:
    • Constant Flow Agreement (CFA) - Streaming money every block.
    • Instant Distribution Agreement (IDA) - Money Fan-out on steroids.
  • To be introduced:
    • Transferable Balance Agreement (TBA) - ERC20 “baptized”.
    • Decaying Flow Agreement.
    • General Distribution Agreement (GDA).

CFA Life Cycle Events

function beforeAgreementCreated;
function afterAgreementCreated;
function beforeAgreementUpdated;
function afterAgreementUpdated;
function beforeAgreementTerminated;
function afterAgreementTerminated;

Become a Composability Extremist

  • Super App, the contract that implemented the agreement life cycle hooks.
  • It enables atomic/transactional composable agreements.
  • Let’s see some examples…

Super App Example 1: DCA

Many want to invest every day some USDC for BTC.

title Dollar Cost Averaging
skinparam backgroundColor #EEEBDC
skinparam handwritten true
skinparam rectangle {
  BackgroundColor<<Super App>> PaleGreen
  backgroundColor<<EOA>> DarkKhaki
  BackgroundColor<<Contract>> DeepSkyBlue
}

rectangle Alice <<EOA>>
rectangle Bob <<EOA>>
rectangle Agent
circle Index
rectangle "DCA Super App" as DCA <<Super App>>
rectangle Exchange <<Contract>>

DCA -up-> Index: Distribute WBTC
DCA -right-> Exchange: Swap USDC for WBTC Periodically
Agent -up-> DCA: Poll & Trigger Swaps

Alice -down-> DCA: Stream USDC
Alice <-- Index: Receives WBTC
Bob -down-> DCA: Stream USDC
Bob <-- Index: Receives WBTC

RESULTS:

Super App Example 2: Referral Link App

Marketer gets commission paid the moment referral link is used.

title Referral Link App
skinparam backgroundColor #EEEBDC
skinparam handwritten true
skinparam rectangle {
  BackgroundColor<<Super App>> PaleGreen
  backgroundColor<<EOA>> DarkKhaki
  BackgroundColor<<Contract>> DeepSkyBlue
}

rectangle Buyer <<EOA>>
rectangle Merchant <<EOA>>
rectangle Marketer <<EOA>>
rectangle "Referral Link App" as App <<Super App>>

Marketer ~right~> Buyer: Share referral link to Merchant
Buyer ~left~> Merchant: Subscribe to a service
Buyer -down-> App: Use referral link and stream payment
App -up-> Marketer: 10% referral fee in streams
App -up-> Merchant: 90% money

RESULTS:

What Are the Problems?

Callbacks Are Scary:

  • Callbacks can (but not necessarily) introduce re-entrance issue,
  • in additional to the bad design of breaking change of ERC-777.transfer,
  • the list of EVM related exploits are wrought with re-entrance issues.

Solutions to Callback Problems:

  • Avoidance (not really a solution).
  • Idiomatic programming patterns:
    • Checks-effects-interactions.
    • Mutex/Re-entrance lock.
  • Use different account model (e.g. EUTXO), which curbs the bad habit of introducing side effects in callbacks without easy way of reasoning the effects.

Agreement Exit Guarantee

Stream sender must always be able to close the stream.

Problem: agreement deleted event hook can fail or enter a dead-loop.

App Jail System

  • Triggers in a agreement deleted event hook:
    • reverts,
    • out of callback gas budget,
    • etc.
  • Rationale: If an app can fail once, it’s like can fail again

Slow Down. What is Composability?

What Do Some Web3 People Have to Say

  • https://multicoin.capital/2022/02/16/composable-web3-compute/
  • https://future.com/how-composability-unlocks-crypto-and-everything-else/
  • https://blog.aragon.org/what-is-composality/
  • https://thenewstack.io/ceramics-web3-composability-resurrects-web-2-0-mashups/

Conceptual Interoperability Model

Integratability (L1 Technical, L2 Syntactic)

  • EVM opcodes for interacting with contract codes:
    • staticcall - readonly/view calls, getter, query, etc.
    • delegatecall (deprecating callcode) - let other code manage caller’s storage, proxy contract
    • call - internal transaction.
  • EVM transaction supports roll-backs.

Interoperability (L3 Semantic, L4 Pragmatic)

  • Solidity ABI Contract Specification.
  • ⚠ ATTN! Non-Solidity Contract ABI interaction with contract code is always possible.
    • Exploit of Solidty Contract ABI decoder bug.
    • Under the radar transactions.

Composability (L5 Dynamic, L6 Conceptual)

  • Modular:
    • Distribute your concepts through open-sourced solidity interface files.
  • Autonomous:
    • Permission-less.
  • Discoverable:
    • Provide example codes helping others to integrate.
    • Self-documented contracts? (Example in other domains: WSDL)

Composability Patterns & Examples:

Compatibility with Standards

  • ERC-20 and its ecosystem (wallet, defi, block scanner, etc.)
  • ERC-777 and its lack of adoption.
  • EIP-2771: Secure Protocol for Native Meta Transactions.

    The Trusted Forwarder is responsible for calling the Recipient contract and MUST append the address of the Transaction Signer (20 bytes of data) to the end of the call data.

“Plugins”

  • rDAI strategy (using Compound Finance)
  • Yearn Vaults.
  • Superfluid Agreements.

Transactional Systems

  • Flash Loans
    • Borrow -> Attempt arbitrage -> Revert if not profitable
  • Any Super Apps
    • Revert

Conceptual Systems, Beyond Single Transaction or Single Agent:

  • Automated Market Makers (AMMs)
  • Certain Super App: DCA, Stream Swap, Transferable Cash Flow etc.

Different Control Flows

Actual Control Flow

title Actual Superfluid Control Flow - createFlow to a Super App
skinparam backgroundColor #EEEBDC
skinparam handwritten true
skinparam dpi 80

autoactivate on
actor Alice
entity "Superfluid Host" as Host
entity CFA
entity Token
entity "Super App" as App

Alice -> Host: callAgreement
  Host -> CFA: createFlow
  note left: ducktype-polymorphic\nevm external call to:\nabi.encodeCall(createFlow,...)
    CFA -> Token #red: token storages updates
    return
    CFA -> App #green : flow life-cycle callback
      opt Level 1 Super App wants to compose
        App -> App: Do Some App Stuff
        return
        App -> Host #gold : Nested callAgreement
          Host -> Host: Perform re-entrance protection
          note left: some nested operations...
          Host -> Token #red: update token storages
          return
        return
      end
    return
  return
return

RESULTS:

Agreement Forwarder

What it Is

  • userData in overloaded functions, or single function with it default to “0x”
    • overloaded function may give confusing error messages, unless we utilize user defined types for generic types “bytes[]”.
  • version management
    • immutable forwarder.
    • release new version of forwarders for upgrades.
  • functions:
    • :CFA
    • creatFlow
    • updateFlow
    • deleteFlow
    • setFlow / flow (user.flow)
    • :IDA
    • createIndex
    • updateSubscriptionUnit
    • approveSubscription
    • revokeSubscripion
    • distribute
    • claim
    • :FDA
    • updateIndexFlow

How it looks like

title Super Agreement Forwarder
skinparam backgroundColor #EEEBDC
skinparam handwritten true
skinparam defaultFontName Impact
skinparam dpi 100

autoactivate on
actor Mario
entity "Super Agreement\nForwarder" as SAF
entity "Superfluid Host" as Host
entity "CFA" as CFA
entity Token

Mario -> SAF: createFlow
  SAF -> Host: forwardBatchCall [createFlow]
    Host -> CFA: createFlow
      CFA -> Token #red: update storages
      return
    return
  return
return

RESULTS:

Functional Agreement and Token Centric Control Flow

Advantages

  • Token becomes what Alice interacts first:
  • More natural API:
    • token.transfer
    • token.createFlow/updateFlow/deleteFlow
    • token.createIndex/distributeToIndex/updateIndexFlow/subcribeToIndex
  • Functional composition, restraining side effects

How It Looks Like

title Token Centric Control Flow
skinparam backgroundColor #EEEBDC
skinparam handwritten true
skinparam defaultFontName Impact
skinparam dpi 100

autoactivate on
actor Alice
entity Token
entity "Superfluid Host" as Host
entity "Functional CFA" as CFA
entity "Super App" as App

Alice -> Token: createFlow
  Token -> Host: safeCallAgreement
    Host -> CFA: createFlow (pure)
    note left: type-safe runtime polymorphic\n+ pure function
    return token update instructions
    opt Super App wants to compose
      Host -> App #green: flow life-cycle callback
        App -> Host #gold: Nested callAgreement
        note left: save additional\ntoken update instructions
        return
      return
    end
    Host -> Token #red: commit token update instructions
    return
  return
return

RESULTS:

Conclusion

  • Composability is powerful, and worth the efforts.
  • Composability is not a new problem, we should draw insights and lessons from the past.
  • There is more than one way to achieve composability.

Thank You

Clone this wiki locally