Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolve time conflict in redeemVoucher and expireVoucher #695

Merged
merged 7 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contracts/protocol/facets/ExchangeHandlerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ contract ExchangeHandlerFacet is IBosonExchangeHandler, BuyerBase, DisputeBase {
(Exchange storage exchange, Voucher storage voucher) = getValidExchange(_exchangeId, ExchangeState.Committed);

// Make sure that the voucher has expired
require(block.timestamp >= voucher.validUntilDate, VOUCHER_STILL_VALID);
require(block.timestamp > voucher.validUntilDate, VOUCHER_STILL_VALID);

// Finalize the exchange, burning the voucher
finalizeExchange(exchange, ExchangeState.Canceled);
Expand Down
2 changes: 1 addition & 1 deletion test/integration/02-Upgraded-facet.js
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation
const escalatedDate = block.timestamp.toString();

// Set time forward past the dispute escalation period
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod) + 1);

// Expire the escalated dispute, testing for the event
await expect(disputeHandler.connect(rando).expireEscalatedDispute(exchangeId))
Expand Down
18 changes: 9 additions & 9 deletions test/protocol/DisputeHandlerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ describe("IBosonDisputeHandler", function () {
block = await provider.getBlock(blockNumber);
escalatedDate = block.timestamp.toString();

await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod) + 1);

// Attempt to retract the dispute, expecting revert
await expect(disputeHandler.connect(buyer).retractDispute(exchangeId)).to.revertedWith(
Expand Down Expand Up @@ -1082,7 +1082,7 @@ describe("IBosonDisputeHandler", function () {

it("Dispute has expired", async function () {
// Set time forward to the dispute expiration date
await setNextBlockTimestamp(Number(timeout));
await setNextBlockTimestamp(Number(timeout) + 1);

// Attempt to resolve the dispute, expecting revert
await expect(
Expand Down Expand Up @@ -1650,7 +1650,7 @@ describe("IBosonDisputeHandler", function () {

it("Dispute escalation response period has elapsed", async function () {
// Set time past escalation period
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod) + 1);

// Attempt to decide the dispute, expecting revert
await expect(
Expand Down Expand Up @@ -1682,7 +1682,7 @@ describe("IBosonDisputeHandler", function () {

it("should emit a EscalatedDisputeExpired event", async function () {
// Set time forward past the dispute escalation period
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod) + 1);

// Expire the escalated dispute, testing for the event
await expect(disputeHandler.connect(rando).expireEscalatedDispute(exchangeId))
Expand All @@ -1692,7 +1692,7 @@ describe("IBosonDisputeHandler", function () {

it("should update state", async function () {
// Set time forward past the dispute escalation period
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod) + 1);

// Expire the dispute
tx = await disputeHandler.connect(rando).expireEscalatedDispute(exchangeId);
Expand Down Expand Up @@ -1740,7 +1740,7 @@ describe("IBosonDisputeHandler", function () {
context("💔 Revert Reasons", async function () {
it("The disputes region of protocol is paused", async function () {
// Set time forward past the dispute escalation period
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod) + 1);

// Pause the disputes region of the protocol
await pauseHandler.connect(pauser).pause([PausableRegion.Disputes]);
Expand Down Expand Up @@ -1942,7 +1942,7 @@ describe("IBosonDisputeHandler", function () {

it("Dispute escalation response period has elapsed", async function () {
// Set time forward past the dispute escalation period
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod) + 1);

// Attempt to refuse the escalated dispute, expecting revert
await expect(disputeHandler.connect(assistantDR).refuseEscalatedDispute(exchangeId)).to.revertedWith(
Expand Down Expand Up @@ -2094,7 +2094,7 @@ describe("IBosonDisputeHandler", function () {

it("should return the expected dispute state if exchange id is valid and dispute has expired", async function () {
// Set time forward to the dispute's timeout
await setNextBlockTimestamp(Number(timeout));
await setNextBlockTimestamp(Number(timeout) + 1);

// Anyone calls expireDispute
await disputeHandler.connect(rando).expireDispute(exchangeId);
Expand Down Expand Up @@ -2347,7 +2347,7 @@ describe("IBosonDisputeHandler", function () {
block = await provider.getBlock(blockNumber);
escalatedDate = block.timestamp.toString();

await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(escalationPeriod) + 1);

// Expire dispute
await disputeHandler.connect(rando).expireEscalatedDispute(exchangeId);
Expand Down
23 changes: 21 additions & 2 deletions test/protocol/ExchangeHandlerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2038,6 +2038,14 @@ describe("IBosonExchangeHandler", function () {
await expect(exchangeHandler.connect(rando).expireVoucher(exchange.id)).to.revertedWith(
RevertReasons.VOUCHER_STILL_VALID
);

// Set time forward past the last valid timestamp
await setNextBlockTimestamp(Number(voucherRedeemableFrom) + Number(voucherValid));

// Attempt to cancel the voucher, expecting revert
await expect(exchangeHandler.connect(rando).expireVoucher(exchange.id)).to.revertedWith(
RevertReasons.VOUCHER_STILL_VALID
);
});
});
});
Expand Down Expand Up @@ -2072,6 +2080,17 @@ describe("IBosonExchangeHandler", function () {
assert.equal(response, ExchangeState.Redeemed, "Exchange state is incorrect");
});

it("It's possible to redeem at the the end of voucher validity period", async function () {
// Set time forward to the offer's validUntilDate
await setNextBlockTimestamp(Number(voucherRedeemableFrom) + Number(voucherValid));

// Redeem the voucher, expecting event
await expect(exchangeHandler.connect(buyer).redeemVoucher(exchange.id)).to.emit(
exchangeHandler,
"VoucherRedeemed"
);
});

context("💔 Revert Reasons", async function () {
it("The exchanges region of protocol is paused", async function () {
// Pause the exchanges region of the protocol
Expand Down Expand Up @@ -2119,7 +2138,7 @@ describe("IBosonExchangeHandler", function () {

it("current time is after to voucher's validUntilDate", async function () {
// Set time forward past the voucher's validUntilDate
await setNextBlockTimestamp(Number(voucherRedeemableFrom) + Number(voucherValid) + Number(oneWeek));
await setNextBlockTimestamp(Number(voucherRedeemableFrom) + Number(voucherValid) + 1);

// Attempt to redeem the voucher, expecting revert
await expect(exchangeHandler.connect(buyer).redeemVoucher(exchange.id)).to.revertedWith(
Expand Down Expand Up @@ -4052,7 +4071,7 @@ describe("IBosonExchangeHandler", function () {
block = await provider.getBlock(blockNumber);
const escalatedDate = block.timestamp.toString();

await setNextBlockTimestamp(Number(escalatedDate) + Number(disputeResolver.escalationResponsePeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(disputeResolver.escalationResponsePeriod) + 1);

// Expire dispute
await disputeHandler.connect(rando).expireEscalatedDispute(exchange.id);
Expand Down
10 changes: 6 additions & 4 deletions test/protocol/FundsHandlerTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2875,7 +2875,7 @@ describe("IBosonFundsHandler", function () {
// protocol: protocolFee
protocolPayoff = offerTokenProtocolFee;

await setNextBlockTimestamp(Number(timeout));
await setNextBlockTimestamp(Number(timeout) + 1);
});

it("should emit a FundsReleased event", async function () {
Expand Down Expand Up @@ -2993,7 +2993,7 @@ describe("IBosonFundsHandler", function () {
disputedDate = block.timestamp.toString();
timeout = BigInt(disputedDate) + resolutionPeriod.toString();

await setNextBlockTimestamp(Number(timeout));
await setNextBlockTimestamp(Number(timeout) + 1);
});

it("should emit a FundsReleased event", async function () {
Expand Down Expand Up @@ -3899,7 +3899,7 @@ describe("IBosonFundsHandler", function () {
block = await provider.getBlock(blockNumber);
escalatedDate = block.timestamp.toString();

await setNextBlockTimestamp(Number(escalatedDate) + Number(disputeResolver.escalationResponsePeriod));
await setNextBlockTimestamp(Number(escalatedDate) + Number(disputeResolver.escalationResponsePeriod) + 1);
});

it("should emit a FundsReleased event", async function () {
Expand Down Expand Up @@ -4001,7 +4001,9 @@ describe("IBosonFundsHandler", function () {
block = await provider.getBlock(blockNumber);
escalatedDate = block.timestamp.toString();

await setNextBlockTimestamp(Number(escalatedDate) + Number(disputeResolver.escalationResponsePeriod));
await setNextBlockTimestamp(
Number(escalatedDate) + Number(disputeResolver.escalationResponsePeriod) + 1
);
});

it("should update state", async function () {
Expand Down
2 changes: 1 addition & 1 deletion test/protocol/clients/BosonVoucherTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ describe("IBosonVoucher", function () {

it("Should be 0 if offer is expired", async function () {
// Skip to after offer expiry
await setNextBlockTimestamp(Number(BigInt(offerDates.validUntil) + 1n));
await setNextBlockTimestamp(Number(offerDates.validUntil), true);

// Get available premints from contract
let availablePremints = await bosonVoucher.getAvailablePreMints(offerId);
Expand Down
6 changes: 4 additions & 2 deletions test/util/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,13 @@ function compareOfferStructs(returnedOffer) {
return true;
}

async function setNextBlockTimestamp(timestamp) {
async function setNextBlockTimestamp(timestamp, mine = false) {
if (typeof timestamp == "string" && timestamp.startsWith("0x0") && timestamp.length > 3)
timestamp = "0x" + timestamp.substring(3);
await provider.send("evm_setNextBlockTimestamp", [timestamp]);
await provider.send("evm_mine", []);

// when testing static call, a block must be mined to get the correct timestamp
if (mine) await provider.send("evm_mine", []);
}

function getSignatureParameters(signature) {
Expand Down