Skip to content

Instantly share code, notes, and snippets.

@hellwolf
Created January 2, 2023 12:31
Show Gist options
  • Save hellwolf/81474048d297abe8a3bb66d9918d457c to your computer and use it in GitHub Desktop.
Save hellwolf/81474048d297abe8a3bb66d9918d457c to your computer and use it in GitHub Desktop.
Superfluid Constant Flow Toy Model
let currentTime = parseInt(Date.now()/1000); // current unix time in seconds
class SuperfluidToken {
accounts = {};
cfaAgreements = {}
_getAccount(owner) {
let acc = this.accounts[owner];
if (!acc) {
this.accounts[owner] = acc = {
settledBalance: 0,
settledTime: currentTime,
netFlowRate: 0,
}
}
return acc;
}
balanceOf(owner) {
const acc = this.accounts[owner];
if (!acc) return 0;
return acc.settledBalance +
(currentTime - acc.settledTime) * acc.netFlowRate;
}
mint(owner, amount) {
const acc = this._getAccount(owner);
acc.settledBalance += amount;
}
transfer(sender, receiver, amount) {
const senderAcc = this._getAccount(sender);
const receiverAcc = this._getAccount(receiver);
if (this.balanceOf(sender) < amount) throw new Error("Not enough balance");
senderAcc.settledBalance -= amount;
receiverAcc.settledBalance += amount;
}
updateFlow(sender, receiver, flowRate) {
const senderAcc = this._getAccount(sender);
const receiverAcc = this._getAccount(receiver);
const flowId = sender + ":" + receiver;
const flow = this.cfaAgreements[flowId];
if (flow) {
flow.updatedAt = currentTime;
flow.flowRate = flowRate;
} else {
this.cfaAgreements[flowId] = {
createdAt: currentTime,
updatedAt: currentTime,
flowRate
}
}
[senderAcc, receiverAcc].map(acc => {
acc.settledBalance += (currentTime - acc.settledTime) * acc.netFlowRate;
acc.settledTime = currentTime;
});
senderAcc.netFlowRate -= flowRate;
receiverAcc.netFlowRate += flowRate;
}
}
// Tests
function printAccount(token, owner) {
console.log(`${owner} balanceOf:${token.balanceOf(owner)}`);
}
const token = new SuperfluidToken();
console.log("# mint to bob $100");
printAccount(token, "bob");
token.mint("bob", 100);
printAccount(token, "bob");
console.log("# transfer $10 from bob to alice");
token.transfer("bob", "alice", 10);
printAccount(token, "bob");
printAccount(token, "alice");
console.log("# transfer $100.1 from bob should fail");
try { token.transfer("bob", "alice", 100.1) } catch (err) { console.log("Caught:", err.message); };
console.log("# create flow from bob to alice at $10/hour");
token.updateFlow("bob", "alice", 10/3600);
printAccount(token, "bob");
printAccount(token, "alice");
console.log("# advancing for 2 hours...");
currentTime += 3600 *2;
printAccount(token, "bob");
printAccount(token, "alice");
console.log("# create flow from alice to carol at $5/hour");
token.updateFlow("alice", "carol", 5/3600);
printAccount(token, "bob");
printAccount(token, "alice");
printAccount(token, "carol");
console.log("# advancing for 2 hours...");
currentTime += 3600 *2;
printAccount(token, "bob");
printAccount(token, "alice");
printAccount(token, "carol");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment