@vechain/vebetterdao-contracts
Version:
Open-source repository that houses the smart contracts powering the decentralized VeBetterDAO on the VeChain Thor blockchain.
127 lines (126 loc) • 8.01 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const hardhat_1 = require("hardhat");
const helpers_1 = require("../../scripts/helpers");
const libraries_1 = require("../../scripts/libraries");
const STAKE_AMOUNT = hardhat_1.ethers.parseEther("100");
const MIN_BET_AMOUNT = hardhat_1.ethers.parseEther("100");
const INITIAL_BALANCE = hardhat_1.ethers.parseEther("1000");
const APP_1 = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("app-1"));
const ChallengeKind = { Stake: 0, Sponsored: 1 };
const ChallengeVisibility = { Public: 0, Private: 1 };
const ChallengeType = { MaxActions: 0, SplitWin: 1 };
const ParticipantStatus = { None: 0, Invited: 1, Declined: 2, Joined: 3 };
async function deployV1Fixture() {
const [admin, alice, bob, carol] = await hardhat_1.ethers.getSigners();
const b3tr = (await (await hardhat_1.ethers.getContractFactory("B3TR")).deploy(admin.address, admin.address, admin.address));
await b3tr.waitForDeployment();
const roundGovernor = (await (await hardhat_1.ethers.getContractFactory("MockRoundGovernor")).deploy());
await roundGovernor.waitForDeployment();
const passport = (await (await hardhat_1.ethers.getContractFactory("MockPassportActions")).deploy());
await passport.waitForDeployment();
const x2EarnApps = (await (await hardhat_1.ethers.getContractFactory("MockX2EarnApps")).deploy());
await x2EarnApps.waitForDeployment();
await x2EarnApps.setAppExists(APP_1, true);
// V1 libraries — deployed against the snapshot in deprecated/V1/.
const ChallengeCoreLogicV1Factory = await hardhat_1.ethers.getContractFactory("ChallengeCoreLogicV1");
const challengeCoreLogicV1 = await ChallengeCoreLogicV1Factory.deploy();
await challengeCoreLogicV1.waitForDeployment();
const ChallengeSettlementLogicV1Factory = await hardhat_1.ethers.getContractFactory("ChallengeSettlementLogicV1", {
libraries: { ChallengeCoreLogicV1: await challengeCoreLogicV1.getAddress() },
});
const challengeSettlementLogicV1 = await ChallengeSettlementLogicV1Factory.deploy();
await challengeSettlementLogicV1.waitForDeployment();
const challengesV1 = (await (0, helpers_1.deployProxy)("B3TRChallengesV1", [
{
b3trAddress: await b3tr.getAddress(),
veBetterPassportAddress: await passport.getAddress(),
xAllocationVotingAddress: await roundGovernor.getAddress(),
x2EarnAppsAddress: await x2EarnApps.getAddress(),
maxChallengeDuration: 4,
maxSelectedApps: 5,
maxParticipants: 100,
minBetAmount: MIN_BET_AMOUNT,
},
{
admin: admin.address,
upgrader: admin.address,
contractsAddressManager: admin.address,
settingsManager: admin.address,
},
], {
ChallengeCoreLogicV1: await challengeCoreLogicV1.getAddress(),
ChallengeSettlementLogicV1: await challengeSettlementLogicV1.getAddress(),
}));
for (const signer of [admin, alice, bob, carol]) {
await b3tr.mint(signer.address, INITIAL_BALANCE);
await b3tr.connect(signer).approve(await challengesV1.getAddress(), INITIAL_BALANCE);
}
return { admin, alice, bob, carol, b3tr, roundGovernor, passport, x2EarnApps, challengesV1 };
}
describe("B3TRChallenges - V2 Upgrade - @shard9c", function () {
it("deploys at V1, seeds state, upgrades to V2, and preserves storage layout", async function () {
const { admin, alice, bob, carol, roundGovernor, passport, challengesV1 } = await deployV1Fixture();
await roundGovernor.setCurrentRoundId(1);
// Seed: create a stake challenge, have alice + bob join, leave carol invited-but-not-joined.
await challengesV1.createChallenge({
kind: ChallengeKind.Stake,
visibility: ChallengeVisibility.Private,
challengeType: ChallengeType.MaxActions,
stakeAmount: STAKE_AMOUNT,
startRound: 2,
endRound: 3,
threshold: 0,
numWinners: 0,
appIds: [APP_1],
invitees: [alice.address, bob.address, carol.address],
title: "v1-state",
description: "v1-state-description",
imageURI: "v1-image",
metadataURI: "v1-metadata",
});
await challengesV1.connect(alice).joinChallenge(1);
await challengesV1.connect(bob).joinChallenge(1);
// carol stays invited
(0, chai_1.expect)(await challengesV1.version()).to.equal("1");
const challengeBeforeUpgrade = await challengesV1.getChallenge(1);
const participantsBefore = await challengesV1.getChallengeParticipants(1);
const invitedBefore = await challengesV1.getChallengeInvited(1);
const challengeCountBefore = await challengesV1.challengeCount();
// Deploy fresh V2 libraries and upgrade in place.
const { ChallengeCoreLogic, ChallengeSettlementLogic } = await (0, libraries_1.challengesLibraries)({ logOutput: false });
const challengesV2 = (await (0, helpers_1.upgradeProxy)("B3TRChallengesV1", "B3TRChallenges", await challengesV1.getAddress(), [], {
version: 2,
libraries: {
ChallengeCoreLogic: await ChallengeCoreLogic.getAddress(),
ChallengeSettlementLogic: await ChallengeSettlementLogic.getAddress(),
},
}));
(0, chai_1.expect)(await challengesV2.version()).to.equal("2");
(0, chai_1.expect)(await challengesV2.challengeCount()).to.equal(challengeCountBefore);
const challengeAfterUpgrade = await challengesV2.getChallenge(1);
(0, chai_1.expect)(challengeAfterUpgrade.creator).to.equal(challengeBeforeUpgrade.creator);
(0, chai_1.expect)(challengeAfterUpgrade.stakeAmount).to.equal(challengeBeforeUpgrade.stakeAmount);
(0, chai_1.expect)(challengeAfterUpgrade.totalPrize).to.equal(challengeBeforeUpgrade.totalPrize);
(0, chai_1.expect)(challengeAfterUpgrade.startRound).to.equal(challengeBeforeUpgrade.startRound);
(0, chai_1.expect)(challengeAfterUpgrade.endRound).to.equal(challengeBeforeUpgrade.endRound);
(0, chai_1.expect)(challengeAfterUpgrade.participantCount).to.equal(challengeBeforeUpgrade.participantCount);
(0, chai_1.expect)(challengeAfterUpgrade.invitedCount).to.equal(challengeBeforeUpgrade.invitedCount);
(0, chai_1.expect)(challengeAfterUpgrade.title).to.equal(challengeBeforeUpgrade.title);
(0, chai_1.expect)(challengeAfterUpgrade.description).to.equal(challengeBeforeUpgrade.description);
(0, chai_1.expect)(challengeAfterUpgrade.imageURI).to.equal(challengeBeforeUpgrade.imageURI);
(0, chai_1.expect)(challengeAfterUpgrade.metadataURI).to.equal(challengeBeforeUpgrade.metadataURI);
(0, chai_1.expect)(await challengesV2.getChallengeParticipants(1)).to.deep.equal(participantsBefore);
(0, chai_1.expect)(await challengesV2.getChallengeInvited(1)).to.deep.equal(invitedBefore);
(0, chai_1.expect)(await challengesV2.getParticipantStatus(1, admin.address)).to.equal(ParticipantStatus.Joined);
(0, chai_1.expect)(await challengesV2.getParticipantStatus(1, alice.address)).to.equal(ParticipantStatus.Joined);
(0, chai_1.expect)(await challengesV2.getParticipantStatus(1, bob.address)).to.equal(ParticipantStatus.Joined);
(0, chai_1.expect)(await challengesV2.getParticipantStatus(1, carol.address)).to.equal(ParticipantStatus.Invited);
// V2 passport gate is active for new joins. Carol still invited but non-person → cannot join post-upgrade.
await passport.setIsPerson(carol.address, false, "User is blacklisted");
await (0, chai_1.expect)(challengesV2.connect(carol).joinChallenge(1))
.to.be.revertedWithCustomError(challengesV2, "NotVerifiedPerson")
.withArgs(carol.address, "User is blacklisted");
});
});