Skip to content

Commit

Permalink
hekla deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
bearni95 committed Dec 12, 2024
1 parent 4215325 commit 49e9812
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ contract BadgeRecruitment is
TrailblazersBadgesS2 public s2Badges;
/// @notice Wallet authorized to sign as a source of randomness
address public randomSigner;
/// @notice Recruitment-enabled badge IDs per cycle
//mapping(uint256 cycle => mapping(uint256 s1BadgeId => bool enabled)) public enabledBadgeIds;
// uint256[] public currentCycleEnabledRecruitmentIds;
/// @notice Current recruitment cycle
uint256 public recruitmentCycleId;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ contract BadgeRecruitmentV2 is BadgeRecruitment {

/// @notice Errors
error RECRUITMENT_ALREADY_COMPLETED();
error RECRUITMENT_NOT_FOUND();

/// @notice Updated version function
function version() external pure virtual returns (string memory) {
Expand Down Expand Up @@ -45,7 +46,7 @@ contract BadgeRecruitmentV2 is BadgeRecruitment {
/// @dev Bypasses the default date checks
function forceDisableAllRecruitments() external virtual onlyRole(DEFAULT_ADMIN_ROLE) {
forceDisableRecruitments();
// emit disabled badges

emit RecruitmentCycleToggled(
recruitmentCycleId,
recruitmentCycles[recruitmentCycleId].startTime,
Expand All @@ -67,39 +68,62 @@ contract BadgeRecruitmentV2 is BadgeRecruitment {

/// @notice Reset a recruitment that hasn't been completed
/// @param _user The user address
/// @param _recruitmentIdx The recruitment index
/// @param _s1TokenId The s1 token ID
/// @param _s1BadgeId The s1 badge ID
/// @param _recruitmentCycle The recruitment index
/// @dev Must be called from the s1 badges contract
function resetRecruitment(
address _user,
uint256 _recruitmentIdx,
uint256 _s1TokenId
uint256 _s1TokenId,
uint256 _s1BadgeId,
uint256 _recruitmentCycle
)
public
virtual
onlyRole(S1_BADGES_ROLE)
{
Recruitment memory recruitment_ = recruitments[_user][_recruitmentIdx];
if (recruitment_.s1TokenId != _s1TokenId) {
revert RECRUITMENT_NOT_STARTED();
if (
!recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType
.Migration]
&& !recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType.Claim]
&& !recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType
.Undefined]
) {
revert RECRUITMENT_NOT_FOUND();
}

if (recruitment_.s2TokenId != 0) {
revert RECRUITMENT_ALREADY_COMPLETED();
bool found = false;

for (uint256 i = 0; i < recruitments[_user].length; i++) {
if (
recruitments[_user][i].recruitmentCycle == _recruitmentCycle
&& recruitments[_user][i].s1TokenId == _s1TokenId
&& recruitments[_user][i].s2TokenId == 0
) {
delete recruitments[_user][i];
found = true;
break;
}
}

// reset
uint256 s1BadgeId_ = recruitment_.s1BadgeId;
if (!found) {
revert RECRUITMENT_NOT_FOUND();
}

//delete
delete recruitments[_user][_recruitmentIdx];
recruitmentCycleUniqueMints[recruitmentCycleId][_user][s1BadgeId_][RecruitmentType.Undefined]
recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType.Undefined]
= false;
recruitmentCycleUniqueMints[recruitmentCycleId][_user][s1BadgeId_][RecruitmentType.Claim] =
recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType.Claim] =
false;
recruitmentCycleUniqueMints[recruitmentCycleId][_user][s1BadgeId_][RecruitmentType.Migration]
recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType.Migration]
= false;

emit RecruitmentReset(recruitmentCycleId, _user, _s1TokenId, s1BadgeId_);
emit RecruitmentReset(_recruitmentCycle, _user, _s1TokenId, _s1BadgeId);
}

/// @notice Set the s2 badges contract
/// @param _s2Badges The s2 badges contract address
/// @dev Must be called from the admin account
function setS2BadgesContract(address _s2Badges) external virtual onlyRole(DEFAULT_ADMIN_ROLE) {
s2Badges = TrailblazersBadgesS2(_s2Badges);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,24 @@ contract TrailblazersBadgesV5 is TrailblazersBadgesV4 {
error RECRUITMENT_ALREADY_COMPLETED();
error NOT_OWNER();
error NOT_IMPLEMENTED();
error RECRUITMENT_NOT_FOUND();
/// @notice Updated version function
/// @return Version string

function version() external pure virtual override returns (string memory) {
return "V5";
}
/// @notice Recruitment contract

BadgeRecruitmentV2 public recruitmentContractV2;
/// @notice Setter for recruitment contract

function setRecruitmentContractV2(address _recruitmentContractV2) public onlyOwner {
recruitmentContractV2 = BadgeRecruitmentV2(_recruitmentContractV2);
}

/// @notice Start recruitment for a badge
/// @param _badgeId Badge ID
/// @param _tokenId Token ID
function startRecruitment(uint256 _badgeId, uint256 _tokenId) public {
if (recruitmentLockDuration == 0) {
Expand All @@ -48,24 +52,15 @@ contract TrailblazersBadgesV5 is TrailblazersBadgesV4 {

/// @notice Reset an ongoing migration
/// @param _tokenId Token ID
function resetMigration(uint256 _tokenId) public virtual {
/// @param _badgeId Badge ID
/// @param _cycleId Cycle ID
/// @dev Only the owner of the token can reset the migration
function resetMigration(uint256 _tokenId, uint256 _badgeId, uint256 _cycleId) public virtual {
if (ownerOf(_tokenId) != _msgSender()) {
revert NOT_OWNER();
}

BadgeRecruitment.Recruitment[] memory recruitments_ =
recruitmentContractV2.getActiveRecruitmentsFor(_msgSender());

for (uint256 i = 0; i < recruitments_.length; i++) {
// check if the recruitment is ongoing
// AND if it isn't finished (s2TokenId == 0)
if (recruitments_[i].s1TokenId == _tokenId && recruitments_[i].s2TokenId == 0) {
unlockTimestamps[_tokenId] = 0;
recruitmentContractV2.resetRecruitment(_msgSender(), i, _tokenId);
return;
}
}

revert RECRUITMENT_ALREADY_COMPLETED();
recruitmentContractV2.resetRecruitment(_msgSender(), _tokenId, _badgeId, _cycleId);
unlockTimestamps[_tokenId] = 0;
}
}
6 changes: 3 additions & 3 deletions packages/nfts/deployments/trailblazers-season-2/hekla.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"BadgeRecruitment": "0x731E8687AF8e98207B1eaE76fEAbDd08fBf01e6a",
"BadgeRecruitment": "0xcb00B57e8F5fCFffE87bb65f3047b6e4e5A73cA9",
"Owner": "0x4100a9B680B1Be1F10Cb8b5a57fE59eA77A8184e",
"TrailblazersBadges": "0xF38805C75F9E58F8766AB7585E3EBFc0C5F863ec",
"TrailblazersBadgesS2": "0x7aBB3b49e539081A43f1d6bd8aC7462187379E5a"
"TrailblazersBadges": "0x3a7d7c963EF905FCdb6CefAA21b52497fae3EFC4",
"TrailblazersBadgesS2": "0xDE43b7b9A485d76bc8D48a69DdE6b89540b27DdD"
}
2 changes: 1 addition & 1 deletion packages/nfts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"pfp:deploy:hekla": "forge clean && pnpm compile && forge script script/profile/Deploy.s.sol --rpc-url https://rpc.hekla.taiko.xyz --broadcast --gas-estimate-multiplier 200",
"pfp:deploy:mainnet": "forge clean && pnpm compile && forge script script/profile/Deploy.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast --gas-estimate-multiplier 200",
"tbz:airdrop:hekla": "forge clean && pnpm compile && forge script script/trailblazers-airdrop/Deploy.s.sol --rpc-url https://rpc.hekla.taiko.xyz --broadcast --gas-estimate-multiplier 200",
"tbz:airdrop:mainnet": "forge clean && pnpm compile && forge script script/trailblazers-airdrop/Deploy.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast --gas-estimate-multiplier 100",
"tbz:airdrop:mainnet": "forge clean && pnpm compile && forge script script/trailblazers-airdrop/Deploy.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --verify --broadcast --gas-estimate-multiplier 100",
"tbz:upgradeV3:hekla": "forge clean && pnpm compile && forge script script/trailblazers-badges/sol/UpgradeV3.s.sol --rpc-url https://rpc.hekla.taiko.xyz --broadcast --gas-estimate-multiplier 200",
"tbz:upgradeV3:mainnet": "forge clean && pnpm compile && forge script script/trailblazers-badges/sol/UpgradeV3.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast --gas-estimate-multiplier 100",
"tbz:upgradeV4:mainnet": "forge clean && pnpm compile && forge script script/trailblazers-badges/UpgradeV4.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast --gas-estimate-multiplier 100",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ contract UpgradeV2 is Script {

s1Token.setRecruitmentLockDuration(S1_LOCK_DURATION);

// deploy s2 badges
impl = address(new TrailblazersBadgesS2());
proxy = address(
new ERC1967Proxy(
impl,
abi.encodeCall(TrailblazersBadgesS2.initialize, (deployerAddress, baseURI))
)
);

s2Token = TrailblazersBadgesS2(proxy);

// deploy recruitment contract
BadgeRecruitment.Config memory config = BadgeRecruitment.Config(
COOLDOWN_RECRUITMENT,
Expand All @@ -114,24 +125,17 @@ contract UpgradeV2 is Script {

badgeRecruitment = BadgeRecruitment(proxy);

// s2 token
impl = address(new TrailblazersBadgesS2());
proxy = address(
new ERC1967Proxy(
impl,
abi.encodeCall(TrailblazersBadgesS2.initialize, (deployerAddress, baseURI))
)
);

s2Token = TrailblazersBadgesS2(proxy);

// overwrite json deployment data
string memory jsonRoot = "root";
vm.serializeAddress(jsonRoot, "TrailblazersBadges", address(s1Token));
vm.serializeAddress(jsonRoot, "TrailblazersBadgesS2", address(s2Token));
vm.serializeAddress(jsonRoot, "BadgeRecruitment", address(badgeRecruitment));
string memory finalJson = vm.serializeAddress(jsonRoot, "Owner", s2Token.owner());
vm.writeJson(finalJson, jsonLocation);

// further setup
s1Token.setRecruitmentContract(address(badgeRecruitment));
s2Token.setMinter(address(badgeRecruitment));
}

// upgrade token contract
Expand Down
31 changes: 26 additions & 5 deletions packages/nfts/test/trailblazers-season-2/BadgeRecruitmentV2.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,21 @@ contract BadgeRecruitmentV2Test is Test {

function test_resetRecruitment() public {
test_full_recruitment();
uint256 initialCycleId = recruitment.recruitmentCycleId();

assertEq(initialCycleId, 2);
// roll forward the cycle
vm.startPrank(owner);

uint256[] memory enabledBadgeIds = new uint256[](1);
enabledBadgeIds[0] = BADGE_ID;
recruitment.forceDisableAllRecruitments();
recruitment.enableRecruitments(enabledBadgeIds);
vm.stopPrank();

uint256 cycleId = recruitment.recruitmentCycleId();
assertEq(cycleId, 3);

address minter = minters[0];
uint256 ongoingTokenId = s1BadgesV5.tokenOfOwnerByIndex(minter, 1);
uint256 completedTokenId = s1BadgesV5.tokenOfOwnerByIndex(minter, 0);
Expand All @@ -266,11 +281,17 @@ contract BadgeRecruitmentV2Test is Test {
vm.startPrank(minter);

// expect revert from the completed migration
vm.expectRevert(TrailblazersBadgesV5.RECRUITMENT_ALREADY_COMPLETED.selector);
s1BadgesV5.resetMigration(completedTokenId);
vm.expectRevert(TrailblazersBadgesV5.RECRUITMENT_NOT_FOUND.selector);
s1BadgesV5.resetMigration(completedTokenId, BADGE_ID, initialCycleId);
// on both cycles
vm.expectRevert(TrailblazersBadgesV5.RECRUITMENT_NOT_FOUND.selector);
s1BadgesV5.resetMigration(completedTokenId, BADGE_ID, cycleId);
// as well as for the ongoing migration on the current cycle
vm.expectRevert(TrailblazersBadgesV5.RECRUITMENT_NOT_FOUND.selector);
s1BadgesV5.resetMigration(ongoingTokenId, BADGE_ID, cycleId);

// reset the ongoing recruitment
s1BadgesV5.resetMigration(ongoingTokenId);
s1BadgesV5.resetMigration(ongoingTokenId, BADGE_ID, initialCycleId);

// start over the ongoing migration
wait(100);
Expand Down Expand Up @@ -300,7 +321,7 @@ contract BadgeRecruitmentV2Test is Test {
assertEq(s2Badges.balanceOf(minter, 2), 1);

// fail to reset the ongoing migration
vm.expectRevert(TrailblazersBadgesV5.RECRUITMENT_ALREADY_COMPLETED.selector);
s1BadgesV5.resetMigration(ongoingTokenId);
vm.expectRevert(TrailblazersBadgesV5.RECRUITMENT_NOT_FOUND.selector);
s1BadgesV5.resetMigration(ongoingTokenId, BADGE_ID, cycleId);
}
}

0 comments on commit 49e9812

Please sign in to comment.