From 3a97330e723d22365a2e18d15c66e62c184b1330 Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Tue, 9 Aug 2022 21:19:42 +1000 Subject: [PATCH] [marketplace] extend lock expiry Add ability to extend lock expiry once all slots are filled. Tests to support lock expiry. --- contracts/AccountLocks.sol | 12 ++++++++++ contracts/Marketplace.sol | 1 + contracts/TestAccountLocks.sol | 4 ++++ test/AccountLocks.test.js | 43 +++++++++++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/contracts/AccountLocks.sol b/contracts/AccountLocks.sol index fa3af1f..65fecab 100644 --- a/contracts/AccountLocks.sol +++ b/contracts/AccountLocks.sol @@ -42,6 +42,18 @@ contract AccountLocks { lock.unlocked = true; } + /// Extends the locks expiry time. Lock must not have already expired. + /// NOTE: We do not need to check that msg.sender is the lock.owner because + /// this function is internal, and is only called after all checks have been + /// performed in Marketplace.fillSlot. + function _extendLockExpiry(bytes32 lockId, uint256 duration) internal { + Lock storage lock = locks[lockId]; + require(lock.owner != address(0), "Lock does not exist"); + // require(lock.owner == msg.sender, "Only lock creator can extend expiry"); + require(lock.expiry >= block.timestamp, "Lock already expired"); + lock.expiry += duration; + } + /// Unlocks an account. This will fail if there are any active locks attached /// to this account. /// Calling this function triggers a cleanup of inactive locks, making this diff --git a/contracts/Marketplace.sol b/contracts/Marketplace.sol index ec5a324..c4697a1 100644 --- a/contracts/Marketplace.sol +++ b/contracts/Marketplace.sol @@ -76,6 +76,7 @@ contract Marketplace is Collateral, Proofs { emit SlotFilled(requestId, slotIndex, slotId); if (context.slotsFilled == request.ask.slots) { context.state = RequestState.Started; + _extendLockExpiry(requestId, block.timestamp + request.ask.duration); emit RequestFulfilled(requestId); } } diff --git a/contracts/TestAccountLocks.sol b/contracts/TestAccountLocks.sol index cf54020..48f2aa8 100644 --- a/contracts/TestAccountLocks.sol +++ b/contracts/TestAccountLocks.sol @@ -20,4 +20,8 @@ contract TestAccountLocks is AccountLocks { function unlockAccount() public { _unlockAccount(); } + + function extendLockExpiry(bytes32 lockId, uint256 expiry) public { + _extendLockExpiry(lockId, expiry); + } } diff --git a/test/AccountLocks.test.js b/test/AccountLocks.test.js index 2cff736..35d6a9a 100644 --- a/test/AccountLocks.test.js +++ b/test/AccountLocks.test.js @@ -1,7 +1,10 @@ const { ethers } = require("hardhat") const { expect } = require("chai") +const { hexlify, randomBytes, toHexString } = ethers.utils +const { advanceTimeTo, snapshot, revert } = require("./evm") const { exampleLock } = require("./examples") -const { now } = require("./time") +const { now, hours } = require("./time") +const { waitUntilExpired } = require("./marketplace") describe("Account Locks", function () { let locks @@ -162,4 +165,42 @@ describe("Account Locks", function () { await locks.unlockAccount() }) }) + + describe("extend lock expiry", function () { + let expiry + let id + + beforeEach(async function () { + await snapshot() + + let lock = exampleLock() + id = lock.id + expiry = lock.expiry + await locks.createLock(id, expiry) + 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 = exampleLock() + await expect( + locks.extendLockExpiry(other.id, hours(1)) + ).to.be.revertedWith("Lock does not exist") + }) + + it("fails when lock is already expired", async function () { + waitUntilExpired(expiry + hours(1)) + await expect(locks.extendLockExpiry(id, hours(1))).to.be.revertedWith( + "Lock already expired" + ) + }) + + it("successfully updates lock expiry", async function () { + await expect(locks.extendLockExpiry(id, hours(1))).not.to.be.reverted + }) + }) })