vault: change flows over time

This commit is contained in:
Mark Spanbroek 2025-01-28 14:58:14 +01:00
parent ac52545574
commit bb7c66629b
3 changed files with 49 additions and 5 deletions

View File

@ -11,6 +11,7 @@ using {_tokensPerSecondPlus as +} for TokensPerSecond global;
using {_tokensPerSecondEquals as ==} for TokensPerSecond global;
using {_tokensPerSecondNotEqual as !=} for TokensPerSecond global;
using {_tokensPerSecondAtLeast as >=} for TokensPerSecond global;
using {_tokensPerSecondLessThan as <} for TokensPerSecond global;
function _tokensPerSecondNegate(
TokensPerSecond rate
@ -54,3 +55,10 @@ function _tokensPerSecondAtLeast(
) pure returns (bool) {
return TokensPerSecond.unwrap(a) >= TokensPerSecond.unwrap(b);
}
function _tokensPerSecondLessThan(
TokensPerSecond a,
TokensPerSecond b
) pure returns (bool) {
return TokensPerSecond.unwrap(a) < TokensPerSecond.unwrap(b);
}

View File

@ -179,22 +179,36 @@ abstract contract VaultBase {
Lock memory lock = _locks[controller][context];
require(lock.isLocked(), LockRequired());
Timestamp start = Timestamps.currentTime();
Balance memory senderBalance = _getBalance(controller, context, from);
Balance memory receiverBalance = _getBalance(controller, context, to);
Flow memory senderFlow = _flows[controller][context][from];
Flow memory receiverFlow = _flows[controller][context][to];
Timestamp start = Timestamps.currentTime();
senderFlow.start = start;
senderFlow.rate = senderFlow.rate - rate;
Flow memory receiverFlow = _flows[controller][context][to];
receiverFlow.start = start;
receiverFlow.rate = receiverFlow.rate + rate;
Balance memory senderBalance = _getBalance(controller, context, from);
uint128 flowMaximum = uint128(-senderFlow._totalAt(lock.maximum));
require(flowMaximum <= senderBalance.available, InsufficientBalance());
_checkFlowInvariant(senderBalance, lock, senderFlow);
_balances[controller][context][from] = senderBalance;
_balances[controller][context][to] = receiverBalance;
_flows[controller][context][from] = senderFlow;
_flows[controller][context][to] = receiverFlow;
}
function _checkFlowInvariant(
Balance memory balance,
Lock memory lock,
Flow memory flow
) private pure {
if (flow.rate < TokensPerSecond.wrap(0)) {
uint128 outgoing = uint128(-flow._totalAt(lock.maximum));
require(outgoing <= balance.available, InsufficientBalance());
}
}
error InsufficientBalance();
error Locked();
error AlreadyLocked();

View File

@ -476,6 +476,28 @@ describe("Vault", function () {
expect(await getBalance(receiver2)).to.equal(8)
})
it("can change flows over time", async function () {
await setAutomine(false)
await vault.flow(context, sender, receiver, 1)
await vault.flow(context, sender, receiver2, 2)
await mine()
const start = await currentTime()
advanceTimeToForNextBlock(start + 4)
await vault.flow(context, receiver2, receiver, 1)
await mine()
expect(await getBalance(sender)).to.equal(deposit - 12)
expect(await getBalance(receiver)).to.equal(4)
expect(await getBalance(receiver2)).to.equal(8)
await advanceTimeTo(start + 8)
expect(await getBalance(sender)).to.equal(deposit - 24)
expect(await getBalance(receiver)).to.equal(12)
expect(await getBalance(receiver2)).to.equal(12)
await advanceTimeTo(start + 12)
expect(await getBalance(sender)).to.equal(deposit - 36)
expect(await getBalance(receiver)).to.equal(20)
expect(await getBalance(receiver2)).to.equal(16)
})
it("designates tokens that flow for the recipient", async function () {
await vault.flow(context, sender, receiver, 3)
const start = await currentTime()