Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(nft): fix s2 badges remigration #18578

Merged
merged 26 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6178142
tbz updated blacklist
bearni95 Oct 10, 2024
439b237
Merge branch 'main' of ssh://github.com/taikoxyz/taiko-mono
bearni95 Oct 11, 2024
f50eeb6
Merge branch 'main' of ssh://github.com/taikoxyz/taiko-mono
bearni95 Oct 16, 2024
cb0e4a8
Merge branch 'main' of ssh://github.com/taikoxyz/taiko-mono
bearni95 Oct 17, 2024
999f49e
Merge branch 'main' of ssh://github.com/taikoxyz/taiko-mono
bearni95 Dec 2, 2024
94c69a7
Merge branch 'main' of ssh://github.com/taikoxyz/taiko-mono
bearni95 Dec 3, 2024
1d85a0c
upgradable owner
KorbinianK Dec 5, 2024
5a6f431
Merge branch 'main' of ssh://github.com/taikoxyz/taiko-mono
bearni95 Dec 6, 2024
15343f9
adjust test
KorbinianK Dec 9, 2024
4fecb20
add initialize to deploy script
KorbinianK Dec 9, 2024
b60a2b5
deployment
KorbinianK Dec 9, 2024
e86cccc
Merge branch 'main' of ssh://github.com/taikoxyz/taiko-mono
bearni95 Dec 9, 2024
654fa7b
Merge branch 'main' into event-register-upgradeable
KorbinianK Dec 10, 2024
b9e2675
the commit
bearni95 Dec 11, 2024
c430ab3
recruitment script
bearni95 Dec 11, 2024
b08d0f9
fmt, lint
bearni95 Dec 11, 2024
6cf3954
Merge remote-tracking branch 'origin/event-register-upgradeable' into…
bearni95 Dec 11, 2024
4215325
subgraph changes
bearni95 Dec 11, 2024
49e9812
hekla deployment
bearni95 Dec 12, 2024
46da91c
Merge branch 'main' into s2-badges-remigrate-fix
KorbinianK Dec 13, 2024
511aed3
Merge branch 'main' into s2-badges-remigrate-fix
KorbinianK Dec 13, 2024
3de9e1e
added check to not allow starting recruitments too close to end cycle…
bearni95 Dec 13, 2024
5b0a77c
Merge branch 'main' into s2-badges-remigrate-fix
bearni95 Dec 16, 2024
16783c3
Merge branch 'main' into s2-badges-remigrate-fix
bearni95 Dec 16, 2024
dc770a7
mainnet deployment
bearni95 Dec 16, 2024
f49c39d
Merge branch 'main' into s2-badges-remigrate-fix
bearni95 Dec 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
141 changes: 141 additions & 0 deletions packages/nfts/contracts/trailblazers-season-2/BadgeRecruitmentV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "./BadgeRecruitment.sol";

contract BadgeRecruitmentV2 is BadgeRecruitment {
/// @notice Events
event RecruitmentReset(
uint256 indexed cycleId, address indexed user, uint256 indexed s1TokenId, uint256 s1BadgeId
);

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

modifier recruitmentHasTimeLeft(address _user) {
uint256 endCycleTime = recruitmentCycles[recruitmentCycleId].endTime;
uint256 potentialRecruitmentEndTime = block.timestamp + this.getConfig().cooldownRecruitment;

if (potentialRecruitmentEndTime > endCycleTime) {
revert NOT_ENOUGH_TIME_LEFT();
}
_;
}

/// @notice Updated version function
function version() external pure virtual returns (string memory) {
return "V2";
}

/// @notice Start a recruitment for a badge
/// @param _s1BadgeId The badge ID (s1)
/// @dev Not all badges are eligible for recruitment at the same time
/// @dev Defines a cooldown for the recruitment to be complete
/// @dev the cooldown is lesser the higher the Pass Tier
/// @dev Must be called from the s1 badges contract
function startRecruitment(
address _user,
uint256 _s1BadgeId,
uint256 _s1TokenId
)
external
virtual
onlyRole(S1_BADGES_ROLE)
recruitmentOpen(_s1BadgeId)
isNotMigrating(_user)
hasntMigratedInCycle(_s1BadgeId, _user, RecruitmentType.Migration)
recruitmentHasTimeLeft(_user)
{
if (s1Badges.ownerOf(_s1TokenId) != _user) {
revert TOKEN_NOT_OWNED();
}
_startRecruitment(_user, _s1BadgeId, _s1TokenId, RecruitmentType.Migration);
}

/// @notice Disable all current recruitments
/// @dev Bypasses the default date checks
function forceDisableAllRecruitments() external virtual onlyRole(DEFAULT_ADMIN_ROLE) {
forceDisableRecruitments();

emit RecruitmentCycleToggled(
recruitmentCycleId,
recruitmentCycles[recruitmentCycleId].startTime,
recruitmentCycles[recruitmentCycleId].endTime,
recruitmentCycles[recruitmentCycleId].s1BadgeIds,
false
);
}

/// @notice Get the active recruitment for a user
/// @param _user The user address
/// @return The active recruitment
function getActiveRecruitmentsFor(address _user) public view returns (Recruitment[] memory) {
if (recruitments[_user].length == 0) {
revert RECRUITMENT_NOT_STARTED();
}
return recruitments[_user];
}

/// @notice Reset a recruitment that hasn't been completed
/// @param _user The user address
/// @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 _s1TokenId,
uint256 _s1BadgeId,
uint256 _recruitmentCycle
)
public
virtual
onlyRole(S1_BADGES_ROLE)
{
if (
!recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType
.Migration]
&& !recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType.Claim]
&& !recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType
.Undefined]
) {
revert RECRUITMENT_NOT_FOUND();
}

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;
}
}

if (!found) {
revert RECRUITMENT_NOT_FOUND();
}

recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType.Undefined]
= false;
recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType.Claim] =
false;
recruitmentCycleUniqueMints[_recruitmentCycle][_user][_s1BadgeId][RecruitmentType.Migration]
= false;

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 @@ -59,7 +59,7 @@ contract TrailblazersBadgesV4 is TrailblazersBadgesV3 {

/// @notice Start recruitment for a badge
/// @param _badgeId Badge id
function startRecruitment(uint256 _badgeId) public {
function startRecruitment(uint256 _badgeId) public virtual {
if (recruitmentLockDuration == 0) {
revert RECRUITMENT_LOCK_DURATION_NOT_SET();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "./TrailblazersS1BadgesV4.sol";
import "./BadgeRecruitment.sol";
import "./BadgeRecruitmentV2.sol";

contract TrailblazersBadgesV5 is TrailblazersBadgesV4 {
/// @notice Errors
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) {
revert RECRUITMENT_LOCK_DURATION_NOT_SET();
}
if (ownerOf(_tokenId) != _msgSender()) {
revert NOT_OWNER();
}

if (unlockTimestamps[_tokenId] > block.timestamp) {
revert BADGE_LOCKED();
}

unlockTimestamps[_tokenId] = block.timestamp + recruitmentLockDuration;
recruitmentContractV2.startRecruitment(_msgSender(), _badgeId, _tokenId);
}

/// @notice Deprecated of legacy function
function startRecruitment(uint256 /*_badgeId*/ ) public virtual override {
revert NOT_IMPLEMENTED();
}

/// @notice Reset an ongoing migration
/// @param _tokenId Token ID
/// @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();
}

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": "0xBd368C65Cb354eBAd6c1429b551bD0197f19C2B8",
"BadgeRecruitment": "0xcb00B57e8F5fCFffE87bb65f3047b6e4e5A73cA9",
"Owner": "0x4100a9B680B1Be1F10Cb8b5a57fE59eA77A8184e",
"TrailblazersBadges": "0x9E14C357E964BeE012bA82Ce9d6513dAec6ea961",
"TrailblazersBadgesS2": "0xc84B76a5836Cb0CeF094808af445F7E98504ED5B"
"TrailblazersBadges": "0x3a7d7c963EF905FCdb6CefAA21b52497fae3EFC4",
"TrailblazersBadgesS2": "0xDE43b7b9A485d76bc8D48a69DdE6b89540b27DdD"
}
6 changes: 4 additions & 2 deletions packages/nfts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@
"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",
"tbz-s2:upgradeV2:mainnet": "forge clean && pnpm compile && forge script script/trailblazers-season-2/UpgradeV2.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast --gas-estimate-multiplier 100"
"tbz-s2:upgradeV2:mainnet": "forge clean && pnpm compile && forge script script/trailblazers-season-2/UpgradeV2.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast --gas-estimate-multiplier 100",
"tbz-s2:upgradeRecruitmentV2:hekla": "forge clean && pnpm compile && forge script script/trailblazers-season-2/RecruitmentUpgradeV2.s.sol --rpc-url https://rpc.hekla.taiko.xyz --broadcast --gas-estimate-multiplier 200",
"tbz-s2:upgradeRecruitmentV2:mainnet": "forge clean && pnpm compile && forge script script/trailblazers-season-2/RecruitmentUpgradeV2.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast --gas-estimate-multiplier 100"
},
"devDependencies": {
"@types/node": "^20.11.30",
Expand Down
Loading
Loading