diff --git a/packages/taikoon/contracts/MerkleWhitelist.sol b/packages/taikoon/contracts/MerkleWhitelist.sol index 86ac55dbd1..5c50b0759a 100644 --- a/packages/taikoon/contracts/MerkleWhitelist.sol +++ b/packages/taikoon/contracts/MerkleWhitelist.sol @@ -1,6 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; +import { UUPSUpgradeable } from + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { Ownable2StepUpgradeable } from + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import { ContextUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"; @@ -8,7 +12,7 @@ import { ContextUpgradeable } from /// @title MerkleWhitelist /// @dev Merkle Tree Whitelist /// @custom:security-contact security@taiko.xyz -contract MerkleWhitelist is ContextUpgradeable { +contract MerkleWhitelist is ContextUpgradeable, UUPSUpgradeable, Ownable2StepUpgradeable { event RootUpdated(bytes32 _root); event MintConsumed(address _minter, uint256 _mintAmount); @@ -30,9 +34,8 @@ contract MerkleWhitelist is ContextUpgradeable { /// @notice Contract initializer /// @param _root Merkle Tree root - function initialize(bytes32 _root) external initializer { - __Context_init(); - root = _root; + function initialize(address _owner, bytes32 _root) external initializer { + __MerkleWhitelist_init(_owner, _root); } /// @notice Check if a wallet can free mint @@ -54,7 +57,8 @@ contract MerkleWhitelist is ContextUpgradeable { /// @notice Internal initializer /// @param _root Merkle Tree root - function __MerkleWhitelist_init(bytes32 _root) internal initializer { + function __MerkleWhitelist_init(address _owner, bytes32 _root) internal initializer { + _transferOwnership(_owner == address(0) ? msg.sender : _owner); __Context_init(); root = _root; } @@ -76,4 +80,7 @@ contract MerkleWhitelist is ContextUpgradeable { minted[_leaf] = true; emit MintConsumed(_msgSender(), _maxMints); } + + /// @notice Internal method to authorize an upgrade + function _authorizeUpgrade(address) internal virtual override onlyOwner { } } diff --git a/packages/taikoon/contracts/TaikoonToken.sol b/packages/taikoon/contracts/TaikoonToken.sol index 439045c4ed..bde8faa689 100644 --- a/packages/taikoon/contracts/TaikoonToken.sol +++ b/packages/taikoon/contracts/TaikoonToken.sol @@ -2,24 +2,16 @@ pragma solidity 0.8.24; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { Ownable2StepUpgradeable } from - "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; + import { ERC721EnumerableUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol"; -import { UUPSUpgradeable } from - "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { MerkleWhitelist } from "./MerkleWhitelist.sol"; /// @title TaikoonToken /// @dev The Taikoons ERC-721 token /// @custom:security-contact security@taiko.xyz -contract TaikoonToken is - ERC721EnumerableUpgradeable, - UUPSUpgradeable, - Ownable2StepUpgradeable, - MerkleWhitelist -{ +contract TaikoonToken is ERC721EnumerableUpgradeable, MerkleWhitelist { /// @notice The current supply uint256 private _totalSupply; // Base URI required to interact with IPFS @@ -35,10 +27,16 @@ contract TaikoonToken is /// @notice Contract initializer /// @param _rootURI Base URI for the token metadata /// @param _merkleRoot Merkle tree root for the whitelist - function initialize(string memory _rootURI, bytes32 _merkleRoot) external initializer { + function initialize( + address _owner, + string memory _rootURI, + bytes32 _merkleRoot + ) + external + initializer + { __ERC721_init("Taikoon", "TKOON"); - __Ownable_init(_msgSender()); - __MerkleWhitelist_init(_merkleRoot); + __MerkleWhitelist_init(_owner, _merkleRoot); _baseURIExtended = _rootURI; } @@ -99,9 +97,6 @@ contract TaikoonToken is return _baseURIExtended; } - /// @notice Internal method to authorize an upgrade - function _authorizeUpgrade(address) internal virtual override onlyOwner { } - /// @notice Internal method to batch mint tokens /// @param _to The address to mint to /// @param _amount The amount of tokens to mint diff --git a/packages/taikoon/foundry.toml b/packages/taikoon/foundry.toml index c20bc4d545..6c524f9f39 100644 --- a/packages/taikoon/foundry.toml +++ b/packages/taikoon/foundry.toml @@ -16,11 +16,10 @@ remappings = [ "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "solady/=node_modules/solady/", - "forge-std/=node_modules/forge-std/src/", + "forge-std/=node_modules/forge-std/", "ds-test/=node_modules/ds-test/src/", "p256-verifier/=node_modules/p256-verifier/", "murky/=node_modules/murky/src/", - "@openzeppelin/foundry-upgrades/=node_modules/@openzeppelin/foundry-upgrades/src/", "solidity-stringutils/=node_modules/solidity-stringutils/", ] diff --git a/packages/taikoon/package.json b/packages/taikoon/package.json index b324343c68..4b5027832a 100644 --- a/packages/taikoon/package.json +++ b/packages/taikoon/package.json @@ -35,7 +35,6 @@ "dependencies": { "@openzeppelin/contracts": "5.0.2", "@openzeppelin/contracts-upgradeable": "5.0.2", - "@openzeppelin/foundry-upgrades": "github:OpenZeppelin/openzeppelin-foundry-upgrades", "@openzeppelin/merkle-tree": "^1.0.6", "convert-csv-to-json": "^2.46.0", "ds-test": "github:dapphub/ds-test#e282159d5170298eb2455a6c05280ab5a73a4ef0", diff --git a/packages/taikoon/script/sol/Deploy.s.sol b/packages/taikoon/script/sol/Deploy.s.sol index 1ed48f580a..d37fa87adc 100644 --- a/packages/taikoon/script/sol/Deploy.s.sol +++ b/packages/taikoon/script/sol/Deploy.s.sol @@ -2,11 +2,10 @@ pragma solidity 0.8.24; import { UtilsScript } from "./Utils.s.sol"; -import { Script, console } from "forge-std/Script.sol"; +import { Script, console } from "forge-std/src/Script.sol"; import { MerkleMintersScript } from "./MerkleMinters.s.sol"; import { Merkle } from "murky/Merkle.sol"; -import { Upgrades } from "@openzeppelin/foundry-upgrades/Upgrades.sol"; - +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import { TaikoonToken } from "../../contracts/TaikoonToken.sol"; contract DeployScript is Script { @@ -16,6 +15,9 @@ contract DeployScript is Script { uint256 public deployerPrivateKey; address public deployerAddress; + // Please set owner to labs.taiko.eth (0xB73b0FC4C0Cfc73cF6e034Af6f6b42Ebe6c8b49D) on Mainnnet. + address owner = vm.envAddress("OWNER"); + function setUp() public { utils = new UtilsScript(); utils.setUp(); @@ -30,6 +32,8 @@ contract DeployScript is Script { function run() public { string memory jsonRoot = "root"; + require(owner != address(0), "Owner must be specified"); + vm.startBroadcast(deployerPrivateKey); bytes32 root = merkleMinters.root(); @@ -37,8 +41,9 @@ contract DeployScript is Script { string memory baseURI = utils.getIpfsBaseURI(); // deploy token with empty root - address proxy = Upgrades.deployUUPSProxy( - "TaikoonToken.sol", abi.encodeCall(TaikoonToken.initialize, (baseURI, root)) + address impl = address(new TaikoonToken()); + address proxy = address( + new ERC1967Proxy(impl, abi.encodeCall(TaikoonToken.initialize, (owner, baseURI, root))) ); TaikoonToken token = TaikoonToken(proxy); @@ -47,6 +52,7 @@ contract DeployScript is Script { console.log("Deployed TaikoonToken to:", address(token)); vm.serializeBytes32(jsonRoot, "MerkleRoot", root); + vm.serializeAddress(jsonRoot, "Owner", token.owner()); string memory finalJson = vm.serializeAddress(jsonRoot, "TaikoonToken", address(token)); vm.writeJson(finalJson, jsonLocation); diff --git a/packages/taikoon/script/sol/MerkleMinters.s.sol b/packages/taikoon/script/sol/MerkleMinters.s.sol index eb88dbc0bb..7e52b81a45 100644 --- a/packages/taikoon/script/sol/MerkleMinters.s.sol +++ b/packages/taikoon/script/sol/MerkleMinters.s.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import { Script, console } from "forge-std/Script.sol"; -import "forge-std/StdJson.sol"; +import { Script, console } from "forge-std/src/Script.sol"; +import "forge-std/src/StdJson.sol"; import { UtilsScript } from "./Utils.s.sol"; import { Merkle } from "murky/Merkle.sol"; import "./CsvParser.sol"; diff --git a/packages/taikoon/script/sol/Utils.s.sol b/packages/taikoon/script/sol/Utils.s.sol index dd9b033837..753e02b384 100644 --- a/packages/taikoon/script/sol/Utils.s.sol +++ b/packages/taikoon/script/sol/Utils.s.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import { Script, console } from "forge-std/Script.sol"; -import "forge-std/StdJson.sol"; +import { Script, console } from "forge-std/src/Script.sol"; +import "forge-std/src/StdJson.sol"; contract UtilsScript is Script { using stdJson for string; diff --git a/packages/taikoon/test/MerkleWhitelist.t.sol b/packages/taikoon/test/MerkleWhitelist.t.sol index 01c2db0a78..60232521a8 100644 --- a/packages/taikoon/test/MerkleWhitelist.t.sol +++ b/packages/taikoon/test/MerkleWhitelist.t.sol @@ -1,13 +1,22 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import { Test, console } from "forge-std/Test.sol"; -import "forge-std/StdJson.sol"; +import { Test, console } from "forge-std/src/Test.sol"; +import "forge-std/src/StdJson.sol"; import { Merkle } from "murky/Merkle.sol"; import { MerkleWhitelist } from "../contracts/MerkleWhitelist.sol"; -import { Upgrades } from "@openzeppelin/foundry-upgrades/Upgrades.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -import { MerkleWhitelistTestWrapper } from "./MerkleWhitelistTestWrapper.sol"; +/// @custom:oz-upgrades-from MerkleWhitelist +contract MerkleWhitelistForTest is MerkleWhitelist { + function updateRoot(bytes32 _root) external { + _updateRoot(_root); + } + + function consumeMint(bytes32[] calldata _proof, uint256 _freeMints) external { + _consumeMint(_proof, _freeMints); + } +} contract MerkleWhitelistTest is Test { Merkle tree; @@ -18,7 +27,7 @@ contract MerkleWhitelistTest is Test { address public owner = vm.addr(0x5); - MerkleWhitelistTestWrapper whitelist; + MerkleWhitelistForTest whitelist; uint256 constant MAX_MINTS = 5; @@ -40,13 +49,12 @@ contract MerkleWhitelistTest is Test { bytes32 root = tree.getRoot(leaves); - address transparentProxy = Upgrades.deployTransparentProxy( - "MerkleWhitelist.sol", owner, abi.encodeCall(MerkleWhitelist.initialize, (root)) + address impl = address(new MerkleWhitelistForTest()); + address proxy = address( + new ERC1967Proxy(impl, abi.encodeCall(MerkleWhitelist.initialize, (address(0), root))) ); - Upgrades.upgradeProxy(transparentProxy, "MerkleWhitelistTestWrapper.sol", ""); - - whitelist = MerkleWhitelistTestWrapper(transparentProxy); + whitelist = MerkleWhitelistForTest(proxy); vm.stopBroadcast(); } diff --git a/packages/taikoon/test/TaikoonToken.t.sol b/packages/taikoon/test/TaikoonToken.t.sol index 16d3a8c6b5..5dadd1c422 100644 --- a/packages/taikoon/test/TaikoonToken.t.sol +++ b/packages/taikoon/test/TaikoonToken.t.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import { Test } from "forge-std/Test.sol"; +import { Test } from "forge-std/src/Test.sol"; + import { TaikoonToken } from "../contracts/TaikoonToken.sol"; import { Merkle } from "murky/Merkle.sol"; -import { Upgrades } from "@openzeppelin/foundry-upgrades/Upgrades.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract TaikoonTokenTest is Test { TaikoonToken public token; @@ -24,8 +25,11 @@ contract TaikoonTokenTest is Test { bytes32 root = tree.getRoot(leaves); // deploy token with empty root - address proxy = Upgrades.deployUUPSProxy( - "TaikoonToken.sol", abi.encodeCall(TaikoonToken.initialize, ("ipfs://", root)) + address impl = address(new TaikoonToken()); + address proxy = address( + new ERC1967Proxy( + impl, abi.encodeCall(TaikoonToken.initialize, (address(0), "ipfs://", root)) + ) ); token = TaikoonToken(proxy); diff --git a/packages/taikoon/test/Upgradeable.t.sol b/packages/taikoon/test/Upgradeable.t.sol index ceefe3fc95..0f2b42d87c 100644 --- a/packages/taikoon/test/Upgradeable.t.sol +++ b/packages/taikoon/test/Upgradeable.t.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import { Test, console } from "forge-std/Test.sol"; +import { Test, console } from "forge-std/src/Test.sol"; import { TaikoonToken } from "../contracts/TaikoonToken.sol"; import { Merkle } from "murky/Merkle.sol"; import { MerkleMintersScript } from "../script/sol/MerkleMinters.s.sol"; -import "forge-std/StdJson.sol"; +import "forge-std/src/StdJson.sol"; -import { Upgrades } from "@openzeppelin/foundry-upgrades/Upgrades.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract UpgradeableTest is Test { using stdJson for string; @@ -31,8 +31,11 @@ contract UpgradeableTest is Test { bytes32 root = tree.getRoot(leaves); // deploy token with empty root - address proxy = Upgrades.deployUUPSProxy( - "TaikoonToken.sol", abi.encodeCall(TaikoonToken.initialize, ("ipfs://", root)) + address impl = address(new TaikoonToken()); + address proxy = address( + new ERC1967Proxy( + impl, abi.encodeCall(TaikoonToken.initialize, (address(0), "ipfs://", root)) + ) ); token = TaikoonToken(proxy); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 67ebe5b64b..38edc14405 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -417,9 +417,6 @@ importers: '@openzeppelin/contracts-upgradeable': specifier: 5.0.2 version: 5.0.2(@openzeppelin/contracts@5.0.2) - '@openzeppelin/foundry-upgrades': - specifier: github:OpenZeppelin/openzeppelin-foundry-upgrades - version: github.com/OpenZeppelin/openzeppelin-foundry-upgrades/332bd3306242e09520df2685b2edb99ebd7f5d37 '@openzeppelin/merkle-tree': specifier: ^1.0.6 version: 1.0.6 @@ -431,7 +428,7 @@ importers: version: github.com/dapphub/ds-test/e282159d5170298eb2455a6c05280ab5a73a4ef0 forge-std: specifier: github:foundry-rs/forge-std - version: github.com/foundry-rs/forge-std/93340e7e6127c817e276bc956b4f4ed13d173449 + version: github.com/foundry-rs/forge-std/5475f852e3f530d7e25dfb4596aa1f9baa8ffdfc ipfs-http-client: specifier: ^60.0.1 version: 60.0.1 @@ -6301,9 +6298,6 @@ packages: resolution: {integrity: sha512-GBryCiyl+taz5DPq0expxzfMVcrpKjWvEBSAqT1tPUSthnzOWnVF77XlUAYgFZqzPsEu9lQ1dHCdqZx7WWMCXA==} peerDependencies: '@web3modal/wallet': 4.1.1 - peerDependenciesMeta: - '@web3modal/siwe': - optional: true dependencies: '@web3modal/common': 4.1.1 '@web3modal/core': 4.1.1(react@18.2.0) @@ -6344,15 +6338,6 @@ packages: '@wagmi/connectors': '>=4.0.0' '@wagmi/core': '>=2.0.0' viem: '>=2.0.0' - peerDependenciesMeta: - '@web3modal/siwe': - optional: true - react: - optional: true - react-dom: - optional: true - vue: - optional: true dependencies: '@wagmi/connectors': 4.1.18(@wagmi/core@2.6.9)(react-dom@18.2.0)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) '@wagmi/core': 2.6.9(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) @@ -8428,7 +8413,7 @@ packages: eslint: 8.55.0 eslint-import-resolver-node: 0.3.9 eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.7.0)(eslint-import-resolver-node@0.3.9)(eslint@8.55.0) - hasown: 2.0.0 + hasown: 2.0.1 is-core-module: 2.13.1 is-glob: 4.0.3 minimatch: 3.1.2 @@ -8527,7 +8512,7 @@ packages: eslint: 8.55.0 eslint-plugin-es: 3.0.1(eslint@8.55.0) eslint-utils: 2.1.0 - ignore: 5.3.0 + ignore: 5.3.1 minimatch: 3.1.2 resolve: 1.22.8 semver: 6.3.1 @@ -9573,13 +9558,6 @@ packages: resolution: {integrity: sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==} dev: false - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - /hasown@2.0.1: resolution: {integrity: sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==} engines: {node: '>= 0.4'} @@ -15514,12 +15492,6 @@ packages: version: 0.0.0 dev: false - github.com/OpenZeppelin/openzeppelin-foundry-upgrades/332bd3306242e09520df2685b2edb99ebd7f5d37: - resolution: {tarball: https://codeload.github.com/OpenZeppelin/openzeppelin-foundry-upgrades/tar.gz/332bd3306242e09520df2685b2edb99ebd7f5d37} - name: openzeppelin-foundry-upgrades - version: 0.0.0 - dev: false - github.com/Vectorized/solady/de0f336d2033d04e0f77c923d639c7fbffd48b6d: resolution: {tarball: https://codeload.github.com/Vectorized/solady/tar.gz/de0f336d2033d04e0f77c923d639c7fbffd48b6d} name: solady @@ -15544,8 +15516,8 @@ packages: version: 1.7.5 dev: false - github.com/foundry-rs/forge-std/93340e7e6127c817e276bc956b4f4ed13d173449: - resolution: {tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/93340e7e6127c817e276bc956b4f4ed13d173449} + github.com/foundry-rs/forge-std/5475f852e3f530d7e25dfb4596aa1f9baa8ffdfc: + resolution: {tarball: https://codeload.github.com/foundry-rs/forge-std/tar.gz/5475f852e3f530d7e25dfb4596aa1f9baa8ffdfc} name: forge-std version: 1.7.6 dev: false