Calling Super Agreements
Using Superfluid at the Smart Contract Level
Working With Superfluid Using Solidity
When you open a stream or make use of instant distributions, what you're really doing is interacting with Superfluid agreements. Money streams are created by interacting with the constant flow agreement (CFA), while calls related to instant distributions are done by working with the instant distribution agreement (IDA).
NOTE: the easiest way to create money streams or work with the IDA in solidity is via the CFAv1 Library and IDAv1 Library.
To get started, you'll need to be sure to import, at minimum, the Superfluid host interface & agreement interface that you'd like to work with. In a situation where you'd like to use both the CFA and IDA in the same contract, you would import these contracts like this:
If you'd like to interact with a Superfluid agreement directly by using solidity, you need to make a function call first to the Superfluid host contract. You'll call the callAgreement
or callAgreementWithContext
function on the host contract (Superfluid.sol
), and pass in a few parameters:
ISuperAgreement agreementClass
- the the agreement you're going to interact with (either the CFA or IDA)
bytes memory calldata
- the transaction you're calling on the agreement you're interacting with, compiled to bytecode (using one of solidity's encoding methods)
bytes memory userData
- any additional data you'd like to include with your function call. If you don't plan to add userData, you can pass in an empty bytes value (i.e. "0x"
). You can learn more about this parameter here.
Here's an example of how this looks in action when interacting with the constant flow agreement. This pattern will be the same whether you're creating, updating, or deleting flows.
The following is an example for interacting with the instant distribution agreement using solidity. This pattern is the same for each interaction you'd like to make with the IDA:
NOTE: If you're interacting with agreements inside of a Super App callback, this process will work differently. See this section for details.
Common Mistakes
One other thing to keep in mind is the value of msg.sender
when working with Superfluid from a contract. For example, developers will occasionally want to create a function which will let an account create a flow into the contract itself. So, they'll write a function that looks like this, expecting it to create a flow into the contract from the msg.sender
of the function:
In the above function, you have set the receiver on the cfaV1.createFlow
function to be the contract's address. Under the hood, even though msg.sender
on the broader createFlowFail
function is an external address, the msg.sender on the cfa.createFlow
call to the Superfluid protocol is the address of the contract. The Superfluid callAgreement
function will see that the contract is trying to create a flow into itself, and revert.
If you want to create a flow into a contract, we recommend that you use either the Core-SDK from outside of a contract or a 2nd contract which already has some balance of Super Tokens.
A similar mistake which stems from this msg.sender
misunderstanding occurs when developers want to allow external accounts to create flows directly to other accounts via a function on the contract. For example:
Recall that the value of msg.sender
on the cfaV1.createFlow
function will be the contract's address, not the external address calling the broader createFlow2Receiver
function. If you're intending to create a flow from the contract to another address, then this code is what you need (just make sure your contract has a balance of Super tokens!). However, if you're running this with the expectation that it will open a flow directly from an external account calling the function to the intended receiver, it will not work as expected.
Last updated