The MetaStreamCloser contract allows a user to provide a digital signature,
giving permission to a third party to close streams on the user's behalf. A
stream's sender or receiver may propmt the contract for a message to sign, the
message being a deleteFlow
function call. By generating a signature and
sending it to a third party, that third party has access to explicitly delete
the unique flow of a token
between the sender
and receiver
exactly once.
At the time of writing, Superfluid has approved a single contract on each network as a "trusted forwarder". The trusted forwarder is a smart contract that verifies an EIP712 digital signature and, if the signature is valid, executes the funcion call on behalf of the signing party, regardless of the message sender.
The message must be generated in accorandance with the BiconomyForwarder's ERC20ForwardRequest.
The message is a sha3 hash of a set of data with abi.encodePacked
. Here is a
soldity example of the message being generated.
bytes32 hash = keccak256(
abi.encodePacked(
senderAddress,
superfluidHostAddress,
tokenAddress, // not applicable
callAgreementGas,
tokenGasPrice, // not applicable
batchId,
batchNonce,
deadline,
keccak256(callAgreementCallData)
)
);
In this case, the tokenAddress
and tokenGasPrice
refers to meta transactions
that may require compensation paid in a non-native token. This protocol does
not require this, but may implement it in the future.
The digital signature is to be generated off-chain using the personal_sign
API.
An example of this with web3.js
is as follows.
const Web3 = require('web3')
const web3 = new Web3()
const privateKey = process.env.PRIV_KEY
const messageHash = '0x' // data returned from contract
function main() {
const { signature } = web3.eth.accounts.sign(messageHash, privateKey)
console.log(signature)
}
Since the signed data allows any address to call this function once, this opens the stream sender to a one-time grief attack. This allows an attacker to delete the user's flow exactly once at any time if they gain access to the digital signature. However, this signature is generated off-chain, and can be encrypted to be sent to a trusted third party for secure storage.
The SDK should immediately take the digital signature as an inoput and encrypt it with a public key, allowing only the owner of the decryption key to decrypt the digital signature and execute the flow deletion on the flow sender's behalf.
Testing is difficult, given the nature of the Biconomy contracts, but this has been successfully executed on the Goerli test network. More testing to come.