|
9 | 9 | PassportRegistry, |
10 | 10 | PassportBuilderScore, |
11 | 11 | PassportWalletRegistry, |
| 12 | + FixedBuilderScore, |
12 | 13 | } from "../../../typechain-types"; |
13 | 14 | import { Artifacts } from "../../shared"; |
14 | 15 | import { ensureTimestamp } from "../../shared/utils"; |
@@ -942,4 +943,128 @@ describe("TalentVault", () => { |
942 | 943 | }); |
943 | 944 | }); |
944 | 945 | }); |
| 946 | + |
| 947 | + describe("FixedBuilderScore", async () => { |
| 948 | + let fixedBuilderScore: FixedBuilderScore; |
| 949 | + |
| 950 | + beforeEach(async () => { |
| 951 | + fixedBuilderScore = (await deployContract(admin, Artifacts.FixedBuilderScore, [ |
| 952 | + 60, |
| 953 | + admin.address, |
| 954 | + ])) as FixedBuilderScore; |
| 955 | + }); |
| 956 | + |
| 957 | + describe("Deployment", async () => { |
| 958 | + it("Should set the correct owner", async () => { |
| 959 | + expect(await fixedBuilderScore.owner()).to.equal(admin.address); |
| 960 | + }); |
| 961 | + |
| 962 | + it("Should set the correct initial fixed score", async () => { |
| 963 | + expect(await fixedBuilderScore.fixedScore()).to.equal(60); |
| 964 | + }); |
| 965 | + }); |
| 966 | + |
| 967 | + describe("#getScore", async () => { |
| 968 | + it("returns the fixed score for any passport ID", async () => { |
| 969 | + expect(await fixedBuilderScore.getScore(1)).to.equal(60); |
| 970 | + expect(await fixedBuilderScore.getScore(999)).to.equal(60); |
| 971 | + expect(await fixedBuilderScore.getScore(0)).to.equal(60); |
| 972 | + }); |
| 973 | + }); |
| 974 | + |
| 975 | + describe("#setFixedScore", async () => { |
| 976 | + context("when called by the owner", async () => { |
| 977 | + it("updates the fixed score", async () => { |
| 978 | + await fixedBuilderScore.setFixedScore(80); |
| 979 | + expect(await fixedBuilderScore.fixedScore()).to.equal(80); |
| 980 | + }); |
| 981 | + |
| 982 | + it("emits FixedScoreUpdated event", async () => { |
| 983 | + await expect(fixedBuilderScore.setFixedScore(80)) |
| 984 | + .to.emit(fixedBuilderScore, "FixedScoreUpdated") |
| 985 | + .withArgs(60, 80); |
| 986 | + }); |
| 987 | + }); |
| 988 | + |
| 989 | + context("when called by a non-owner", async () => { |
| 990 | + it("reverts", async () => { |
| 991 | + await expect(fixedBuilderScore.connect(user1).setFixedScore(80)).to.be.revertedWith( |
| 992 | + `OwnableUnauthorizedAccount("${user1.address}")` |
| 993 | + ); |
| 994 | + }); |
| 995 | + }); |
| 996 | + }); |
| 997 | + |
| 998 | + describe("TalentVault with FixedBuilderScore", async () => { |
| 999 | + beforeEach(async () => { |
| 1000 | + // Swap PassportBuilderScore for FixedBuilderScore in TalentVault |
| 1001 | + await talentVault.setPassportBuilderScore(fixedBuilderScore.address); |
| 1002 | + }); |
| 1003 | + |
| 1004 | + it("uses the fixed score for yield calculation", async () => { |
| 1005 | + expect(await talentVault.passportBuilderScore()).to.equal(fixedBuilderScore.address); |
| 1006 | + }); |
| 1007 | + |
| 1008 | + context("when fixed score is >= 60 (bonus tier)", async () => { |
| 1009 | + it("calculates rewards at 10% APY", async () => { |
| 1010 | + await fixedBuilderScore.setFixedScore(60); |
| 1011 | + |
| 1012 | + const depositAmount = ethers.utils.parseEther("1000"); |
| 1013 | + await talentToken.transfer(user1.address, depositAmount); |
| 1014 | + await talentToken.connect(user1).approve(talentVault.address, depositAmount); |
| 1015 | + await talentVault.connect(user1).deposit(depositAmount, user1.address); |
| 1016 | + |
| 1017 | + // Simulate time passing |
| 1018 | + ensureTimestamp(currentDateEpochSeconds + 31536000); // 1 year ahead |
| 1019 | + |
| 1020 | + await talentVault.connect(user1).refresh(); |
| 1021 | + |
| 1022 | + // 10% yield over 90 days (yieldAccrualDeadline) |
| 1023 | + const expectedRewards = yieldBasePerDay.mul(2).mul(90); |
| 1024 | + const userBalance = await talentVault.balanceOf(user1.address); |
| 1025 | + expect(userBalance).to.be.closeTo(depositAmount.add(expectedRewards), ethers.utils.parseEther("0.1")); |
| 1026 | + }); |
| 1027 | + }); |
| 1028 | + |
| 1029 | + context("when fixed score is < 60 (base tier)", async () => { |
| 1030 | + it("calculates rewards at 5% APY", async () => { |
| 1031 | + await fixedBuilderScore.setFixedScore(59); |
| 1032 | + |
| 1033 | + const depositAmount = ethers.utils.parseEther("1000"); |
| 1034 | + await talentToken.transfer(user1.address, depositAmount); |
| 1035 | + await talentToken.connect(user1).approve(talentVault.address, depositAmount); |
| 1036 | + await talentVault.connect(user1).deposit(depositAmount, user1.address); |
| 1037 | + |
| 1038 | + // Simulate time passing |
| 1039 | + ensureTimestamp(currentDateEpochSeconds + 31536000); // 1 year ahead |
| 1040 | + |
| 1041 | + await talentVault.connect(user1).refresh(); |
| 1042 | + |
| 1043 | + // 5% yield over 90 days (yieldAccrualDeadline) |
| 1044 | + const expectedRewards = yieldBasePerDay.mul(90); |
| 1045 | + const userBalance = await talentVault.balanceOf(user1.address); |
| 1046 | + expect(userBalance).to.be.closeTo(depositAmount.add(expectedRewards), ethers.utils.parseEther("0.1")); |
| 1047 | + }); |
| 1048 | + }); |
| 1049 | + |
| 1050 | + context("when admin changes fixed score", async () => { |
| 1051 | + it("affects future yield calculations for all users", async () => { |
| 1052 | + // Start with score 0 (base rate) |
| 1053 | + await fixedBuilderScore.setFixedScore(0); |
| 1054 | + |
| 1055 | + const depositAmount = ethers.utils.parseEther("1000"); |
| 1056 | + await talentToken.transfer(user1.address, depositAmount); |
| 1057 | + await talentToken.connect(user1).approve(talentVault.address, depositAmount); |
| 1058 | + await talentVault.connect(user1).deposit(depositAmount, user1.address); |
| 1059 | + |
| 1060 | + // Change to bonus tier |
| 1061 | + await fixedBuilderScore.setFixedScore(60); |
| 1062 | + |
| 1063 | + // All users now get the bonus rate |
| 1064 | + const yieldRate = await talentVault.getYieldRateForScore(user1.address); |
| 1065 | + expect(yieldRate).to.equal(10_00); // 10% |
| 1066 | + }); |
| 1067 | + }); |
| 1068 | + }); |
| 1069 | + }); |
945 | 1070 | }); |
0 commit comments