UNPKG

@vechain/vebetterdao-contracts

Version:

Open-source repository that houses the smart contracts powering the decentralized VeBetterDAO on the VeChain Thor blockchain.

244 lines (243 loc) 15.5 kB
import { ethers } from "hardhat"; import { describe, it, beforeEach } from "mocha"; import { expect } from "chai"; import { setupSignalingFixture } from "./fixture.test"; import { endorseApp } from "../helpers/xnodes"; import { linkEntityToPassportWithSignature } from "../helpers/common"; describe("VeBetterPassport (Signaling Logic) - @shard8b", function () { let veBetterPassport; let owner; let otherAccounts; let appId; let regularSignaler; let appAdmin; let x2EarnApps; beforeEach(async function () { const fixture = await setupSignalingFixture(); veBetterPassport = fixture.veBetterPassport; owner = fixture.owner; otherAccounts = fixture.otherAccounts; appId = fixture.appId; regularSignaler = fixture.regularSignaler; appAdmin = fixture.appAdmin; x2EarnApps = fixture.x2EarnApps; }); describe("Signaling By Default Admin", function () { it("Admin can update the signaling threshold", async function () { // Enable score check await veBetterPassport.connect(owner).toggleCheck(4); // score check should be enabled expect(await veBetterPassport.isCheckEnabled(4)).to.be.true; // Expect score threshold to be 0 expect(await veBetterPassport.thresholdPoPScore()).to.equal(0); await expect(veBetterPassport.connect(regularSignaler).signalUserWithReason(owner.address, "Some reason")) .to.emit(veBetterPassport, "UserSignaled") .withArgs(owner.address, regularSignaler.address, appId, "Some reason"); expect(await veBetterPassport.signaledCounter(owner.address)).to.equal(1); // User should be a person as their score is 0 and participation score check is enabled with threshold of 0, // even if they have been signaled (as the signaling threshold is not met yet) expect(await veBetterPassport.isPerson(owner.address)).to.deep.equal([ true, "User's participation score is above the threshold", ]); // Update the signaling threshold to 1 await veBetterPassport.connect(owner).setSignalingThreshold(1); // Enable signaling check await veBetterPassport.connect(owner).toggleCheck(3); // User should be a bot as they have been signaled and signaling threshold is 1 expect(await veBetterPassport.isPerson(owner.address)).to.deep.equal([ false, "User has been signaled too many times", ]); }); it("DEFAULT_ADMIN_ROLE can reset signals of a user", async function () { // Signal the user await expect(veBetterPassport.connect(regularSignaler).signalUserWithReason(owner.address, "Some reason")) .to.emit(veBetterPassport, "UserSignaled") .withArgs(owner.address, regularSignaler.address, appId, "Some reason"); expect(await veBetterPassport.signaledCounter(owner.address)).to.equal(1); // Reset the signals await expect(veBetterPassport .connect(owner) .resetUserSignalsWithReason(owner.address, "User demonstrated erroneous signaling")) .to.emit(veBetterPassport, "UserSignalsReset") .withArgs(owner.address, "User demonstrated erroneous signaling"); expect(await veBetterPassport.signaledCounter(owner.address)).to.equal(0); }); it("Should not be able to reset signals without DEFAULT_ADMIN_ROLE", async function () { // Signal the user await expect(veBetterPassport.connect(regularSignaler).signalUserWithReason(owner.address, "Some reason")) .to.emit(veBetterPassport, "UserSignaled") .withArgs(owner.address, regularSignaler.address, appId, "Some reason"); expect(await veBetterPassport.signaledCounter(owner.address)).to.equal(1); // Try to reset with a non-admin account await expect(veBetterPassport .connect(regularSignaler) .resetUserSignalsWithReason(owner.address, "User demonstrated erroneous signaling")).to.be.reverted; // Counter should remain unchanged expect(await veBetterPassport.signaledCounter(owner.address)).to.equal(1); }); it("ROLE_GRANTER can add and remove app signalers", async function () { const targetSignaler = otherAccounts[2]; // First verify the account is not a signaler expect(await veBetterPassport.appOfSignaler(targetSignaler.address)).to.equal(ethers.ZeroHash); // Add signaler using admin await expect(veBetterPassport.connect(owner).assignSignalerToApp(appId, targetSignaler.address)) .to.emit(veBetterPassport, "SignalerAssignedToApp") .withArgs(targetSignaler.address, appId); expect(await veBetterPassport.appOfSignaler(targetSignaler.address)).to.equal(appId); // Remove signaler await expect(veBetterPassport.connect(owner).removeSignalerFromApp(targetSignaler.address)) .to.emit(veBetterPassport, "SignalerRemovedFromApp") .withArgs(targetSignaler.address, appId); expect(await veBetterPassport.appOfSignaler(targetSignaler.address)).to.equal(ethers.ZeroHash); }); it("DEFAULT_ADMIN_ROLE can signal a user without reason", async function () { const targetUser = otherAccounts[5]; // Admin can signal without providing a reason await expect(veBetterPassport.connect(owner).signalUser(targetUser.address)) .to.emit(veBetterPassport, "UserSignaled") .withArgs(targetUser.address, owner.address, ethers.ZeroHash, ""); expect(await veBetterPassport.signaledCounter(targetUser.address)).to.equal(1); }); it("Non-admin users cannot use signalUser (no reason)", async function () { const targetUser = otherAccounts[7]; // Regular signaler should not be able to use the no-reason function await expect(veBetterPassport.connect(regularSignaler).signalUser(targetUser.address)).to.be.reverted; // Verify no signals were recorded expect(await veBetterPassport.signaledCounter(targetUser.address)).to.equal(0); }); }); describe("Signaling By SIGNALER_ROLE", function () { it("Admin of App can assign and revoke a signaler", async function () { const targetSignaler = otherAccounts[2]; // First verify the account is not a signaler expect(await veBetterPassport.appOfSignaler(targetSignaler.address)).to.equal(ethers.ZeroHash); // Assign signaler await expect(veBetterPassport.connect(appAdmin).assignSignalerToAppByAppAdmin(appId, targetSignaler.address)) .to.emit(veBetterPassport, "SignalerAssignedToApp") .withArgs(targetSignaler.address, appId); expect(await veBetterPassport.appOfSignaler(targetSignaler.address)).to.equal(appId); // Remove signaler await expect(veBetterPassport.connect(appAdmin).removeSignalerFromAppByAppAdmin(targetSignaler.address)) .to.emit(veBetterPassport, "SignalerRemovedFromApp") .withArgs(targetSignaler.address, appId); expect(await veBetterPassport.appOfSignaler(targetSignaler.address)).to.equal(ethers.ZeroHash); }); it("Non-Admin of an app cannot add a signaler", async function () { const nonAdminAccount = otherAccounts[3]; const targetSignaler = otherAccounts[4]; // Try to assign signaler with non-admin account await expect(veBetterPassport.connect(nonAdminAccount).assignSignalerToAppByAppAdmin(appId, targetSignaler.address)).to.be.reverted; }); it("Signaler can signal a user", async function () { const targetUser = otherAccounts[3]; // Verify starting state expect(await veBetterPassport.hasRole(await veBetterPassport.SIGNALER_ROLE(), regularSignaler.address)).to.be.true; expect(await veBetterPassport.signaledCounter(targetUser.address)).to.equal(0); await expect(veBetterPassport.connect(regularSignaler).signalUserWithReason(targetUser.address, "Some reason")) .to.emit(veBetterPassport, "UserSignaled") .withArgs(targetUser.address, regularSignaler.address, appId, "Some reason"); expect(await veBetterPassport.signaledCounter(targetUser.address)).to.equal(1); // Remove signaler role await expect(veBetterPassport.connect(appAdmin).removeSignalerFromAppByAppAdmin(regularSignaler.address)) .to.emit(veBetterPassport, "SignalerRemovedFromApp") .withArgs(regularSignaler.address, appId); // Try to signal again - should fail await expect(veBetterPassport.connect(regularSignaler).signalUserWithReason(targetUser.address, "Some reason")).to .be.reverted; }); it("Passport signals should be updated when an entity's signals get reset", async function () { // Create a new entity-passport relationship const entity = otherAccounts[3]; const passport = otherAccounts[4]; // Link entity to passport await linkEntityToPassportWithSignature(veBetterPassport, passport, entity, 100000); // Make passport a signaler and reset signaler for the app await expect(veBetterPassport.connect(appAdmin).assignSignalerToAppByAppAdmin(appId, passport.address)) .to.emit(veBetterPassport, "SignalerAssignedToApp") .withArgs(passport.address, appId); // Signal the entity await expect(veBetterPassport.connect(passport).signalUserWithReason(entity.address, "Some reason")) .to.emit(veBetterPassport, "UserSignaled") .withArgs(entity.address, passport.address, appId, "Some reason"); // Verify signals for both entity and passport expect(await veBetterPassport.signaledCounter(entity.address)).to.equal(1); expect(await veBetterPassport.signaledCounter(passport.address)).to.equal(1); // Reset signals await expect(veBetterPassport .connect(owner) .resetUserSignalsWithReason(entity.address, "User demonstrated erroneous signaling")) .to.emit(veBetterPassport, "UserSignalsReset") .withArgs(entity.address, "User demonstrated erroneous signaling"); // Verify signals are reset for both expect(await veBetterPassport.signaledCounter(entity.address)).to.equal(0); expect(await veBetterPassport.signaledCounter(passport.address)).to.equal(0); }); it("Passport signals should be updated when an entity's app signals get reset", async function () { // Create a new entity-passport relationship const entity = otherAccounts[3]; const passport = otherAccounts[4]; // Link entity to passport await linkEntityToPassportWithSignature(veBetterPassport, passport, entity, 100000); // Signal the entity await expect(veBetterPassport.connect(regularSignaler).signalUserWithReason(entity.address, "Some reason")) .to.emit(veBetterPassport, "UserSignaled") .withArgs(entity.address, regularSignaler.address, appId, "Some reason"); expect(await veBetterPassport.signaledCounter(entity.address)).to.equal(1); expect(await veBetterPassport.signaledCounter(passport.address)).to.equal(1); // Reset signals via app admin await expect(veBetterPassport .connect(owner) .resetUserSignalsWithReason(entity.address, "User demonstrated erroneous signaling")) .to.emit(veBetterPassport, "UserSignalsReset") .withArgs(entity.address, "User demonstrated erroneous signaling"); // Verify signals are reset for both expect(await veBetterPassport.signaledCounter(entity.address)).to.equal(0); expect(await veBetterPassport.signaledCounter(passport.address)).to.equal(0); }); }); it("should be able to reset signals of a user by app admins", async function () { // Create a new app with otherAccounts[5] as admin const newAppAdmin = otherAccounts[5]; const targetUser = otherAccounts[6]; await x2EarnApps .connect(newAppAdmin) .submitApp(otherAccounts[7].address, newAppAdmin, otherAccounts[7].address, "metadataURI"); const newAppId = ethers.keccak256(ethers.toUtf8Bytes(otherAccounts[7].address)); await endorseApp(newAppId, newAppAdmin); // Make newAppAdmin both a signaler and reset signaler for the new app await expect(veBetterPassport.connect(newAppAdmin).assignSignalerToAppByAppAdmin(newAppId, newAppAdmin.address)) .to.emit(veBetterPassport, "SignalerAssignedToApp") .withArgs(newAppAdmin.address, newAppId); // Signal user with both signalers await expect(veBetterPassport.connect(regularSignaler).signalUserWithReason(targetUser.address, "Some reason")) .to.emit(veBetterPassport, "UserSignaled") .withArgs(targetUser.address, regularSignaler.address, appId, "Some reason"); await expect(veBetterPassport.connect(newAppAdmin).signalUserWithReason(targetUser.address, "Some reason")) .to.emit(veBetterPassport, "UserSignaled") .withArgs(targetUser.address, newAppAdmin.address, newAppId, "Some reason"); expect(await veBetterPassport.signaledCounter(targetUser.address)).to.equal(2); // Reset signals of user by app admin await expect(veBetterPassport .connect(owner) .resetUserSignalsWithReason(targetUser.address, "User demonstrated erroneous signaling")) .to.emit(veBetterPassport, "UserSignalsReset") .withArgs(targetUser.address, "User demonstrated erroneous signaling"); expect(await veBetterPassport.signaledCounter(targetUser.address)).to.equal(0); }); describe("Signaling By UPGRADER_ROLE", function () { it("Should allow to set signaling threshold", async function () { await veBetterPassport.connect(owner).setSignalingThreshold(2); expect(await veBetterPassport.signalingThreshold()).to.equal(2); await expect(veBetterPassport.connect(owner).grantRole(await veBetterPassport.UPGRADER_ROLE(), otherAccounts[2].address)) .to.emit(veBetterPassport, "RoleGranted") .withArgs(await veBetterPassport.UPGRADER_ROLE(), otherAccounts[2].address, owner.address); await veBetterPassport.connect(otherAccounts[2]).setSignalingThreshold(3); expect(await veBetterPassport.signalingThreshold()).to.equal(3); }); it("Should revert if not UPGRADER_ROLE", async function () { await expect(veBetterPassport.connect(otherAccounts[3]).setSignalingThreshold(4)).to.be.reverted; }); }); });