mirror of
https://github.com/status-im/codex-contracts-eth.git
synced 2025-02-07 14:13:28 +00:00
755 lines
28 KiB
JavaScript
755 lines
28 KiB
JavaScript
const { expect } = require("chai")
|
|
const { ethers } = require("hardhat")
|
|
const { randomBytes } = ethers.utils
|
|
const {
|
|
currentTime,
|
|
advanceTimeTo,
|
|
mine,
|
|
setAutomine,
|
|
setNextBlockTimestamp,
|
|
snapshot,
|
|
revert,
|
|
} = require("./evm")
|
|
|
|
describe("Vault", function () {
|
|
const fund = randomBytes(32)
|
|
|
|
let token
|
|
let vault
|
|
let controller
|
|
let account, account2, account3
|
|
|
|
beforeEach(async function () {
|
|
await snapshot()
|
|
const TestToken = await ethers.getContractFactory("TestToken")
|
|
token = await TestToken.deploy()
|
|
const Vault = await ethers.getContractFactory("Vault")
|
|
vault = await Vault.deploy(token.address)
|
|
;[controller, account, account2, account3] = await ethers.getSigners()
|
|
await token.mint(account.address, 1_000_000)
|
|
await token.mint(account2.address, 1_000_000)
|
|
await token.mint(account3.address, 1_000_000)
|
|
})
|
|
|
|
afterEach(async function () {
|
|
await revert()
|
|
})
|
|
|
|
describe("when a fund has no lock set", function () {
|
|
it("allows a lock to be set", async function () {
|
|
expiry = (await currentTime()) + 80
|
|
maximum = (await currentTime()) + 100
|
|
await vault.lock(fund, expiry, maximum)
|
|
expect((await vault.getLock(fund))[0]).to.equal(expiry)
|
|
expect((await vault.getLock(fund))[1]).to.equal(maximum)
|
|
})
|
|
|
|
it("does not allow a lock with expiry past maximum", async function () {
|
|
let maximum = (await currentTime()) + 100
|
|
const locking = vault.lock(fund, maximum + 1, maximum)
|
|
await expect(locking).to.be.revertedWith("ExpiryPastMaximum")
|
|
})
|
|
|
|
it("does not allow extending of lock", async function () {
|
|
await expect(
|
|
vault.extendLock(fund, (await currentTime()) + 1)
|
|
).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(fund, account.address, amount)
|
|
).to.be.revertedWith("LockRequired")
|
|
})
|
|
|
|
it("does not allow designating tokens", async function () {
|
|
await expect(
|
|
vault.designate(fund, account.address, 0)
|
|
).to.be.revertedWith("LockRequired")
|
|
})
|
|
|
|
it("does not allow transfer of tokens", async function () {
|
|
await expect(
|
|
vault.transfer(fund, account.address, account2.address, 0)
|
|
).to.be.revertedWith("LockRequired")
|
|
})
|
|
|
|
it("does not allow flowing of tokens", async function () {
|
|
await expect(
|
|
vault.flow(fund, account.address, account2.address, 0)
|
|
).to.be.revertedWith("LockRequired")
|
|
})
|
|
|
|
it("does not allow burning of tokens", async function () {
|
|
await expect(vault.burn(fund, account.address)).to.be.revertedWith(
|
|
"LockRequired"
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("when a fund is locked", function () {
|
|
let expiry
|
|
let maximum
|
|
|
|
beforeEach(async function () {
|
|
const beginning = (await currentTime()) + 10
|
|
expiry = beginning + 80
|
|
maximum = beginning + 100
|
|
await setAutomine(false)
|
|
await setNextBlockTimestamp(beginning)
|
|
await vault.lock(fund, expiry, maximum)
|
|
})
|
|
|
|
describe("locking", function () {
|
|
beforeEach(async function () {
|
|
await setAutomine(true)
|
|
})
|
|
|
|
it("cannot set lock when already locked", async function () {
|
|
await expect(vault.lock(fund, expiry, maximum)).to.be.revertedWith(
|
|
"AlreadyLocked"
|
|
)
|
|
})
|
|
|
|
it("can extend a lock expiry up to its maximum", async function () {
|
|
await vault.extendLock(fund, expiry + 1)
|
|
expect((await vault.getLock(fund))[0]).to.equal(expiry + 1)
|
|
await vault.extendLock(fund, maximum)
|
|
expect((await vault.getLock(fund))[0]).to.equal(maximum)
|
|
})
|
|
|
|
it("cannot extend a lock past its maximum", async function () {
|
|
const extending = vault.extendLock(fund, maximum + 1)
|
|
await expect(extending).to.be.revertedWith("ExpiryPastMaximum")
|
|
})
|
|
|
|
it("cannot move expiry forward", async function () {
|
|
const extending = vault.extendLock(fund, expiry - 1)
|
|
await expect(extending).to.be.revertedWith("InvalidExpiry")
|
|
})
|
|
})
|
|
|
|
describe("depositing", function () {
|
|
const amount = 1000
|
|
|
|
beforeEach(async function () {
|
|
await setAutomine(true)
|
|
})
|
|
|
|
it("accepts deposits of tokens", async function () {
|
|
await token.connect(account).approve(vault.address, amount)
|
|
await vault.deposit(fund, account.address, amount)
|
|
const balance = await vault.getBalance(fund, account.address)
|
|
expect(balance).to.equal(amount)
|
|
})
|
|
|
|
it("keeps custody of tokens that are deposited", async function () {
|
|
await token.connect(account).approve(vault.address, amount)
|
|
await vault.deposit(fund, account.address, amount)
|
|
expect(await token.balanceOf(vault.address)).to.equal(amount)
|
|
})
|
|
|
|
it("deposit fails when tokens cannot be transferred", async function () {
|
|
await token.connect(account).approve(vault.address, amount - 1)
|
|
const depositing = vault.deposit(fund, account.address, amount)
|
|
await expect(depositing).to.be.revertedWith("insufficient allowance")
|
|
})
|
|
|
|
it("adds multiple deposits to the balance", async function () {
|
|
await token.connect(account).approve(vault.address, amount)
|
|
await vault.deposit(fund, account.address, amount / 2)
|
|
await vault.deposit(fund, account.address, amount / 2)
|
|
const balance = await vault.getBalance(fund, account.address)
|
|
expect(balance).to.equal(amount)
|
|
})
|
|
|
|
it("separates deposits from different funds", async function () {
|
|
const fund1 = randomBytes(32)
|
|
const fund2 = randomBytes(32)
|
|
await vault.lock(fund1, expiry, maximum)
|
|
await vault.lock(fund2, expiry, maximum)
|
|
await token.connect(account).approve(vault.address, 3)
|
|
await vault.deposit(fund1, account.address, 1)
|
|
await vault.deposit(fund2, account.address, 2)
|
|
expect(await vault.getBalance(fund1, account.address)).to.equal(1)
|
|
expect(await vault.getBalance(fund2, account.address)).to.equal(2)
|
|
})
|
|
|
|
it("separates deposits from different controllers", async function () {
|
|
const [, , controller1, controller2] = await ethers.getSigners()
|
|
const vault1 = vault.connect(controller1)
|
|
const vault2 = vault.connect(controller2)
|
|
await vault1.lock(fund, expiry, maximum)
|
|
await vault2.lock(fund, expiry, maximum)
|
|
await token.connect(account).approve(vault.address, 3)
|
|
await vault1.deposit(fund, account.address, 1)
|
|
await vault2.deposit(fund, account.address, 2)
|
|
expect(await vault1.getBalance(fund, account.address)).to.equal(1)
|
|
expect(await vault2.getBalance(fund, account.address)).to.equal(2)
|
|
})
|
|
})
|
|
|
|
describe("designating", function () {
|
|
const amount = 1000
|
|
|
|
beforeEach(async function () {
|
|
await token.connect(account).approve(vault.address, amount)
|
|
await vault.deposit(fund, account.address, amount)
|
|
})
|
|
|
|
it("can designate tokens for a single recipient", async function () {
|
|
await setAutomine(true)
|
|
await vault.designate(fund, account.address, amount)
|
|
expect(
|
|
await vault.getDesignatedBalance(fund, account.address)
|
|
).to.equal(amount)
|
|
})
|
|
|
|
it("can designate part of the balance", async function () {
|
|
await setAutomine(true)
|
|
await vault.designate(fund, account.address, 10)
|
|
expect(
|
|
await vault.getDesignatedBalance(fund, account.address)
|
|
).to.equal(10)
|
|
})
|
|
|
|
it("adds up designated tokens", async function () {
|
|
await setAutomine(true)
|
|
await vault.designate(fund, account.address, 10)
|
|
await vault.designate(fund, account.address, 10)
|
|
expect(
|
|
await vault.getDesignatedBalance(fund, account.address)
|
|
).to.equal(20)
|
|
})
|
|
|
|
it("does not change the balance", async function () {
|
|
await setAutomine(true)
|
|
await vault.designate(fund, account.address, 10)
|
|
expect(await vault.getBalance(fund, account.address)).to.equal(amount)
|
|
})
|
|
|
|
it("cannot designate more than the undesignated balance", async function () {
|
|
await setAutomine(true)
|
|
await vault.designate(fund, account.address, amount)
|
|
await expect(
|
|
vault.designate(fund, account.address, 1)
|
|
).to.be.revertedWith("InsufficientBalance")
|
|
})
|
|
|
|
it("cannot designate tokens that are flowing", async function () {
|
|
await vault.flow(fund, account.address, account2.address, 5)
|
|
setAutomine(true)
|
|
await vault.designate(fund, account.address, 500)
|
|
const designating = vault.designate(fund, account.address, 1)
|
|
await expect(designating).to.be.revertedWith("InsufficientBalance")
|
|
})
|
|
})
|
|
|
|
describe("transfering", function () {
|
|
const amount = 1000
|
|
|
|
let address1
|
|
let address2
|
|
let address3
|
|
|
|
beforeEach(async function () {
|
|
await token.connect(account).approve(vault.address, amount)
|
|
await vault.deposit(fund, account.address, amount)
|
|
address1 = account.address
|
|
address2 = account2.address
|
|
address3 = account3.address
|
|
})
|
|
|
|
it("can transfer tokens from one recipient to the other", async function () {
|
|
await setAutomine(true)
|
|
await vault.transfer(fund, address1, address2, amount)
|
|
expect(await vault.getBalance(fund, address1)).to.equal(0)
|
|
expect(await vault.getBalance(fund, address2)).to.equal(amount)
|
|
})
|
|
|
|
it("can transfer part of a balance", async function () {
|
|
await setAutomine(true)
|
|
await vault.transfer(fund, address1, address2, 10)
|
|
expect(await vault.getBalance(fund, address1)).to.equal(amount - 10)
|
|
expect(await vault.getBalance(fund, address2)).to.equal(10)
|
|
})
|
|
|
|
it("can transfer out funds that were transfered in", async function () {
|
|
await setAutomine(true)
|
|
await vault.transfer(fund, address1, address2, amount)
|
|
await vault.transfer(fund, address2, address3, amount)
|
|
expect(await vault.getBalance(fund, address2)).to.equal(0)
|
|
expect(await vault.getBalance(fund, address3)).to.equal(amount)
|
|
})
|
|
|
|
it("does not transfer more than the balance", async function () {
|
|
await setAutomine(true)
|
|
await expect(
|
|
vault.transfer(fund, address1, address2, amount + 1)
|
|
).to.be.revertedWith("InsufficientBalance")
|
|
})
|
|
|
|
it("does not transfer designated tokens", async function () {
|
|
await setAutomine(true)
|
|
await vault.designate(fund, account.address, 1)
|
|
await expect(
|
|
vault.transfer(fund, account.address, account2.address, amount)
|
|
).to.be.revertedWith("InsufficientBalance")
|
|
})
|
|
|
|
it("does not transfer tokens that are flowing", async function () {
|
|
await vault.flow(fund, address1, address2, 5)
|
|
setAutomine(true)
|
|
await vault.transfer(fund, address1, address2, 500)
|
|
await expect(
|
|
vault.transfer(fund, address1, address2, 1)
|
|
).to.be.revertedWith("InsufficientBalance")
|
|
})
|
|
})
|
|
|
|
describe("flowing", function () {
|
|
const deposit = 1000
|
|
|
|
let address1
|
|
let address2
|
|
let address3
|
|
|
|
beforeEach(async function () {
|
|
await token.connect(account).approve(vault.address, deposit)
|
|
await vault.deposit(fund, account.address, deposit)
|
|
address1 = account.address
|
|
address2 = account2.address
|
|
address3 = account3.address
|
|
})
|
|
|
|
async function getBalance(recipient) {
|
|
return await vault.getBalance(fund, recipient)
|
|
}
|
|
|
|
it("moves tokens over time", async function () {
|
|
await vault.flow(fund, address1, address2, 2)
|
|
mine()
|
|
const start = await currentTime()
|
|
await advanceTimeTo(start + 2)
|
|
expect(await getBalance(address1)).to.equal(deposit - 4)
|
|
expect(await getBalance(address2)).to.equal(4)
|
|
await advanceTimeTo(start + 4)
|
|
expect(await getBalance(address1)).to.equal(deposit - 8)
|
|
expect(await getBalance(address2)).to.equal(8)
|
|
})
|
|
|
|
it("can move tokens to several different recipients", async function () {
|
|
await vault.flow(fund, address1, address2, 1)
|
|
await vault.flow(fund, address1, address3, 2)
|
|
await mine()
|
|
const start = await currentTime()
|
|
await advanceTimeTo(start + 2)
|
|
expect(await getBalance(address1)).to.equal(deposit - 6)
|
|
expect(await getBalance(address2)).to.equal(2)
|
|
expect(await getBalance(address3)).to.equal(4)
|
|
await advanceTimeTo(start + 4)
|
|
expect(await getBalance(address1)).to.equal(deposit - 12)
|
|
expect(await getBalance(address2)).to.equal(4)
|
|
expect(await getBalance(address3)).to.equal(8)
|
|
})
|
|
|
|
it("allows flows to be diverted to other recipient", async function () {
|
|
await vault.flow(fund, address1, address2, 3)
|
|
await vault.flow(fund, address2, address3, 1)
|
|
await mine()
|
|
const start = await currentTime()
|
|
await advanceTimeTo(start + 2)
|
|
expect(await getBalance(address1)).to.equal(deposit - 6)
|
|
expect(await getBalance(address2)).to.equal(4)
|
|
expect(await getBalance(address3)).to.equal(2)
|
|
await advanceTimeTo(start + 4)
|
|
expect(await getBalance(address1)).to.equal(deposit - 12)
|
|
expect(await getBalance(address2)).to.equal(8)
|
|
expect(await getBalance(address3)).to.equal(4)
|
|
})
|
|
|
|
it("allows flow to be reversed back to the sender", async function () {
|
|
await vault.flow(fund, address1, address2, 3)
|
|
await vault.flow(fund, address2, address1, 3)
|
|
await mine()
|
|
const start = await currentTime()
|
|
await advanceTimeTo(start + 2)
|
|
expect(await getBalance(address1)).to.equal(deposit)
|
|
expect(await getBalance(address2)).to.equal(0)
|
|
await advanceTimeTo(start + 4)
|
|
expect(await getBalance(address1)).to.equal(deposit)
|
|
expect(await getBalance(address2)).to.equal(0)
|
|
})
|
|
|
|
it("can change flows over time", async function () {
|
|
await vault.flow(fund, address1, address2, 1)
|
|
await vault.flow(fund, address1, address3, 2)
|
|
await mine()
|
|
const start = await currentTime()
|
|
setNextBlockTimestamp(start + 4)
|
|
await vault.flow(fund, address3, address2, 1)
|
|
await mine()
|
|
expect(await getBalance(address1)).to.equal(deposit - 12)
|
|
expect(await getBalance(address2)).to.equal(4)
|
|
expect(await getBalance(address3)).to.equal(8)
|
|
await advanceTimeTo(start + 8)
|
|
expect(await getBalance(address1)).to.equal(deposit - 24)
|
|
expect(await getBalance(address2)).to.equal(12)
|
|
expect(await getBalance(address3)).to.equal(12)
|
|
await advanceTimeTo(start + 12)
|
|
expect(await getBalance(address1)).to.equal(deposit - 36)
|
|
expect(await getBalance(address2)).to.equal(20)
|
|
expect(await getBalance(address3)).to.equal(16)
|
|
})
|
|
|
|
it("designates tokens that flow for the recipient", async function () {
|
|
await vault.flow(fund, address1, address2, 3)
|
|
await mine()
|
|
const start = await currentTime()
|
|
await advanceTimeTo(start + 7)
|
|
expect(await vault.getDesignatedBalance(fund, address2)).to.equal(21)
|
|
})
|
|
|
|
it("flows longer when lock is extended", async function () {
|
|
await vault.flow(fund, address1, address2, 2)
|
|
await mine()
|
|
const start = await currentTime()
|
|
await vault.extendLock(fund, maximum)
|
|
await mine()
|
|
await advanceTimeTo(maximum)
|
|
const total = (maximum - start) * 2
|
|
expect(await getBalance(address1)).to.equal(deposit - total)
|
|
expect(await getBalance(address2)).to.equal(total)
|
|
await advanceTimeTo(maximum + 10)
|
|
expect(await getBalance(address1)).to.equal(deposit - total)
|
|
expect(await getBalance(address2)).to.equal(total)
|
|
})
|
|
|
|
it("rejects negative flows", async function () {
|
|
setAutomine(true)
|
|
await expect(
|
|
vault.flow(fund, address1, address2, -1)
|
|
).to.be.revertedWith("NegativeFlow")
|
|
})
|
|
|
|
it("rejects flow when insufficient available tokens", async function () {
|
|
setAutomine(true)
|
|
await expect(
|
|
vault.flow(fund, address1, address2, 11)
|
|
).to.be.revertedWith("InsufficientBalance")
|
|
})
|
|
|
|
it("rejects total flows exceeding available tokens", async function () {
|
|
await vault.flow(fund, address1, address2, 10)
|
|
setAutomine(true)
|
|
await expect(
|
|
vault.flow(fund, address1, address2, 1)
|
|
).to.be.revertedWith("InsufficientBalance")
|
|
})
|
|
|
|
it("cannot flow designated tokens", async function () {
|
|
await vault.designate(fund, address1, 500)
|
|
await vault.flow(fund, address1, address2, 5)
|
|
setAutomine(true)
|
|
await expect(
|
|
vault.flow(fund, address1, address2, 1)
|
|
).to.be.revertedWith("InsufficientBalance")
|
|
})
|
|
})
|
|
|
|
describe("burning", function () {
|
|
const amount = 1000
|
|
|
|
beforeEach(async function () {
|
|
await setAutomine(true)
|
|
await token.connect(account).approve(vault.address, amount)
|
|
await vault.deposit(fund, account.address, amount)
|
|
})
|
|
|
|
it("can burn a deposit", async function () {
|
|
await vault.burn(fund, account.address)
|
|
expect(await vault.getBalance(fund, account.address)).to.equal(0)
|
|
})
|
|
|
|
it("moves the tokens to address 0xdead", async function () {
|
|
const dead = "0x000000000000000000000000000000000000dead"
|
|
const before = await token.balanceOf(dead)
|
|
await vault.burn(fund, account.address)
|
|
const after = await token.balanceOf(dead)
|
|
expect(after - before).to.equal(amount)
|
|
})
|
|
|
|
it("allows designated tokens to be burned", async function () {
|
|
await vault.designate(fund, account.address, 10)
|
|
await vault.burn(fund, account.address)
|
|
expect(await vault.getBalance(fund, account.address)).to.equal(0)
|
|
})
|
|
|
|
it("moves burned designated tokens to address 0xdead", async function () {
|
|
const dead = "0x000000000000000000000000000000000000dead"
|
|
await vault.designate(fund, account.address, 10)
|
|
const before = await token.balanceOf(dead)
|
|
await vault.burn(fund, account.address)
|
|
const after = await token.balanceOf(dead)
|
|
expect(after - before).to.equal(amount)
|
|
})
|
|
|
|
it("cannot burn tokens that are flowing", async function () {
|
|
await vault.flow(fund, account.address, account2.address, 5)
|
|
const burning1 = vault.burn(fund, account.address)
|
|
await expect(burning1).to.be.revertedWith("CannotBurnFlowingTokens")
|
|
const burning2 = vault.burn(fund, account2.address)
|
|
await expect(burning2).to.be.revertedWith("CannotBurnFlowingTokens")
|
|
})
|
|
|
|
it("can burn tokens that are no longer flowing", async function () {
|
|
await vault.flow(fund, account.address, account2.address, 5)
|
|
await vault.flow(fund, account2.address, account.address, 5)
|
|
await expect(vault.burn(fund, account.address)).not.to.be.reverted
|
|
})
|
|
})
|
|
|
|
describe("withdrawing", function () {
|
|
const amount = 1000
|
|
|
|
beforeEach(async function () {
|
|
await setAutomine(true)
|
|
await token.connect(account).approve(vault.address, amount)
|
|
await vault.deposit(fund, account.address, amount)
|
|
})
|
|
|
|
it("does not allow withdrawal before lock expires", async function () {
|
|
await setNextBlockTimestamp(expiry - 1)
|
|
const withdrawing = vault.withdraw(fund, account.address)
|
|
await expect(withdrawing).to.be.revertedWith("Locked")
|
|
})
|
|
|
|
it("disallows withdrawal for everyone in the fund", async function () {
|
|
const address1 = account.address
|
|
const address2 = account2.address
|
|
await vault.transfer(fund, address1, address2, amount / 2)
|
|
let withdrawing1 = vault.withdraw(fund, address1)
|
|
let withdrawing2 = vault.withdraw(fund, address2)
|
|
await expect(withdrawing1).to.be.revertedWith("Locked")
|
|
await expect(withdrawing2).to.be.revertedWith("Locked")
|
|
})
|
|
})
|
|
})
|
|
|
|
describe("when a fund lock is expiring", function () {
|
|
let expiry
|
|
let maximum
|
|
|
|
beforeEach(async function () {
|
|
const beginning = (await currentTime()) + 10
|
|
expiry = beginning + 80
|
|
maximum = beginning + 100
|
|
await setAutomine(false)
|
|
await setNextBlockTimestamp(beginning)
|
|
await vault.lock(fund, expiry, maximum)
|
|
})
|
|
|
|
async function expire() {
|
|
await setNextBlockTimestamp(expiry)
|
|
}
|
|
|
|
describe("locking", function () {
|
|
beforeEach(async function () {
|
|
await setAutomine(true)
|
|
})
|
|
|
|
it("cannot set lock when lock expired", async function () {
|
|
await expire()
|
|
const locking = vault.lock(fund, expiry, maximum)
|
|
await expect(locking).to.be.revertedWith("AlreadyLocked")
|
|
})
|
|
|
|
it("cannot extend an expired lock", async function () {
|
|
await expire()
|
|
const extending = vault.extendLock(fund, maximum)
|
|
await expect(extending).to.be.revertedWith("LockRequired")
|
|
})
|
|
|
|
it("deletes lock when no tokens remain", async function () {
|
|
await token.connect(account).approve(vault.address, 30)
|
|
await vault.deposit(fund, account.address, 30)
|
|
await vault.transfer(fund, account.address, account2.address, 20)
|
|
await vault.transfer(fund, account2.address, account3.address, 10)
|
|
// some tokens are burned
|
|
await vault.burn(fund, account2.address)
|
|
await expire()
|
|
// some tokens are withdrawn
|
|
await vault.withdraw(fund, account.address)
|
|
expect((await vault.getLock(fund))[0]).not.to.equal(0)
|
|
expect((await vault.getLock(fund))[1]).not.to.equal(0)
|
|
// remainder of the tokens are withdrawn by recipient
|
|
await vault
|
|
.connect(account3)
|
|
.withdrawByRecipient(controller.address, fund)
|
|
expect((await vault.getLock(fund))[0]).to.equal(0)
|
|
expect((await vault.getLock(fund))[1]).to.equal(0)
|
|
})
|
|
})
|
|
|
|
describe("flowing", function () {
|
|
const deposit = 1000
|
|
|
|
beforeEach(async function () {
|
|
await token.connect(account).approve(vault.address, deposit)
|
|
await vault.deposit(fund, account.address, deposit)
|
|
})
|
|
|
|
it("stops flows when lock expires", async function () {
|
|
await vault.flow(fund, account.address, account2.address, 2)
|
|
await mine()
|
|
const start = await currentTime()
|
|
const total = (expiry - start) * 2
|
|
let balance1, balance2
|
|
await advanceTimeTo(expiry)
|
|
balance1 = await vault.getBalance(fund, account.address)
|
|
balance2 = await vault.getBalance(fund, account2.address)
|
|
expect(balance1).to.equal(deposit - total)
|
|
expect(balance2).to.equal(total)
|
|
await advanceTimeTo(expiry + 10)
|
|
balance1 = await vault.getBalance(fund, account.address)
|
|
balance2 = await vault.getBalance(fund, account2.address)
|
|
expect(balance1).to.equal(deposit - total)
|
|
expect(balance2).to.equal(total)
|
|
})
|
|
|
|
it("does not allow new flows to start", async function () {
|
|
await setAutomine(true)
|
|
await expire()
|
|
await expect(
|
|
vault.flow(fund, account.address, account2.address, 0)
|
|
).to.be.revertedWith("LockRequired")
|
|
})
|
|
})
|
|
|
|
describe("withdrawing", function () {
|
|
const amount = 1000
|
|
|
|
beforeEach(async function () {
|
|
setAutomine(true)
|
|
await token.connect(account).approve(vault.address, amount)
|
|
await vault.deposit(fund, account.address, amount)
|
|
})
|
|
|
|
it("allows controller to withdraw for a recipient", async function () {
|
|
await expire()
|
|
const before = await token.balanceOf(account.address)
|
|
await vault.withdraw(fund, account.address)
|
|
const after = await token.balanceOf(account.address)
|
|
expect(after - before).to.equal(amount)
|
|
})
|
|
|
|
it("allows recipient to withdraw for itself", async function () {
|
|
await expire()
|
|
const before = await token.balanceOf(account.address)
|
|
await vault
|
|
.connect(account)
|
|
.withdrawByRecipient(controller.address, fund)
|
|
const after = await token.balanceOf(account.address)
|
|
expect(after - before).to.equal(amount)
|
|
})
|
|
|
|
it("empties the balance when withdrawing", async function () {
|
|
await expire()
|
|
await vault.withdraw(fund, account.address)
|
|
expect(await vault.getBalance(fund, account.address)).to.equal(0)
|
|
})
|
|
|
|
it("allows designated tokens to be withdrawn", async function () {
|
|
await vault.designate(fund, account.address, 10)
|
|
await expire()
|
|
const before = await token.balanceOf(account.address)
|
|
await vault.withdraw(fund, account.address)
|
|
const after = await token.balanceOf(account.address)
|
|
expect(after - before).to.equal(amount)
|
|
})
|
|
|
|
it("does not withdraw designated tokens more than once", async function () {
|
|
await vault.designate(fund, account.address, 10)
|
|
await expire()
|
|
await vault.withdraw(fund, account.address)
|
|
const before = await token.balanceOf(account.address)
|
|
await vault.withdraw(fund, account.address)
|
|
const after = await token.balanceOf(account.address)
|
|
expect(after).to.equal(before)
|
|
})
|
|
|
|
it("can withdraw funds that were transfered in", async function () {
|
|
await vault.transfer(fund, account.address, account2.address, amount)
|
|
await expire()
|
|
const before = await token.balanceOf(account2.address)
|
|
await vault.withdraw(fund, account2.address)
|
|
const after = await token.balanceOf(account2.address)
|
|
expect(after - before).to.equal(amount)
|
|
})
|
|
|
|
it("cannot withdraw funds that were transfered out", async function () {
|
|
await vault.transfer(fund, account.address, account2.address, amount)
|
|
await expire()
|
|
const before = await token.balanceOf(account.address)
|
|
await vault.withdraw(fund, account.address)
|
|
const after = await token.balanceOf(account.address)
|
|
expect(after).to.equal(before)
|
|
})
|
|
|
|
it("cannot withdraw more than once", async function () {
|
|
await expire()
|
|
await vault.withdraw(fund, account.address)
|
|
const before = await token.balanceOf(account.address)
|
|
await vault.withdraw(fund, account.address)
|
|
const after = await token.balanceOf(account.address)
|
|
expect(after).to.equal(before)
|
|
})
|
|
|
|
it("cannot withdraw burned tokens", async function () {
|
|
await vault.burn(fund, account.address)
|
|
await expire()
|
|
const before = await token.balanceOf(account.address)
|
|
await vault.withdraw(fund, account.address)
|
|
const after = await token.balanceOf(account.address)
|
|
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(fund, account.address, amount)
|
|
).to.be.revertedWith("LockRequired")
|
|
})
|
|
|
|
it("does not allow designating tokens", async function () {
|
|
setAutomine(true)
|
|
await expire()
|
|
await expect(
|
|
vault.designate(fund, account.address, 0)
|
|
).to.be.revertedWith("LockRequired")
|
|
})
|
|
|
|
it("does not allow transfer of tokens", async function () {
|
|
setAutomine(true)
|
|
await expire()
|
|
await expect(
|
|
vault.transfer(fund, 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(fund, account.address)).to.be.revertedWith(
|
|
"LockRequired"
|
|
)
|
|
})
|
|
})
|
|
})
|