215 lines
6.4 KiB
JavaScript
215 lines
6.4 KiB
JavaScript
const { ethers } = require("hardhat")
|
|
const { expect } = require("chai")
|
|
const { hexlify, randomBytes, toHexString } = ethers.utils
|
|
const {
|
|
advanceTimeTo,
|
|
snapshot,
|
|
revert,
|
|
advanceTime,
|
|
currentTime,
|
|
} = require("./evm")
|
|
const { exampleLock } = require("./examples")
|
|
const { hours } = require("./time")
|
|
|
|
describe("Account Locks", function () {
|
|
let locks
|
|
|
|
beforeEach(async function () {
|
|
let AccountLocks = await ethers.getContractFactory("TestAccountLocks")
|
|
locks = await AccountLocks.deploy()
|
|
})
|
|
|
|
describe("creating a lock", function () {
|
|
it("allows creation of a lock with an expiry time", async function () {
|
|
let { id, expiry } = await exampleLock()
|
|
await locks.createLock(id, expiry)
|
|
})
|
|
|
|
it("fails to create a lock with an existing id", async function () {
|
|
let { id, expiry } = await exampleLock()
|
|
await locks.createLock(id, expiry)
|
|
await expect(locks.createLock(id, expiry + 1)).to.be.revertedWith(
|
|
"Lock already exists"
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("locking an account", function () {
|
|
let lock
|
|
|
|
beforeEach(async function () {
|
|
lock = await exampleLock()
|
|
await locks.createLock(lock.id, lock.expiry)
|
|
})
|
|
|
|
it("locks an account", async function () {
|
|
let [account] = await ethers.getSigners()
|
|
await locks.lock(account.address, lock.id)
|
|
})
|
|
|
|
it("fails to lock account when lock does not exist", async function () {
|
|
let [account] = await ethers.getSigners()
|
|
let nonexistent = (await exampleLock()).id
|
|
await expect(locks.lock(account.address, nonexistent)).to.be.revertedWith(
|
|
"Lock does not exist"
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("unlocking a lock", function () {
|
|
let lock
|
|
|
|
beforeEach(async function () {
|
|
lock = await exampleLock()
|
|
await locks.createLock(lock.id, lock.expiry)
|
|
})
|
|
|
|
it("unlocks a lock", async function () {
|
|
await locks.unlock(lock.id)
|
|
})
|
|
|
|
it("fails to unlock a lock that does not exist", async function () {
|
|
let nonexistent = (await exampleLock()).id
|
|
await expect(locks.unlock(nonexistent)).to.be.revertedWith(
|
|
"Lock does not exist"
|
|
)
|
|
})
|
|
|
|
it("fails to unlock by someone other than the creator", async function () {
|
|
let [_, other] = await ethers.getSigners()
|
|
await expect(locks.connect(other).unlock(lock.id)).to.be.revertedWith(
|
|
"Only lock creator can unlock"
|
|
)
|
|
})
|
|
})
|
|
|
|
describe("unlocking an account", function () {
|
|
it("unlocks an account that has not been locked", async function () {
|
|
await locks.unlockAccount()
|
|
})
|
|
|
|
it("unlocks an account whose locks have been unlocked", async function () {
|
|
let [account] = await ethers.getSigners()
|
|
let lock = await exampleLock()
|
|
await locks.createLock(lock.id, lock.expiry)
|
|
await locks.lock(account.address, lock.id)
|
|
await locks.unlock(lock.id)
|
|
await locks.unlockAccount()
|
|
})
|
|
|
|
it("unlocks an account whose locks have expired", async function () {
|
|
let [account] = await ethers.getSigners()
|
|
let lock = { ...(await exampleLock()), expiry: currentTime() }
|
|
await locks.createLock(lock.id, lock.expiry)
|
|
await locks.lock(account.address, lock.id)
|
|
await locks.unlockAccount()
|
|
})
|
|
|
|
it("unlocks multiple accounts tied to the same lock", async function () {
|
|
let [account0, account1] = await ethers.getSigners()
|
|
let lock = await exampleLock()
|
|
await locks.createLock(lock.id, lock.expiry)
|
|
await locks.lock(account0.address, lock.id)
|
|
await locks.lock(account1.address, lock.id)
|
|
await locks.unlock(lock.id)
|
|
await locks.connect(account0).unlockAccount()
|
|
await locks.connect(account1).unlockAccount()
|
|
})
|
|
|
|
it("fails to unlock when some locks are still locked", async function () {
|
|
let [account] = await ethers.getSigners()
|
|
let [lock1, lock2] = [await exampleLock(), await exampleLock()]
|
|
await locks.createLock(lock1.id, lock1.expiry)
|
|
await locks.createLock(lock2.id, lock2.expiry)
|
|
await locks.lock(account.address, lock1.id)
|
|
await locks.lock(account.address, lock2.id)
|
|
await locks.unlock(lock1.id)
|
|
await expect(locks.unlockAccount()).to.be.revertedWith("Account locked")
|
|
})
|
|
})
|
|
|
|
describe("limits", function () {
|
|
let maxlocks
|
|
let account
|
|
|
|
beforeEach(async function () {
|
|
maxlocks = await locks.MAX_LOCKS_PER_ACCOUNT()
|
|
;[account] = await ethers.getSigners()
|
|
})
|
|
|
|
async function addLock() {
|
|
let { id, expiry } = await exampleLock()
|
|
await locks.createLock(id, expiry)
|
|
await locks.lock(account.address, id)
|
|
return id
|
|
}
|
|
|
|
it("supports a limited amount of locks per account", async function () {
|
|
for (let i = 0; i < maxlocks; i++) {
|
|
await addLock()
|
|
}
|
|
await expect(addLock()).to.be.revertedWith("Max locks reached")
|
|
})
|
|
|
|
it("doesn't count unlocked locks towards the limit", async function () {
|
|
for (let i = 0; i < maxlocks; i++) {
|
|
let id = await addLock()
|
|
await locks.unlock(id)
|
|
}
|
|
await expect(addLock()).not.to.be.reverted
|
|
})
|
|
|
|
it("handles maximum amount of locks within gas limit", async function () {
|
|
let ids = []
|
|
for (let i = 0; i < maxlocks; i++) {
|
|
ids.push(await addLock())
|
|
}
|
|
for (let id of ids) {
|
|
await locks.unlock(id)
|
|
}
|
|
await locks.unlockAccount()
|
|
})
|
|
})
|
|
|
|
describe("extend lock expiry", function () {
|
|
let expiry
|
|
let newExpiry
|
|
let id
|
|
|
|
beforeEach(async function () {
|
|
await snapshot()
|
|
|
|
let lock = await exampleLock()
|
|
id = lock.id
|
|
expiry = lock.expiry
|
|
await locks.createLock(id, expiry)
|
|
newExpiry = (await currentTime()) + hours(1)
|
|
|
|
let [account] = await ethers.getSigners()
|
|
await locks.lock(account.address, id)
|
|
})
|
|
|
|
afterEach(async function () {
|
|
await revert()
|
|
})
|
|
|
|
it("fails when lock id doesn't exist", async function () {
|
|
let other = await exampleLock()
|
|
await expect(
|
|
locks.extendLockExpiryTo(other.id, newExpiry)
|
|
).to.be.revertedWith("Lock does not exist")
|
|
})
|
|
|
|
it("fails when lock is already expired", async function () {
|
|
await advanceTimeTo(expiry)
|
|
await expect(locks.extendLockExpiryTo(id, newExpiry)).to.be.revertedWith(
|
|
"Lock already expired"
|
|
)
|
|
})
|
|
|
|
it("successfully updates lock expiry", async function () {
|
|
await expect(locks.extendLockExpiryTo(id, newExpiry)).not.to.be.reverted
|
|
})
|
|
})
|
|
})
|