Skip to content

Commit

Permalink
feat(nfts): trailblazer-badges v2 upgrade (#17848)
Browse files Browse the repository at this point in the history
  • Loading branch information
bearni95 authored Jul 30, 2024
1 parent 3649785 commit ffb326b
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 3 deletions.
40 changes: 40 additions & 0 deletions packages/nfts/contracts/trailblazers-badges/TrailblazersBadges.sol
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,44 @@ contract TrailblazersBadges is ERC721EnumerableUpgradeable, ECDSAWhitelist {
balances[7] = 0 != getTokenId(_owner, BADGE_SHINTO);
return balances;
}

/// @notice v2

/// @notice Retrieve the base URI
function baseURI() public view returns (string memory) {
return _baseURIExtended;
}

/// @notice Upgraded badgeBalances using tokenOfOwnerByIndex
/// @param _owner The addresses to check
/// @return balances The badges atomic balances
function badgeBalancesV2(address _owner) public view returns (bool[] memory balances) {
uint256 balance = balanceOf(_owner);
uint256[] memory tokenIds = new uint256[](balance);
for (uint256 i = 0; i < balance; i++) {
tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
}
balances = new bool[](8);

for (uint256 i = 0; i < balance; i++) {
uint256 badgeId = badges[tokenIds[i]];
balances[badgeId] = true;
}

return balances;
}

/// @notice Return the total badge supply by badgeId
/// @return balances The amount of each badge id
function totalBadgeSupply() public view returns (uint256[] memory balances) {
uint256 totalSupply = totalSupply();
balances = new uint256[](8);

for (uint256 i = 1; i <= totalSupply; i++) {
uint256 badgeId = badges[i];
balances[badgeId]++;
}

return balances;
}
}
2 changes: 1 addition & 1 deletion packages/nfts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"eslint": "pnpm exec eslint --ignore-path .eslintignore --ext .js,.ts . --fix",
"fmt:sol": "forge fmt",
"lint:sol": "forge fmt && pnpm solhint 'contracts/**/*.sol'",
"test": "pnpm clean && pnpm compile && forge test --match-path 'test/*.t.sol' -vvv",
"test": "forge test --match-path 'test/*.t.sol' -vvv",
"node": "anvil",
"layout": "./deployments/gen-layouts.sh",
"taikoon:merkle": "node script/taikoon/js/generate-merkle-tree.js",
Expand Down
5 changes: 3 additions & 2 deletions packages/nfts/script/trailblazers-badges/sol/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ contract DeployScript is Script {

// Hardhat Testnet Values
address owner = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266;
address mintSigner = 0x3cda4F2EaC3fc2FdE78B3DFFe1A1A1Eff88c68c5;
string baseURI = "https://taikonfts.4everland.link/ipfs/bafybeierqzehlrqeqqeb6fwmil4dj3ij2p6exgoj4lysl53fsxwob6wbdy";
address mintSigner = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266;
string baseURI =
"https://taikonfts.4everland.link/ipfs/bafybeierqzehlrqeqqeb6fwmil4dj3ij2p6exgoj4lysl53fsxwob6wbdy";
IMinimalBlacklist blacklist = IMinimalBlacklist(0xe61E9034b5633977eC98E302b33e321e8140F105);

function setUp() public {
Expand Down
41 changes: 41 additions & 0 deletions packages/nfts/script/trailblazers-badges/sol/UpgradeV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import { UtilsScript } from "./Utils.s.sol";
import { Script, console } from "forge-std/src/Script.sol";
import { Merkle } from "murky/Merkle.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import { TrailblazersBadges } from "../../../contracts/trailblazers-badges/TrailblazersBadges.sol";
import { IMinimalBlacklist } from "@taiko/blacklist/IMinimalBlacklist.sol";

contract UpgradeV2 is Script {
UtilsScript public utils;
string public jsonLocation;
uint256 public deployerPrivateKey;
address public deployerAddress;

address tokenV1 = 0xa20a8856e00F5ad024a55A663F06DCc419FFc4d5;
TrailblazersBadges public token;

function setUp() public {
utils = new UtilsScript();
utils.setUp();

jsonLocation = utils.getContractJsonLocation();
deployerPrivateKey = utils.getPrivateKey();
deployerAddress = utils.getAddress();
}

function run() public {
token = TrailblazersBadges(tokenV1);
vm.startBroadcast(deployerPrivateKey);

token.upgradeToAndCall(
address(new TrailblazersBadges()), abi.encodeCall(TrailblazersBadges.baseURI, ())
);

token = TrailblazersBadges(token);

console.log("Upgraded TrailblazersBadges to:", address(token));
}
}
88 changes: 88 additions & 0 deletions packages/nfts/test/trailblazers-badges/TrailblazersBadges.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,92 @@ contract TrailblazersBadgesTest is Test {
vm.assertEq(token.getTokenId(minters[0], badgeId), 0);
vm.assertEq(token.getTokenId(minters[1], badgeId), 1);
}

function test_transfer_dataConsistency2() public {
// mint a token to minter 0
uint256 badgeId = token.BADGE_DRUMMERS();

// mint the badge

vm.startBroadcast(owner);
bytes32 _hash = token.getHash(minters[0], badgeId);

(uint8 v, bytes32 r, bytes32 s) = vm.sign(mintSignerPk, _hash);

bool canMint = token.canMint(abi.encodePacked(r, s, v), minters[0], badgeId);
assertTrue(canMint);

token.mint(abi.encodePacked(r, s, v), minters[0], badgeId);
vm.stopBroadcast();

// transfer to minters[1]
vm.startBroadcast(minters[0]);
token.safeTransferFrom(minters[0], minters[1], 1);

// ensure the badge balances are consistent
bool[] memory badges = token.badgeBalancesV2(minters[1]);

// ensure only badgeId = 5 (Drummers) is true
vm.assertFalse(badges[token.BADGE_RAVERS()]);
vm.assertFalse(badges[token.BADGE_ROBOTS()]);
vm.assertFalse(badges[token.BADGE_BOUNCERS()]);
vm.assertFalse(badges[token.BADGE_MASTERS()]);
vm.assertFalse(badges[token.BADGE_MONKS()]);
vm.assertTrue(badges[token.BADGE_DRUMMERS()]);
vm.assertFalse(badges[token.BADGE_ANDROIDS()]);
vm.assertFalse(badges[token.BADGE_SHINTO()]);

vm.stopBroadcast();

// ensure wallets[0] has no badges
badges = token.badgeBalancesV2(minters[0]);

vm.assertFalse(badges[token.BADGE_RAVERS()]);
vm.assertFalse(badges[token.BADGE_ROBOTS()]);
vm.assertFalse(badges[token.BADGE_BOUNCERS()]);
vm.assertFalse(badges[token.BADGE_MASTERS()]);
vm.assertFalse(badges[token.BADGE_MONKS()]);
vm.assertFalse(badges[token.BADGE_DRUMMERS()]);
vm.assertFalse(badges[token.BADGE_ANDROIDS()]);
vm.assertFalse(badges[token.BADGE_SHINTO()]);

// check the token IDs
vm.assertEq(token.getTokenId(minters[0], badgeId), 0);
vm.assertEq(token.getTokenId(minters[1], badgeId), 1);
}

function mintBadgeTo(uint256 badgeId, address minter) private {
vm.startBroadcast(owner);
bytes32 _hash = token.getHash(minter, badgeId);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(mintSignerPk, _hash);
bool canMint = token.canMint(abi.encodePacked(r, s, v), minter, badgeId);
assertTrue(canMint);

token.mint(abi.encodePacked(r, s, v), minter, badgeId);
vm.stopBroadcast();
}

function test_totalBadgeSupply() public {
mintBadgeTo(token.BADGE_RAVERS(), minters[0]);
mintBadgeTo(token.BADGE_ROBOTS(), minters[0]);
mintBadgeTo(token.BADGE_BOUNCERS(), minters[1]);
mintBadgeTo(token.BADGE_MASTERS(), minters[0]);
mintBadgeTo(token.BADGE_MONKS(), minters[0]);
mintBadgeTo(token.BADGE_DRUMMERS(), minters[0]);
mintBadgeTo(token.BADGE_DRUMMERS(), minters[1]);
mintBadgeTo(token.BADGE_DRUMMERS(), minters[2]);
mintBadgeTo(token.BADGE_ANDROIDS(), minters[0]);
mintBadgeTo(token.BADGE_SHINTO(), minters[0]);

uint256[] memory badges = token.totalBadgeSupply();

vm.assertEq(badges[token.BADGE_RAVERS()], 1);
vm.assertEq(badges[token.BADGE_ROBOTS()], 1);
vm.assertEq(badges[token.BADGE_BOUNCERS()], 1);
vm.assertEq(badges[token.BADGE_MASTERS()], 1);
vm.assertEq(badges[token.BADGE_MONKS()], 1);
vm.assertEq(badges[token.BADGE_DRUMMERS()], 3);
vm.assertEq(badges[token.BADGE_ANDROIDS()], 1);
vm.assertEq(badges[token.BADGE_SHINTO()], 1);
}
}

0 comments on commit ffb326b

Please sign in to comment.