vault: only allow deposit, transfer, etc when locked

This commit is contained in:
Mark Spanbroek 2025-02-03 16:26:51 +01:00
parent 3864559d85
commit 6e531f2087
2 changed files with 81 additions and 4 deletions

View File

@ -79,9 +79,18 @@ abstract contract VaultBase {
address from, address from,
uint128 amount uint128 amount
) internal { ) internal {
Lock memory lock = _locks[controller][context];
require(lock.isLocked(), LockRequired());
Recipient recipient = Recipient.wrap(from); Recipient recipient = Recipient.wrap(from);
_balances[controller][context][recipient].available += amount; Balance memory balance = _balances[controller][context][recipient];
_locks[controller][context].value += amount;
balance.available += amount;
lock.value += amount;
_balances[controller][context][recipient] = balance;
_locks[controller][context] = lock;
_token.safeTransferFrom(from, address(this), amount); _token.safeTransferFrom(from, address(this), amount);
} }
@ -123,6 +132,7 @@ abstract contract VaultBase {
Recipient recipient Recipient recipient
) internal { ) internal {
Lock memory lock = _locks[controller][context]; Lock memory lock = _locks[controller][context];
require(lock.isLocked(), LockRequired());
Flow memory flow = _flows[controller][context][recipient]; Flow memory flow = _flows[controller][context][recipient];
require(flow.rate == TokensPerSecond.wrap(0), CannotBurnFlowingTokens()); require(flow.rate == TokensPerSecond.wrap(0), CannotBurnFlowingTokens());
@ -150,6 +160,9 @@ abstract contract VaultBase {
Recipient to, Recipient to,
uint128 amount uint128 amount
) internal { ) internal {
Lock memory lock = _locks[controller][context];
require(lock.isLocked(), LockRequired());
Balance memory senderBalance = _getBalance(controller, context, from); Balance memory senderBalance = _getBalance(controller, context, from);
Balance memory receiverBalance = _getBalance(controller, context, to); Balance memory receiverBalance = _getBalance(controller, context, to);
require(amount <= senderBalance.available, InsufficientBalance()); require(amount <= senderBalance.available, InsufficientBalance());
@ -158,7 +171,6 @@ abstract contract VaultBase {
receiverBalance.available += amount; receiverBalance.available += amount;
Flow memory senderFlow = _flows[controller][context][from]; Flow memory senderFlow = _flows[controller][context][from];
Lock memory lock = _locks[controller][context];
_checkFlowInvariant(senderBalance, lock, senderFlow); _checkFlowInvariant(senderBalance, lock, senderFlow);
_balances[controller][context][from] = senderBalance; _balances[controller][context][from] = senderBalance;
@ -171,6 +183,9 @@ abstract contract VaultBase {
Recipient recipient, Recipient recipient,
uint128 amount uint128 amount
) internal { ) internal {
Lock memory lock = _locks[controller][context];
require(lock.isLocked(), LockRequired());
Balance memory balance = _balances[controller][context][recipient]; Balance memory balance = _balances[controller][context][recipient];
require(amount <= balance.available, InsufficientBalance()); require(amount <= balance.available, InsufficientBalance());
@ -178,7 +193,6 @@ abstract contract VaultBase {
balance.designated += amount; balance.designated += amount;
Flow memory flow = _flows[controller][context][recipient]; Flow memory flow = _flows[controller][context][recipient];
Lock memory lock = _locks[controller][context];
_checkFlowInvariant(balance, lock, flow); _checkFlowInvariant(balance, lock, flow);
_balances[controller][context][recipient] = balance; _balances[controller][context][recipient] = balance;

View File

@ -56,12 +56,37 @@ describe("Vault", function () {
).to.be.revertedWith("LockRequired") ).to.be.revertedWith("LockRequired")
}) })
it("does not allow depositing of tokens", async function () {
const amount = 1000
await token.connect(account).approve(vault.address, amount)
await expect(
vault.deposit(context, account.address, amount)
).to.be.revertedWith("LockRequired")
})
it("does not allow designating tokens", async function () {
await expect(
vault.designate(context, account.address, 0)
).to.be.revertedWith("LockRequired")
})
it("does not allow transfer of tokens", async function () {
await expect(
vault.transfer(context, account.address, account2.address, 0)
).to.be.revertedWith("LockRequired")
})
it("does not allow flowing of tokens", async function () { it("does not allow flowing of tokens", async function () {
await expect( await expect(
vault.flow(context, account.address, account2.address, 0) vault.flow(context, account.address, account2.address, 0)
).to.be.revertedWith("LockRequired") ).to.be.revertedWith("LockRequired")
}) })
it("does not allow burning of tokens", async function () {
await expect(vault.burn(context, account.address)).to.be.revertedWith(
"LockRequired"
)
})
}) })
describe("when lock is locked", function () { describe("when lock is locked", function () {
@ -143,6 +168,8 @@ describe("Vault", function () {
it("separates deposits from different contexts", async function () { it("separates deposits from different contexts", async function () {
const context1 = randomBytes(32) const context1 = randomBytes(32)
const context2 = randomBytes(32) const context2 = randomBytes(32)
await vault.lock(context1, expiry, maximum)
await vault.lock(context2, expiry, maximum)
await token.connect(account).approve(vault.address, 3) await token.connect(account).approve(vault.address, 3)
await vault.deposit(context1, account.address, 1) await vault.deposit(context1, account.address, 1)
await vault.deposit(context2, account.address, 2) await vault.deposit(context2, account.address, 2)
@ -154,6 +181,8 @@ describe("Vault", function () {
const [, , controller1, controller2] = await ethers.getSigners() const [, , controller1, controller2] = await ethers.getSigners()
const vault1 = vault.connect(controller1) const vault1 = vault.connect(controller1)
const vault2 = vault.connect(controller2) const vault2 = vault.connect(controller2)
await vault1.lock(context, expiry, maximum)
await vault2.lock(context, expiry, maximum)
await token.connect(account).approve(vault.address, 3) await token.connect(account).approve(vault.address, 3)
await vault1.deposit(context, account.address, 1) await vault1.deposit(context, account.address, 1)
await vault2.deposit(context, account.address, 2) await vault2.deposit(context, account.address, 2)
@ -689,5 +718,39 @@ describe("Vault", function () {
expect(after).to.equal(before) expect(after).to.equal(before)
}) })
}) })
it("does not allow depositing of tokens", async function () {
setAutomine(true)
await expire()
const amount = 1000
await token.connect(account).approve(vault.address, amount)
await expect(
vault.deposit(context, account.address, amount)
).to.be.revertedWith("LockRequired")
})
it("does not allow designating tokens", async function () {
setAutomine(true)
await expire()
await expect(
vault.designate(context, account.address, 0)
).to.be.revertedWith("LockRequired")
})
it("does not allow transfer of tokens", async function () {
setAutomine(true)
await expire()
await expect(
vault.transfer(context, account.address, account2.address, 0)
).to.be.revertedWith("LockRequired")
})
it("does not allow burning of tokens", async function () {
setAutomine(true)
await expire()
await expect(vault.burn(context, account.address)).to.be.revertedWith(
"LockRequired"
)
})
}) })
}) })