vault: reject flow when insufficient tokens available

This commit is contained in:
Mark Spanbroek 2025-01-23 14:28:17 +01:00
parent d9452a7ac2
commit 38f3a73c8f
2 changed files with 37 additions and 12 deletions

View File

@ -184,11 +184,13 @@ abstract contract VaultBase {
Recipient to, Recipient to,
TokensPerSecond rate TokensPerSecond rate
) internal { ) internal {
require( Lock memory lock = _getLock(controller, context);
_getLock(controller, context).expiry != Timestamp.wrap(0), require(lock.expiry != Timestamp.wrap(0), LockRequired());
LockRequired()
);
Timestamp start = Timestamps.currentTime(); Timestamp start = Timestamps.currentTime();
uint64 duration = Timestamp.unwrap(lock.maximum) - Timestamp.unwrap(start);
int256 total = int256(uint256(duration)) * TokensPerSecond.unwrap(rate);
Balance memory balance = _getBalance(controller, context, from);
require(total <= int256(balance.available), InsufficientBalance());
_flows[controller][context][to] = Flow({start: start, rate: rate}); _flows[controller][context][to] = Flow({start: start, rate: rate});
_flows[controller][context][from] = Flow({start: start, rate: -rate}); _flows[controller][context][from] = Flow({start: start, rate: -rate});
} }

View File

@ -383,14 +383,14 @@ describe("Vault", function () {
describe("flow", function () { describe("flow", function () {
const context = randomBytes(32) const context = randomBytes(32)
const amount = 42 const deposit = 100
let sender let sender
let receiver let receiver
beforeEach(async function () { beforeEach(async function () {
await token.connect(account).approve(vault.address, amount) await token.connect(account).approve(vault.address, deposit)
await vault.deposit(context, account.address, amount) await vault.deposit(context, account.address, deposit)
sender = account.address sender = account.address
receiver = account2.address receiver = account2.address
}) })
@ -408,20 +408,22 @@ describe("Vault", function () {
describe("when a lock is set", async function () { describe("when a lock is set", async function () {
let expiry let expiry
let maximum
beforeEach(async function () { beforeEach(async function () {
expiry = (await currentTime()) + 20 expiry = (await currentTime()) + 20
await vault.lockup(context, expiry, expiry) maximum = expiry + 10
await vault.lockup(context, expiry, maximum)
}) })
it("moves tokens over time", async function () { it("moves tokens over time", async function () {
await vault.flow(context, sender, receiver, 2) await vault.flow(context, sender, receiver, 2)
const start = await currentTime() const start = await currentTime()
await advanceTimeTo(start + 2) await advanceTimeTo(start + 2)
expect(await vault.balance(context, sender)).to.equal(amount - 4) expect(await vault.balance(context, sender)).to.equal(deposit - 4)
expect(await vault.balance(context, receiver)).to.equal(4) expect(await vault.balance(context, receiver)).to.equal(4)
await advanceTimeTo(start + 4) await advanceTimeTo(start + 4)
expect(await vault.balance(context, sender)).to.equal(amount - 8) expect(await vault.balance(context, sender)).to.equal(deposit - 8)
expect(await vault.balance(context, receiver)).to.equal(8) expect(await vault.balance(context, receiver)).to.equal(8)
}) })
@ -437,12 +439,33 @@ describe("Vault", function () {
const start = await currentTime() const start = await currentTime()
await advanceTimeTo(expiry) await advanceTimeTo(expiry)
const total = (expiry - start) * 2 const total = (expiry - start) * 2
expect(await vault.balance(context, sender)).to.equal(amount - total) expect(await vault.balance(context, sender)).to.equal(deposit - total)
expect(await vault.balance(context, receiver)).to.equal(total) expect(await vault.balance(context, receiver)).to.equal(total)
await advanceTimeTo(expiry + 10) await advanceTimeTo(expiry + 10)
expect(await vault.balance(context, sender)).to.equal(amount - total) expect(await vault.balance(context, sender)).to.equal(deposit - total)
expect(await vault.balance(context, receiver)).to.equal(total) expect(await vault.balance(context, receiver)).to.equal(total)
}) })
it("flows longer when lock is extended", async function () {
await vault.flow(context, sender, receiver, 2)
const start = await currentTime()
await vault.extend(context, maximum)
await advanceTimeTo(maximum)
const total = (maximum - start) * 2
expect(await vault.balance(context, sender)).to.equal(deposit - total)
expect(await vault.balance(context, receiver)).to.equal(total)
await advanceTimeTo(maximum + 10)
expect(await vault.balance(context, sender)).to.equal(deposit - total)
expect(await vault.balance(context, receiver)).to.equal(total)
})
it("rejects flow when insufficient available tokens", async function () {
const duration = maximum - await currentTime()
const rate = Math.round(deposit / duration)
await expect(
vault.flow(context, sender, receiver, rate + 1)
).to.be.revertedWith("InsufficientBalance")
})
}) })
}) })
}) })