pragma solidity 0.8.26;
import {Test, console2} from "../../lib/forge-std/src/Test.sol";
import {DeployLevelOne} from "../script/DeployLevelOne.s.sol";
import {GraduateToLevelTwo} from "../script/GraduateToLevelTwo.s.sol";
import {LevelOne} from "../src/LevelOne.sol";
import {LevelTwo} from "../src/LevelTwo.sol";
import {MockUSDC} from "./mocks/MockUSDC.sol";
contract LevelOneAndGraduateTest is Test {
DeployLevelOne deployBot;
GraduateToLevelTwo graduateBot;
LevelOne levelOneProxy;
LevelTwo levelTwoImplementation;
address proxyAddress;
address levelOneImplementationAddress;
address levelTwoImplementationAddress;
MockUSDC usdc;
address principal;
uint256 schoolFees;
address alice;
address bob;
address ed;
address clara;
address dan;
address eli;
address fin;
address grey;
address harriet;
function setUp() public {
deployBot = new DeployLevelOne();
proxyAddress = deployBot.deployLevelOne();
levelOneProxy = LevelOne(proxyAddress);
usdc = deployBot.getUSDC();
principal = deployBot.principal();
schoolFees = deployBot.getSchoolFees();
levelOneImplementationAddress = deployBot.getImplementationAddress();
alice = makeAddr("first_teacher");
bob = makeAddr("second_teacher");
ed = makeAddr("third_teacher");
clara = makeAddr("first_student");
dan = makeAddr("second_student");
eli = makeAddr("third_student");
fin = makeAddr("fourth_student");
grey = makeAddr("fifth_student");
harriet = makeAddr("sixth_student");
usdc.mint(clara, schoolFees);
usdc.mint(dan, schoolFees);
usdc.mint(eli, schoolFees);
usdc.mint(fin, schoolFees);
usdc.mint(grey, schoolFees);
usdc.mint(harriet, schoolFees);
}
modifier schoolInSession() {
_teachersAdded();
_studentsEnrolled();
vm.prank(principal);
levelOneProxy.startSession(70);
_;
}
function test_confirm_can_graduate_but_overpayment() public schoolInSession {
uint256 bursaryBeforeUpgrade = usdc.balanceOf(address(levelOneProxy));
console2.log("Bursary before system upgrade: ", bursaryBeforeUpgrade);
uint256 aliceWageBeforeUpgrade = usdc.balanceOf(alice);
uint256 bobWageBeforeUpgrade = usdc.balanceOf(bob);
console2.log("Teacher Alice balance before system upgrade: ", aliceWageBeforeUpgrade);
console2.log("Teacher Bob balance before system upgrade: ", bobWageBeforeUpgrade);
levelTwoImplementation = new LevelTwo();
levelTwoImplementationAddress = address(levelTwoImplementation);
bytes memory data = abi.encodeCall(LevelTwo.graduate, ());
vm.prank(principal);
levelOneProxy.graduateAndUpgrade(levelTwoImplementationAddress, data);
uint256 bursaryAfterUpgrade = usdc.balanceOf(address(levelOneProxy));
console2.log("Bursary after system upgrade: ", bursaryAfterUpgrade);
uint256 aliceWageAfterUpgrade = usdc.balanceOf(alice);
uint256 bobWageAfterUpgrade = usdc.balanceOf(bob);
console2.log("Teacher Alice balance after system upgrade: ", aliceWageAfterUpgrade);
console2.log("Teacher Bob balance after system upgrade: ", bobWageAfterUpgrade);
assertEq((aliceWageAfterUpgrade * 100) / bursaryBeforeUpgrade, 35, "Alice wage is 35% of bursary");
assertEq((bobWageAfterUpgrade * 100) / bursaryBeforeUpgrade, 35, "Bob wage is 35% of bursary");
}
function _teachersAdded() internal {
vm.startPrank(principal);
levelOneProxy.addTeacher(alice);
levelOneProxy.addTeacher(bob);
vm.stopPrank();
}
function _studentsEnrolled() internal {
vm.startPrank(clara);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.startPrank(dan);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.startPrank(eli);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.startPrank(fin);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.startPrank(grey);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
vm.startPrank(harriet);
usdc.approve(address(levelOneProxy), schoolFees);
levelOneProxy.enroll();
vm.stopPrank();
}
}
Foundry and manual review.