Skip to content

Commit

Permalink
adaptations for mainnet deployments
Browse files Browse the repository at this point in the history
  • Loading branch information
bearni95 committed May 28, 2024
1 parent 9e6449b commit 7ef5fd5
Show file tree
Hide file tree
Showing 15 changed files with 99 additions and 15 deletions.
2 changes: 2 additions & 0 deletions packages/nfts/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ IPFS_BASE_URI=
OWNER=
4EVERLAND_ACCESS_KEY=
4EVERLAND_SECRET_KEY=
BLACKLIST_ADDRESS=
MAINNET_PRIVATE_KEY=
36 changes: 32 additions & 4 deletions packages/nfts/contracts/snaefell/MerkleWhitelist.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,61 @@ import { Ownable2StepUpgradeable } from
import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import { ContextUpgradeable } from
"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import { IMinimalBlacklist } from "@taiko/blacklist/IMinimalBlacklist.sol";

/// @title MerkleWhitelist
/// @dev Merkle Tree Whitelist
/// @custom:security-contact [email protected]
contract MerkleWhitelist is ContextUpgradeable, UUPSUpgradeable, Ownable2StepUpgradeable {
event RootUpdated(bytes32 _root);
event MintConsumed(address _minter, uint256 _mintAmount);
event BlacklistUpdated(address _blacklist);

error MINTS_EXCEEDED();
error INVALID_PROOF();
error INVALID_TOKEN_AMOUNT();
error ADDRESS_BLACKLISTED();

/// @notice Merkle Tree Root
bytes32 public root;
/// @notice Tracker for minted leaves
mapping(bytes32 leaf => bool hasMinted) public minted;

/// @notice Blackist address
IMinimalBlacklist public blacklist;
/// @notice Gap for upgrade safety
uint256[48] private __gap;

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

/// @notice Update the blacklist address
/// @param _blacklist The new blacklist address
function updateBlacklist(IMinimalBlacklist _blacklist) external onlyOwner {
blacklist = _blacklist;
emit BlacklistUpdated(address(_blacklist));
}

/// @notice Contract initializer
/// @param _root Merkle Tree root
function initialize(address _owner, bytes32 _root) external initializer {
__MerkleWhitelist_init(_owner, _root);
function initialize(
address _owner,
bytes32 _root,
IMinimalBlacklist _blacklist
)
external
initializer
{
__MerkleWhitelist_init(_owner, _root, _blacklist);
}

/// @notice Check if a wallet can free mint
/// @param _minter Address of the minter
/// @param _maxMints Max amount of free mints
/// @return Whether the wallet can mint
function canMint(address _minter, uint256 _maxMints) public view returns (bool) {
if (blacklist.isBlacklisted(_minter)) revert ADDRESS_BLACKLISTED();
bytes32 _leaf = leaf(_minter, _maxMints);
return !minted[_leaf];
}
Expand All @@ -57,10 +77,18 @@ contract MerkleWhitelist is ContextUpgradeable, UUPSUpgradeable, Ownable2StepUpg

/// @notice Internal initializer
/// @param _root Merkle Tree root
function __MerkleWhitelist_init(address _owner, bytes32 _root) internal initializer {
function __MerkleWhitelist_init(
address _owner,
bytes32 _root,
IMinimalBlacklist _blacklist
)
internal
initializer
{
_transferOwnership(_owner == address(0) ? msg.sender : _owner);
__Context_init();
root = _root;
blacklist = _blacklist;
}

/// @notice Update the merkle tree's root
Expand Down
6 changes: 4 additions & 2 deletions packages/nfts/contracts/snaefell/SnaefellToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity 0.8.24;
import { ERC721EnumerableUpgradeable } from
"@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol";
import { MerkleWhitelist } from "./MerkleWhitelist.sol";
import { IMinimalBlacklist } from "@taiko/blacklist/IMinimalBlacklist.sol";

/// @title TaikoonToken
/// @dev The SnaefellToken ERC-721 token
Expand All @@ -28,13 +29,14 @@ contract SnaefellToken is ERC721EnumerableUpgradeable, MerkleWhitelist {
function initialize(
address _owner,
string memory _rootURI,
bytes32 _merkleRoot
bytes32 _merkleRoot,
IMinimalBlacklist _blacklistAddress
)
external
initializer
{
__ERC721_init("SnaefellToken", "SNF");
__MerkleWhitelist_init(_owner, _merkleRoot);
__MerkleWhitelist_init(_owner, _merkleRoot, _blacklistAddress);
_baseURIExtended = _rootURI;
}

Expand Down
3 changes: 1 addition & 2 deletions packages/nfts/deployments/snaefell/devnet.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"MerkleRoot": "0xb5edb18eeaeb9c03bde474b7dd392d0594ecc3d9066c7e3c90d611086543d01e",
"Owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"AlphaToken": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512"
"SnaefellToken": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9"
}
4 changes: 2 additions & 2 deletions packages/nfts/deployments/snaefell/localhost.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"AlphaToken": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
"Owner": "0xB73b0FC4C0Cfc73cF6e034Af6f6b42Ebe6c8b49D"
"Owner": "0xB73b0FC4C0Cfc73cF6e034Af6f6b42Ebe6c8b49D",
"SnaefellToken": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9"
}
4 changes: 4 additions & 0 deletions packages/nfts/deployments/snaefell/mainnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"Owner": "0xB73b0FC4C0Cfc73cF6e034Af6f6b42Ebe6c8b49D",
"SnaefellToken": "0xe5d84034f185eC81bD0D6f4Fc400F324792B4D52"
}
5 changes: 5 additions & 0 deletions packages/nfts/deployments/taikoon/mainnet.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"MerkleRoot": "0x1c71ed62062e13d65812291988bfef0460682d875100761c58592d17c18555a9",
"Owner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"TaikoonToken": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512"
}
4 changes: 3 additions & 1 deletion packages/nfts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
"taikoon:deploy:ipfs": "rm -rf data/taikoon/metadata/* && node script/taikoon/js/4everland.js",
"snaefell:deploy:ipfs": "rm -rf data/snaefell/metadata/* && node script/snaefell/js/4everland.js",
"taikoon:deploy:devnet": "forge clean && pnpm compile && forge script script/taikoon/sol/Deploy.s.sol --rpc-url https://rpc.internal.taiko.xyz --broadcast --gas-estimate-multiplier 200",
"snaefell:deploy:devnet": "forge clean && pnpm compile && forge script script/snaefell/sol/Deploy.s.sol --rpc-url https://rpc.internal.taiko.xyz --broadcast --gas-estimate-multiplier 200"
"snaefell:deploy:devnet": "forge clean && pnpm compile && forge script script/snaefell/sol/Deploy.s.sol --rpc-url https://rpc.internal.taiko.xyz --broadcast --gas-estimate-multiplier 200",
"taikoon:deploy:mainnet": "forge clean && pnpm compile && forge script script/taikoon/sol/Deploy.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast",
"snaefell:deploy:mainnet": "forge clean && pnpm compile && forge script script/snaefell/sol/Deploy.s.sol --rpc-url https://rpc.mainnet.taiko.xyz --broadcast"
},
"devDependencies": {
"@types/node": "^20.11.30",
Expand Down
1 change: 1 addition & 0 deletions packages/nfts/script/snaefell/js/generate-merkle-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ async function main(network) {

main("hardhat");
main("devnet");
main('mainnet')
7 changes: 6 additions & 1 deletion packages/nfts/script/snaefell/sol/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ contract DeployScript is Script {

address impl = address(new SnaefellToken());
address proxy = address(
new ERC1967Proxy(impl, abi.encodeCall(SnaefellToken.initialize, (owner, baseURI, root)))
new ERC1967Proxy(
impl,
abi.encodeCall(
SnaefellToken.initialize, (owner, baseURI, root, utils.getBlacklist())
)
)
);

SnaefellToken token = SnaefellToken(proxy);
Expand Down
17 changes: 17 additions & 0 deletions packages/nfts/script/snaefell/sol/Utils.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ pragma solidity 0.8.24;

import { Script, console } from "forge-std/src/Script.sol";
import "forge-std/src/StdJson.sol";
import { IMinimalBlacklist } from "@taiko/blacklist/IMinimalBlacklist.sol";
import { MockBlacklist } from "../../../test/util/Blacklist.sol";

contract UtilsScript is Script {
using stdJson for string;
Expand All @@ -27,6 +29,9 @@ contract UtilsScript is Script {
} else if (chainId == 167_008) {
lowercaseNetworkKey = "katla";
uppercaseNetworkKey = "KATLA";
} else if (chainId == 167_000) {
lowercaseNetworkKey = "mainnet";
uppercaseNetworkKey = "MAINNET";
} else {
revert("Unsupported chainId");
}
Expand All @@ -51,5 +56,17 @@ contract UtilsScript is Script {
return vm.envString("IPFS_BASE_URI");
}

function getBlacklist() public returns (IMinimalBlacklist blacklistAddress) {
if (block.chainid == 167_000) {
// mainnet blacklist address
blacklistAddress = IMinimalBlacklist(vm.envAddress("BLACKLIST_ADDRESS"));
} else {
// deploy a mock blacklist otherwise
blacklistAddress = IMinimalBlacklist(new MockBlacklist());
}

return blacklistAddress;
}

function run() public { }
}
2 changes: 1 addition & 1 deletion packages/nfts/script/taikoon/js/generate-merkle-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ async function main(network) {
}

main("hardhat");
main("holesky");
main("devnet");
main('mainnet')
3 changes: 3 additions & 0 deletions packages/nfts/script/taikoon/sol/Utils.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ contract UtilsScript is Script {
} else if (chainId == 167_008) {
lowercaseNetworkKey = "katla";
uppercaseNetworkKey = "KATLA";
} else if (chainId == 167_000) {
lowercaseNetworkKey = "mainnet";
uppercaseNetworkKey = "MAINNET";
} else {
revert("Unsupported chainId");
}
Expand Down
10 changes: 9 additions & 1 deletion packages/nfts/test/snaefell/SnaefellToken.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import { Test } from "forge-std/src/Test.sol";
import { SnaefellToken } from "../../contracts/snaefell/SnaefellToken.sol";
import { Merkle } from "murky/Merkle.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import { UtilsScript } from "../../script/snaefell/sol/Utils.s.sol";

contract SnaefellTokenTest is Test {
UtilsScript public utils;

SnaefellToken public token;

address public owner = vm.addr(0x5);
Expand All @@ -20,6 +23,8 @@ contract SnaefellTokenTest is Test {
Merkle tree = new Merkle();

function setUp() public {
utils = new UtilsScript();
utils.setUp();
// create whitelist merkle tree
vm.startBroadcast(owner);
bytes32 root = tree.getRoot(leaves);
Expand All @@ -28,7 +33,10 @@ contract SnaefellTokenTest is Test {
address impl = address(new SnaefellToken());
address proxy = address(
new ERC1967Proxy(
impl, abi.encodeCall(SnaefellToken.initialize, (address(0), "ipfs://", root))
impl,
abi.encodeCall(
SnaefellToken.initialize, (address(0), "ipfs://", root, utils.getBlacklist())
)
)
);

Expand Down
10 changes: 9 additions & 1 deletion packages/nfts/test/snaefell/Upgradeable.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import { Test, console } from "forge-std/src/Test.sol";
import { SnaefellToken } from "../../contracts/snaefell/SnaefellToken.sol";
import { Merkle } from "murky/Merkle.sol";
import "forge-std/src/StdJson.sol";
import { UtilsScript } from "../../script/snaefell/sol/Utils.s.sol";

import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract UpgradeableTest is Test {
using stdJson for string;

UtilsScript public utils;

SnaefellToken public token;

address public owner = vm.addr(0x5);
Expand All @@ -23,6 +26,8 @@ contract UpgradeableTest is Test {
Merkle tree = new Merkle();

function setUp() public {
utils = new UtilsScript();
utils.setUp();
// create whitelist merkle tree
vm.startPrank(owner);
bytes32 root = tree.getRoot(leaves);
Expand All @@ -31,7 +36,10 @@ contract UpgradeableTest is Test {
address impl = address(new SnaefellToken());
address proxy = address(
new ERC1967Proxy(
impl, abi.encodeCall(SnaefellToken.initialize, (address(0), "ipfs://", root))
impl,
abi.encodeCall(
SnaefellToken.initialize, (address(0), "ipfs://", root, utils.getBlacklist())
)
)
);

Expand Down

0 comments on commit 7ef5fd5

Please sign in to comment.