diff --git a/contracts/Vault.sol b/contracts/Vault.sol index 2d5a838..fefb265 100644 --- a/contracts/Vault.sol +++ b/contracts/Vault.sol @@ -79,6 +79,11 @@ contract Vault is VaultBase { _flow(controller, fund, from, to, rate); } + function burnDesignated(Fund fund, Recipient recipient, uint128 amount) public { + Controller controller = Controller.wrap(msg.sender); + _burnDesignated(controller, fund, recipient, amount); + } + function burnAccount(Fund fund, Recipient recipient) public { Controller controller = Controller.wrap(msg.sender); _burnAccount(controller, fund, recipient); diff --git a/contracts/vault/VaultBase.sol b/contracts/vault/VaultBase.sol index aa9cb5f..494e50d 100644 --- a/contracts/vault/VaultBase.sol +++ b/contracts/vault/VaultBase.sol @@ -170,6 +170,23 @@ abstract contract VaultBase { _accounts[controller][fund][to] = receiver; } + function _burnDesignated( + Controller controller, + Fund fund, + Recipient recipient, + uint128 amount + ) internal { + Lock memory lock = _locks[controller][fund]; + require(lock.status() == LockStatus.Locked, FundNotLocked()); + + Account storage account = _accounts[controller][fund][recipient]; + require(account.balance.designated >= amount, InsufficientBalance()); + + account.balance.designated -= amount; + + _token.safeTransfer(address(0xdead), amount); + } + function _burnAccount( Controller controller, Fund fund, diff --git a/test/Vault.tests.js b/test/Vault.tests.js index 4d25969..91cfcde 100644 --- a/test/Vault.tests.js +++ b/test/Vault.tests.js @@ -452,6 +452,7 @@ describe("Vault", function () { }) describe("burning", function () { + const dead = "0x000000000000000000000000000000000000dead" const amount = 1000 beforeEach(async function () { @@ -460,6 +461,47 @@ describe("Vault", function () { await vault.deposit(fund, account.address, amount) }) + describe("burn designated", function () { + const designated = 100 + + beforeEach(async function () { + await vault.designate(fund, account.address, designated) + }) + + it("burns a number of designated tokens", async function () { + await vault.burnDesignated(fund, account.address, 10) + expect( + await vault.getDesignatedBalance(fund, account.address) + ).to.equal(designated - 10) + expect(await vault.getBalance(fund, account.address)).to.equal( + amount - 10 + ) + }) + + it("can burn all of the designated tokens", async function () { + await vault.burnDesignated(fund, account.address, designated) + expect( + await vault.getDesignatedBalance(fund, account.address) + ).to.equal(0) + expect(await vault.getBalance(fund, account.address)).to.equal( + amount - designated + ) + }) + + it("cannot burn more than all designated tokens", async function () { + await expect( + vault.burnDesignated(fund, account.address, designated + 1) + ).to.be.revertedWith("InsufficientBalance") + }) + + it("moves burned tokens to address 0xdead", async function () { + const before = await token.balanceOf(dead) + await vault.burnDesignated(fund, account.address, 10) + const after = await token.balanceOf(dead) + expect(after - before).to.equal(10) + }) + }) + describe("burn account", function () { it("can burn an account", async function () { await vault.burnAccount(fund, account.address) @@ -475,7 +517,6 @@ describe("Vault", function () { }) it("moves account tokens to address 0xdead", async function () { - const dead = "0x000000000000000000000000000000000000dead" await vault.designate(fund, account.address, 10) const before = await token.balanceOf(dead) await vault.burnAccount(fund, account.address) @@ -511,7 +552,6 @@ describe("Vault", function () { }) it("moves all tokens in the fund to address 0xdead", async function () { - const dead = "0x000000000000000000000000000000000000dead" await vault.transfer(fund, account.address, account2.address, 10) await vault.transfer(fund, account.address, account3.address, 10) const before = await token.balanceOf(dead) @@ -822,6 +862,12 @@ describe("Vault", function () { ).to.be.revertedWith("FundNotLocked") }) + it("does not allow burning of designated tokens", async function () { + await expect( + vault.burnDesignated(fund, account.address, 1) + ).to.be.revertedWith("FundNotLocked") + }) + it("does not allow burning of accounts", async function () { await expect(vault.burnAccount(fund, account.address)).to.be.revertedWith( "FundNotLocked"