diff --git a/.changeset/funny-rats-draw.md b/.changeset/funny-rats-draw.md new file mode 100644 index 000000000..ec3182e42 --- /dev/null +++ b/.changeset/funny-rats-draw.md @@ -0,0 +1,5 @@ +--- +"@zoralabs/protocol-deployments": patch +--- + +Updated determinstic preminter deployment script to not fail if already deployed diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 000000000..902b2aa24 --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,14 @@ +{ + "mode": "pre", + "tag": "prerelease", + "initialVersions": { + "@zoralabs/zora-1155-contracts": "2.5.1", + "@zoralabs/protocol-deployments": "0.0.6", + "@zoralabs/protocol-rewards": "1.2.1", + "@zoralabs/protocol-sdk": "0.3.2" + }, + "changesets": [ + "funny-rats-draw", + "twelve-swans-help" + ] +} diff --git a/.changeset/tame-chairs-obey.md b/.changeset/tame-chairs-obey.md deleted file mode 100644 index 0e031e43c..000000000 --- a/.changeset/tame-chairs-obey.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@zoralabs/zora-1155-contracts": patch ---- - -Fixed setting uid when doing a premint v1 diff --git a/.changeset/twelve-swans-help.md b/.changeset/twelve-swans-help.md new file mode 100644 index 000000000..5db1f06d4 --- /dev/null +++ b/.changeset/twelve-swans-help.md @@ -0,0 +1,5 @@ +--- +"@zoralabs/protocol-deployments": patch +--- + +Deployed 2.5.1 to zora sepolia and zora goerli diff --git a/packages/1155-contracts/CHANGELOG.md b/packages/1155-contracts/CHANGELOG.md index 21eff506d..563e1e079 100644 --- a/packages/1155-contracts/CHANGELOG.md +++ b/packages/1155-contracts/CHANGELOG.md @@ -1,5 +1,11 @@ # @zoralabs/zora-1155-contracts +## 2.5.1 + +### Patch Changes + +- 68566fce: Fixed setting uid when doing a premint v1 + ## 2.5.0 ### Minor Changes @@ -8,7 +14,7 @@ ### New fields on signature - Adding a new `PremintConfigV2` struct that can be signed, that now contains a `createReferral`. `ZoraCreator1155PremintExecutor` recognizes new version of the premint config, and still works with the v1 (legacy) version of the `PremintConfig`. Version one of the premint config still works and is still defined in the `PremintConfig` struct. + Adding a new `PremintConfigV2` struct that can be signed, that now contains a `createReferral`. `ZoraCreator1155PremintExecutor` recognizes new version of the premint config, and still works with the v1 (legacy) version of the `PremintConfig`. Version one of the premint config still works and is still defined in the `PremintConfig` struct. Additional changes included in `PremintConfigV2`: @@ -22,7 +28,7 @@ ### Replacing external signature validation and authorization check with just authorization check `ZoraCreator1155PremintExecutor`'s function `isValidSignature(contractConfig, premintConfig)` is deprecated in favor of: - + ```solidity isAuthorizedToCreatePremint( address signer, @@ -30,10 +36,10 @@ address contractAddress ) public view returns (bool isAuthorized) ``` - which instead of validating signatures and checking if the signer is authorized to create premints, just checks if an signer is authorized to create premints on the contract. This offloads signature decoding/validation to calling clients offchain, and reduces needing to create different signatures for this function on the contract for each version of the premint config. It also allows Premints to be validated on contracts that were not created using premints, such as contracts that are upgraded, and contracts created directly via the factory. - - - ### Changes to handling of setting of fundsRecipient + + which instead of validating signatures and checking if the signer is authorized to create premints, just checks if an signer is authorized to create premints on the contract. This offloads signature decoding/validation to calling clients offchain, and reduces needing to create different signatures for this function on the contract for each version of the premint config. It also allows Premints to be validated on contracts that were not created using premints, such as contracts that are upgraded, and contracts created directly via the factory. + + ### Changes to handling of setting of fundsRecipient Previously the `fundsRecipient` on the fixed priced minters' sales config for the token was set to the signer of the premint. This has been changed to be set to the `payoutRecipient` of the premint config on `PremintConfigV2`, and to the `royaltyRecipient` of the premint config for v1 of the premint config, for 1155 contracts that are to be newly created, and for existing 1155 contracts that are upgraded to the latest version. @@ -137,7 +143,7 @@ takes a signer, contractConfig.contractAdmin, and 1155 address, and determines if the signer is authorized to sign premints on the given contract. Replaces `isValidSignature` - by putting the burden on clients to first decode the signature, then pass the recovered signer to this function to determine if the signer has premint authorization on the contract. - deprecated function `isValidSignature` - call `isAuthorizedToCreatePremint` instead - + ### Patch Changes - 885ffa4: Premint executor can still execute premint mints that were created with V1 signatures for `delegateSetupNewToken` diff --git a/packages/1155-contracts/package.json b/packages/1155-contracts/package.json index 98a7eb4d0..10499d423 100644 --- a/packages/1155-contracts/package.json +++ b/packages/1155-contracts/package.json @@ -1,6 +1,6 @@ { "name": "@zoralabs/zora-1155-contracts", - "version": "2.5.0", + "version": "2.5.1", "repository": "git@github.com:ourzora/zora-protocol.git", "author": "Iain ", "license": "MIT", diff --git a/packages/1155-contracts/src/version/ContractVersionBase.sol b/packages/1155-contracts/src/version/ContractVersionBase.sol index 864c81940..70e265553 100644 --- a/packages/1155-contracts/src/version/ContractVersionBase.sol +++ b/packages/1155-contracts/src/version/ContractVersionBase.sol @@ -1,5 +1,5 @@ // This file is automatically generated by code; do not manually update -// Last updated on 2023-11-20T19:36:43.527Z +// Last updated on 2023-11-21T02:54:10.313Z // SPDX-License-Identifier: MIT pragma solidity 0.8.17; @@ -10,6 +10,6 @@ import {IVersionedContract} from "../interfaces/IVersionedContract.sol"; contract ContractVersionBase is IVersionedContract { /// @notice The version of the contract function contractVersion() external pure override returns (string memory) { - return "2.5.0"; + return "2.5.1"; } } diff --git a/packages/protocol-deployments/CHANGELOG.md b/packages/protocol-deployments/CHANGELOG.md index 447599ebc..5c5c6a694 100644 --- a/packages/protocol-deployments/CHANGELOG.md +++ b/packages/protocol-deployments/CHANGELOG.md @@ -1,5 +1,12 @@ # @zoralabs/premint-sdk +## 0.0.7-prerelease.0 + +### Patch Changes + +- dba9bb0: Updated determinstic preminter deployment script to not fail if already deployed +- 4c4ae23: Deployed 2.5.1 to zora sepolia and zora goerli + ## 0.0.6 ### Patch Changes diff --git a/packages/protocol-deployments/addresses/999.json b/packages/protocol-deployments/addresses/999.json index 105bc7af5..669d67b1f 100644 --- a/packages/protocol-deployments/addresses/999.json +++ b/packages/protocol-deployments/addresses/999.json @@ -1,14 +1,14 @@ { - "CONTRACT_1155_IMPL": "0xcD7230AFfBC8C720aE607e0Bc386fbCAF5C34C2E", - "CONTRACT_1155_IMPL_VERSION": "2.4.0", - "FACTORY_IMPL": "0x869Be2EaE4AB30Cf319a46B5dE50Ac203c8784Aa", + "CONTRACT_1155_IMPL": "0xa2669e686fa4192166daEa69F269b262636eE198", + "CONTRACT_1155_IMPL_VERSION": "2.5.1", + "FACTORY_IMPL": "0x30ed75ffaDF6215A3190d43ec505750a70B29fAc", "FACTORY_PROXY": "0x777777C338d93e2C7adf08D102d45CA7CC4Ed021", "FIXED_PRICE_SALE_STRATEGY": "0x04E2516A2c207E84a1839755675dfd8eF6302F0a", "MERKLE_MINT_SALE_STRATEGY": "0xf48172CA3B6068B20eE4917Eb27b5472f1f272C7", - "PREMINTER_IMPL": "0x6E2AbBcd82935bFC68A1d5d2c96372b13b65eD9C", + "PREMINTER_IMPL": "0x37A7c717c3EDA58e4ec7F424B2A46934Fd8f8468", "PREMINTER_PROXY": "0x7777773606e7e46C8Ba8B98C08f5cD218e31d340", "REDEEM_MINTER_FACTORY": "0x78964965cF77850224513a367f899435C5B69174", "UPGRADE_GATE": "0xbC50029836A59A4E5e1Bb8988272F46ebA0F9900", - "timestamp": 1699570171, - "commit": "385e4932" + "timestamp": 1700533625, + "commit": "8c57238e" } \ No newline at end of file diff --git a/packages/protocol-deployments/addresses/999999999.json b/packages/protocol-deployments/addresses/999999999.json index 7f93dbaa4..49a11f757 100644 --- a/packages/protocol-deployments/addresses/999999999.json +++ b/packages/protocol-deployments/addresses/999999999.json @@ -1,14 +1,14 @@ { - "CONTRACT_1155_IMPL": "0xC6899816663891D7493939d74d83cb7f2BBcBB16", - "CONTRACT_1155_IMPL_VERSION": "2.4.0", - "FACTORY_IMPL": "0xA2d5B3C1feb801c0A1CF083Ee17d939A5E5D2464", + "CONTRACT_1155_IMPL": "0xF3a46845548bE811Ce37e65153563f4a0AaEbe31", + "CONTRACT_1155_IMPL_VERSION": "2.5.1", + "FACTORY_IMPL": "0xF7e49F97E82cc38ACd82E303F37Fe046f5a190B5", "FACTORY_PROXY": "0x777777C338d93e2C7adf08D102d45CA7CC4Ed021", "FIXED_PRICE_SALE_STRATEGY": "0x6d28164C3CE04A190D5F9f0f8881fc807EAD975A", "MERKLE_MINT_SALE_STRATEGY": "0x5e5fD4b758076BAD940db0284b711A67E8a3B88c", - "PREMINTER_IMPL": "0x4e10791d56a6E90b4b7E2840Fa96DD4fB273F3F2", + "PREMINTER_IMPL": "0x37A7c717c3EDA58e4ec7F424B2A46934Fd8f8468", "PREMINTER_PROXY": "0x7777773606e7e46C8Ba8B98C08f5cD218e31d340", "REDEEM_MINTER_FACTORY": "0x25cFb6dd9cDE8425e781d6718a29Ccbca3F038d6", "UPGRADE_GATE": "0x0000000000000000000000000000000000000000", - "timestamp": 1700087849, - "commit": "a2700107" + "timestamp": 1700531325, + "commit": "fdd3d044" } \ No newline at end of file diff --git a/packages/protocol-deployments/package.json b/packages/protocol-deployments/package.json index 214600c03..623e4039a 100644 --- a/packages/protocol-deployments/package.json +++ b/packages/protocol-deployments/package.json @@ -1,6 +1,6 @@ { "name": "@zoralabs/protocol-deployments", - "version": "0.0.6", + "version": "0.0.7-prerelease.0", "repository": "https://github.com/ourzora/zora-protocol", "license": "MIT", "main": "./dist/index.js", diff --git a/packages/protocol-deployments/script/DeployProxiesToNewChain.s.sol b/packages/protocol-deployments/script/DeployProxiesToNewChain.s.sol index 6c4b842d6..5ab98642a 100644 --- a/packages/protocol-deployments/script/DeployProxiesToNewChain.s.sol +++ b/packages/protocol-deployments/script/DeployProxiesToNewChain.s.sol @@ -8,8 +8,9 @@ import {ZoraDeployerBase} from "../src/ZoraDeployerBase.sol"; import {Deployment} from "../src/DeploymentConfig.sol"; import {ZoraDeployerUtils} from "../src/ZoraDeployerUtils.sol"; import {DeploymentTestingUtils} from "../src/DeploymentTestingUtils.sol"; +import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; -contract DeployProxiesToNewChain is ZoraDeployerBase, DeploymentTestingUtils { +contract DeployProxiesToNewChain is ZoraDeployerBase { function run() public returns (string memory) { Deployment memory deployment = getDeployment(); @@ -31,7 +32,14 @@ contract DeployProxiesToNewChain is ZoraDeployerBase, DeploymentTestingUtils { console2.log("testing premint"); - signAndExecutePremint(deployment.preminterProxy, vm.envAddress("TEST_PREMINT_FUNDS_RECIPIENT")); + address fundsRecipient = vm.envAddress("TEST_PREMINT_FUNDS_RECIPIENT"); + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ + mintRecipient: fundsRecipient, + mintComment: "", + mintReferral: fundsRecipient + }); + + signAndExecutePremintV2(deployment.preminterProxy, vm.envAddress("TEST_PREMINT_FUNDS_RECIPIENT"), mintArguments); vm.stopBroadcast(); diff --git a/packages/protocol-deployments/script/DeployTestContracts.s.sol b/packages/protocol-deployments/script/DeployTestContracts.s.sol new file mode 100644 index 000000000..41fa930c8 --- /dev/null +++ b/packages/protocol-deployments/script/DeployTestContracts.s.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import "forge-std/Script.sol"; +import "forge-std/console2.sol"; + +import {ZoraDeployerBase} from "../src/ZoraDeployerBase.sol"; +import {Deployment} from "../src/DeploymentConfig.sol"; +import {ZoraDeployerUtils} from "../src/ZoraDeployerUtils.sol"; +import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; + +contract DeployTestContracts is ZoraDeployerBase { + function run() public returns (string memory) { + Deployment memory deployment = getDeployment(); + + vm.startBroadcast(); + + ZoraDeployerUtils.deployTestContractForVerification(deployment.factoryProxy, makeAddr("admin")); + + address fundsRecipient = vm.envAddress("DEPLOYER"); + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ + mintRecipient: fundsRecipient, + mintComment: "", + mintReferral: fundsRecipient + }); + + signAndExecutePremintV2(deployment.preminterProxy, fundsRecipient, mintArguments); + + vm.stopBroadcast(); + + // now test signing and executing premint + + return getDeploymentJSON(deployment); + } +} diff --git a/packages/protocol-deployments/src/DeploymentTestingUtils.sol b/packages/protocol-deployments/src/DeploymentTestingUtils.sol index 107bdd824..2d8645000 100644 --- a/packages/protocol-deployments/src/DeploymentTestingUtils.sol +++ b/packages/protocol-deployments/src/DeploymentTestingUtils.sol @@ -6,56 +6,138 @@ import {IMinter1155} from "@zoralabs/zora-1155-contracts/src/interfaces/IMinter1 import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; import {ZoraCreator1155PremintExecutorImpl} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol"; import {ZoraCreator1155FactoryImpl} from "@zoralabs/zora-1155-contracts/src/factory/ZoraCreator1155FactoryImpl.sol"; -import {ZoraCreator1155Attribution, ContractCreationConfig, PremintConfigV2, TokenCreationConfigV2} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155Attribution.sol"; +import {ZoraCreator1155Attribution, ContractCreationConfig, PremintConfigV2, TokenCreationConfigV2, PremintConfig, TokenCreationConfig} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155Attribution.sol"; +import {ScriptDeploymentConfig} from "./DeploymentConfig.sol"; import {ZoraCreator1155Impl} from "@zoralabs/zora-1155-contracts/src/nft/ZoraCreator1155Impl.sol"; contract DeploymentTestingUtils is Script { - function signAndExecutePremint(address premintExecutorProxyAddress, address payoutRecipient) internal { - console2.log("preminter proxy", premintExecutorProxyAddress); - + function createAndSignPremintV1( + address premintExecutorProxyAddress, + address payoutRecipient + ) + internal + returns ( + ContractCreationConfig memory contractConfig, + IZoraCreator1155PremintExecutor preminterAtProxy, + PremintConfig memory premintConfig, + bytes memory signature + ) + { (address creator, uint256 creatorPrivateKey) = makeAddrAndKey("creator"); - IZoraCreator1155PremintExecutor preminterAtProxy = IZoraCreator1155PremintExecutor(premintExecutorProxyAddress); - - IMinter1155 fixedPriceMinter = ZoraCreator1155FactoryImpl(address(preminterAtProxy.zora1155Factory())).fixedPriceMinter(); + preminterAtProxy = IZoraCreator1155PremintExecutor(premintExecutorProxyAddress); - PremintConfigV2 memory premintConfig = PremintConfigV2({ - tokenConfig: TokenCreationConfigV2({ + premintConfig = PremintConfig({ + tokenConfig: TokenCreationConfig({ tokenURI: "blah.token", maxSupply: 10, maxTokensPerAddress: 5, pricePerToken: 0, mintStart: 0, mintDuration: 0, + royaltyMintSchedule: 0, royaltyBPS: 100, - payoutRecipient: payoutRecipient, - fixedPriceMinter: address(fixedPriceMinter), - createReferral: address(0) + royaltyRecipient: payoutRecipient, + fixedPriceMinter: address(ZoraCreator1155FactoryImpl(address(preminterAtProxy.zora1155Factory())).fixedPriceMinter()) }), - uid: 100, + uid: 101, version: 0, deleted: false }); // now interface with proxy preminter - sign and execute the premint - ContractCreationConfig memory contractConfig = ContractCreationConfig({contractAdmin: creator, contractName: "blah", contractURI: "blah.contract"}); + contractConfig = ContractCreationConfig({contractAdmin: creator, contractName: "blahb", contractURI: "blah.contract"}); address deterministicAddress = preminterAtProxy.getContractAddress(contractConfig); + signature = signPremint(premintConfig, deterministicAddress, creatorPrivateKey); + } + + function signAndExecutePremintV1( + address premintExecutorProxyAddress, + address payoutRecipient, + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments + ) internal { + ( + ContractCreationConfig memory contractConfig, + IZoraCreator1155PremintExecutor preminterAtProxy, + PremintConfig memory premintConfig, + bytes memory signature + ) = createAndSignPremintV1(premintExecutorProxyAddress, payoutRecipient); + uint256 quantityToMint = 1; - address mintRecipient = creator; + // execute the premint + IZoraCreator1155PremintExecutor.PremintResult memory premintResult = preminterAtProxy.premintV1{value: mintFee(quantityToMint)}( + contractConfig, + premintConfig, + signature, + quantityToMint, + mintArguments + ); + + require(ZoraCreator1155Impl(premintResult.contractAddress).delegatedTokenId(premintConfig.uid) == premintResult.tokenId, "token id mismatch"); + } + + function createAndSignPremintV2( + address premintExecutorProxyAddress, + address payoutRecipient + ) + internal + returns ( + ContractCreationConfig memory contractConfig, + IZoraCreator1155PremintExecutor preminterAtProxy, + PremintConfigV2 memory premintConfig, + bytes memory signature + ) + { + (address creator, uint256 creatorPrivateKey) = makeAddrAndKey("creator"); + preminterAtProxy = IZoraCreator1155PremintExecutor(premintExecutorProxyAddress); - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: mintRecipient, - mintComment: "", - mintReferral: address(0) + premintConfig = PremintConfigV2({ + tokenConfig: TokenCreationConfigV2({ + tokenURI: "blah.token", + maxSupply: 100, + maxTokensPerAddress: 50, + pricePerToken: 0, + mintStart: 0, + mintDuration: 0, + royaltyBPS: 100, + payoutRecipient: payoutRecipient, + fixedPriceMinter: address(ZoraCreator1155FactoryImpl(address(preminterAtProxy.zora1155Factory())).fixedPriceMinter()), + createReferral: creator + }), + uid: 100, + version: 0, + deleted: false }); - bytes memory signature = signPremint(premintConfig, deterministicAddress, creatorPrivateKey); + // now interface with proxy preminter - sign and execute the premint + contractConfig = ContractCreationConfig({contractAdmin: creator, contractName: "blahb", contractURI: "blah.contract"}); + address deterministicAddress = preminterAtProxy.getContractAddress(contractConfig); + + signature = signPremint(premintConfig, deterministicAddress, creatorPrivateKey); + } + function signAndExecutePremintV2( + address premintExecutorProxyAddress, + address payoutRecipient, + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments + ) internal { + ( + ContractCreationConfig memory contractConfig, + IZoraCreator1155PremintExecutor preminterAtProxy, + PremintConfigV2 memory premintConfig, + bytes memory signature + ) = createAndSignPremintV2(premintExecutorProxyAddress, payoutRecipient); + + uint256 quantityToMint = 1; // execute the premint - uint256 tokenId = preminterAtProxy.premintV2{value: 0.000777 ether}(contractConfig, premintConfig, signature, quantityToMint, mintArguments).tokenId; + uint256 tokenId = preminterAtProxy + .premintV2{value: mintFee(quantityToMint)}(contractConfig, premintConfig, signature, quantityToMint, mintArguments).tokenId; - require(ZoraCreator1155Impl(deterministicAddress).delegatedTokenId(premintConfig.uid) == tokenId, "token id not created for uid"); + require( + ZoraCreator1155Impl(preminterAtProxy.getContractAddress(contractConfig)).delegatedTokenId(premintConfig.uid) == tokenId, + "token id not created for uid" + ); } function signPremint(PremintConfigV2 memory premintConfig, address deterministicAddress, uint256 privateKey) private view returns (bytes memory signature) { @@ -67,4 +149,18 @@ contract DeploymentTestingUtils is Script { (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest); return abi.encodePacked(r, s, v); } + + function mintFee(uint256 quantityToMint) internal pure returns (uint256) { + return quantityToMint * 0.000777 ether; + } + + function signPremint(PremintConfig memory premintConfig, address deterministicAddress, uint256 privateKey) private view returns (bytes memory signature) { + bytes32 signatureVersion = ZoraCreator1155Attribution.HASHED_VERSION_1; + bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); + // sign the premint + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, deterministicAddress, signatureVersion, block.chainid); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(privateKey, digest); + return abi.encodePacked(r, s, v); + } } diff --git a/packages/protocol-deployments/src/DeterministicDeployerScript.sol b/packages/protocol-deployments/src/DeterministicDeployerScript.sol index c7a2abf0f..c498bd993 100644 --- a/packages/protocol-deployments/src/DeterministicDeployerScript.sol +++ b/packages/protocol-deployments/src/DeterministicDeployerScript.sol @@ -199,13 +199,9 @@ contract DeterministicDeployerScript is Script { bytes32 proxyDeployerSalt = params.proxyDeployerSalt; bytes memory proxyDeployerCreationCode = params.proxyDeployerCreationCode; - if (ZoraDeployerUtils.IMMUTABLE_CREATE2_FACTORY.hasBeenDeployed(proxyDeployerAddress)) { - factoryDeployer = DeterministicProxyDeployer(proxyDeployerAddress); - } else { - factoryDeployer = DeterministicProxyDeployer(ZoraDeployerUtils.IMMUTABLE_CREATE2_FACTORY.safeCreate2(proxyDeployerSalt, proxyDeployerCreationCode)); - } + ZoraDeployerUtils.getOrImmutable2Create(proxyDeployerAddress, proxyDeployerSalt, proxyDeployerCreationCode); - if (address(factoryDeployer) != params.proxyDeployerAddress) revert MismatchedAddress(params.proxyDeployerAddress, address(factoryDeployer)); + factoryDeployer = DeterministicProxyDeployer(proxyDeployerAddress); } function deployDeterministicProxy(string memory proxyName, address implementation, address owner, uint256 chain) internal returns (address) { diff --git a/packages/protocol-deployments/src/ZoraDeployerBase.sol b/packages/protocol-deployments/src/ZoraDeployerBase.sol index 23f19eb68..bc9ff4373 100644 --- a/packages/protocol-deployments/src/ZoraDeployerBase.sol +++ b/packages/protocol-deployments/src/ZoraDeployerBase.sol @@ -13,9 +13,10 @@ import {ZoraDeployerUtils} from "./ZoraDeployerUtils.sol"; import {IMinter1155} from "@zoralabs/zora-1155-contracts/src/interfaces/IMinter1155.sol"; import {DeterministicDeployerScript} from "./DeterministicDeployerScript.sol"; import {ZoraCreator1155FactoryImpl} from "@zoralabs/zora-1155-contracts/src/factory/ZoraCreator1155FactoryImpl.sol"; +import {DeploymentTestingUtils} from "./DeploymentTestingUtils.sol"; /// @notice Deployment drops for base where -abstract contract ZoraDeployerBase is ScriptDeploymentConfig, DeterministicDeployerScript { +abstract contract ZoraDeployerBase is DeploymentTestingUtils, ScriptDeploymentConfig, DeterministicDeployerScript { using stdJson for string; /// @notice File used for demo metadata on verification test mint diff --git a/packages/protocol-deployments/src/ZoraDeployerUtils.sol b/packages/protocol-deployments/src/ZoraDeployerUtils.sol index 0e71b4ec3..cc05151a8 100644 --- a/packages/protocol-deployments/src/ZoraDeployerUtils.sol +++ b/packages/protocol-deployments/src/ZoraDeployerUtils.sol @@ -17,6 +17,7 @@ import {ZoraCreatorRedeemMinterFactory} from "@zoralabs/zora-1155-contracts/src/ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; import {ICreatorRoyaltiesControl} from "@zoralabs/zora-1155-contracts/src/interfaces/ICreatorRoyaltiesControl.sol"; import {UpgradeGate} from "@zoralabs/zora-1155-contracts/src/upgrades/UpgradeGate.sol"; +import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; struct Create2Deployment { address deployerAddress; @@ -117,12 +118,13 @@ library ZoraDeployerUtils { // create preminter implementation bytes memory creationCode = abi.encodePacked(type(ZoraCreator1155PremintExecutorImpl).creationCode, abi.encode(factoryProxyAddress)); - address preminterImplementation = IMMUTABLE_CREATE2_FACTORY.safeCreate2( - bytes32(0x0000000000000000000000000000000000000000668d7f9ec18e35000dbaba0e), - creationCode - ); + bytes32 salt = bytes32(0x0000000000000000000000000000000000000000668d7f9ec18e35000dbaba0e); + + address determinsticAddress = ZoraDeployerUtils.getImmutableCreate2Address(salt, creationCode); - return preminterImplementation; + ZoraDeployerUtils.getOrImmutable2Create(determinsticAddress, salt, creationCode); + + return determinsticAddress; } function deterministicFactoryDeployerAddress() internal view returns (address) { @@ -152,6 +154,24 @@ library ZoraDeployerUtils { ); } + error MismatchedAddress(address expected, address actual); + + function getImmutableCreate2Address(bytes32 salt, bytes memory creationCode) internal pure returns (address) { + return Create2.computeAddress(salt, keccak256(creationCode), address(IMMUTABLE_CREATE2_FACTORY)); + } + + function getOrImmutable2Create(address expectedAddress, bytes32 salt, bytes memory creationCode) internal returns (bool contractWasCreated) { + if (IMMUTABLE_CREATE2_FACTORY.hasBeenDeployed(expectedAddress)) { + return false; + } else { + address result = ZoraDeployerUtils.IMMUTABLE_CREATE2_FACTORY.safeCreate2(salt, creationCode); + + if (result != expectedAddress) revert MismatchedAddress(expectedAddress, result); + + return true; + } + } + /// @notice Deploy a test contract for etherscan auto-verification /// @param factoryProxy Factory address to use /// @param admin Admin owner address to use @@ -174,25 +194,18 @@ library ZoraDeployerUtils { ); } - function getUpgradeCalldata(Deployment memory deployment) internal returns (bytes memory upgradeCalldata) { - // create 1155 proxy from deployment factory proxy address - ZoraCreator1155FactoryImpl factory = ZoraCreator1155FactoryImpl(deployment.factoryProxy); - - address owner = factory.owner(); - + function getUpgradeCalldata(address targetImpl) internal pure returns (bytes memory upgradeCalldata) { // simulate upgrade call - upgradeCalldata = abi.encodeWithSelector(factory.upgradeTo.selector, deployment.factoryImpl); + upgradeCalldata = abi.encodeWithSelector(UUPSUpgradeable.upgradeTo.selector, targetImpl); } - function simulateUpgrade(Deployment memory deployment) internal returns (address target, bytes memory upgradeCalldata) { + function simulateUpgrade(address targetProxy, address targetImpl) internal returns (bytes memory upgradeCalldata) { // console log update information - upgradeCalldata = getUpgradeCalldata(deployment); + upgradeCalldata = getUpgradeCalldata(targetImpl); - target = deployment.factoryProxy; // upgrade the factory proxy to the new implementation - - (bool success, ) = target.call(upgradeCalldata); + (bool success, ) = targetProxy.call(upgradeCalldata); require(success, "upgrade failed"); } diff --git a/packages/protocol-deployments/test/UpgradesTest.t.sol b/packages/protocol-deployments/test/UpgradesTest.t.sol index b74f735e8..9195eebb2 100644 --- a/packages/protocol-deployments/test/UpgradesTest.t.sol +++ b/packages/protocol-deployments/test/UpgradesTest.t.sol @@ -3,10 +3,13 @@ pragma solidity 0.8.17; import "forge-std/Test.sol"; import {ZoraCreator1155FactoryImpl} from "@zoralabs/zora-1155-contracts/src/factory/ZoraCreator1155FactoryImpl.sol"; +import {ZoraCreator1155PremintExecutorImpl} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol"; import {ForkDeploymentConfig, Deployment, ChainConfig} from "../src/DeploymentConfig.sol"; import {ZoraDeployerUtils} from "../src/ZoraDeployerUtils.sol"; +import {DeploymentTestingUtils} from "../src/DeploymentTestingUtils.sol"; +import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; -contract UpgradesTest is ForkDeploymentConfig, Test { +contract UpgradesTest is ForkDeploymentConfig, DeploymentTestingUtils, Test { /// @notice gets the chains to do fork tests on, by reading environment var FORK_TEST_CHAINS. /// Chains are by name, and must match whats under `rpc_endpoints` in the foundry.toml function getForkTestChains() private view returns (string[] memory result) { @@ -18,8 +21,39 @@ contract UpgradesTest is ForkDeploymentConfig, Test { } } + function determine1155Upgrade(Deployment memory deployment) private view returns (bool upgradeNeeded, address targetProxy, address targetImpl) { + targetProxy = deployment.factoryProxy; + targetImpl = deployment.factoryImpl; + address currentImplementation = ZoraCreator1155FactoryImpl(targetProxy).implementation(); + + upgradeNeeded = targetImpl != currentImplementation; + } + + function determinePreminterUpgrade(Deployment memory deployment) private returns (bool upgradeNeeded, address targetProxy, address targetImpl) { + targetProxy = deployment.preminterProxy; + targetImpl = deployment.preminterImpl; + + // right now we cannot call "implementation" on contract since it doesn't exist yet, so we check if deployed impl meets the v1 impl we know + address preminterV1ImplAddress = 0x6E2AbBcd82935bFC68A1d5d2c96372b13b65eD9C; + + // if the target impl is still the v1 impl, it didnt have a method to check impl so we can't call it, also we know its still v1 impl so we don't need to upgrade + if (targetImpl == preminterV1ImplAddress) { + upgradeNeeded = false; + } else { + // if doesnt have implementation method, then we know upgrade is needed + (bool success, bytes memory data) = deployment.preminterProxy.call(abi.encodePacked(ZoraCreator1155PremintExecutorImpl.implementation.selector)); + + if (!success) { + upgradeNeeded = true; + } else { + address currentImplementation = abi.decode(data, (address)); + upgradeNeeded = currentImplementation != targetImpl; + } + } + } + /// @notice checks which chains need an upgrade, simulated the upgrade, and gets the upgrade calldata - function simulate1155UpgradeOnFork(string memory chainName) private { + function simulateUpgradeOnFork(string memory chainName) private { // create and select the fork, which will be used for all subsequent calls vm.createSelectFork(vm.rpcUrl(chainName)); @@ -29,32 +63,68 @@ contract UpgradesTest is ForkDeploymentConfig, Test { address creator = makeAddr("creator"); - vm.startPrank(chainConfig.factoryOwner); + (bool is1155UpgradeNeeded, address targetProxy1155, address targetImpl1155) = determine1155Upgrade(deployment); + (bool preminterUpgradeNeeded, address targetPreminterProxy, address targetPremintImpl) = determinePreminterUpgrade(deployment); - address currentImplementation = ZoraCreator1155FactoryImpl(deployment.factoryProxy).implementation(); + if (!is1155UpgradeNeeded && !preminterUpgradeNeeded) { + return; + } - if (currentImplementation != deployment.factoryImpl) { - address targetImpl = deployment.factoryImpl; - (address target, bytes memory upgradeCalldata) = ZoraDeployerUtils.simulateUpgrade(deployment); + console2.log("====== upgrade needed ======"); + console2.log("chain:", chainName); + console2.log("upgrade owner:", chainConfig.factoryOwner); - ZoraDeployerUtils.deployTestContractForVerification(deployment.factoryProxy, creator); + if (is1155UpgradeNeeded) { + console2.log("-- 1155 upgrade needed --"); + vm.prank(chainConfig.factoryOwner); + bytes memory factory1155UpgradeCalldata = ZoraDeployerUtils.simulateUpgrade(targetProxy1155, targetImpl1155); + vm.prank(creator); + ZoraDeployerUtils.deployTestContractForVerification(targetProxy1155, creator); - console2.log("=== 1155 upgrade needed ==="); - console2.log("chain:", chainName); - console2.log("upgrade owner:", chainConfig.factoryOwner); - console2.log("upgrade target:", target); + console2.log("1155 upgrade target:", targetProxy1155); console2.log("upgrade calldata:"); - console.logBytes(upgradeCalldata); - console2.log("upgrade to address:", targetImpl); - console2.log("upgrade to version:", ZoraCreator1155FactoryImpl(targetImpl).contractVersion()); - console2.log("=====================\n"); + console.logBytes(factory1155UpgradeCalldata); + console2.log("upgrade to address:", targetImpl1155); + console2.log("upgrade to version:", ZoraCreator1155FactoryImpl(targetImpl1155).contractVersion()); + console2.log("------------------------"); } + + // hack - for now, only check on zora sepolia or goerli + if (preminterUpgradeNeeded) { + console2.log("-- preminter upgrade needed --"); + console2.log("preminter upgrade target:", targetPreminterProxy); + vm.prank(chainConfig.factoryOwner); + bytes memory preminterUpgradeCalldata = ZoraDeployerUtils.simulateUpgrade(deployment.preminterProxy, deployment.preminterImpl); + + address collector = makeAddr("collector"); + address mintReferral = makeAddr("referral"); + vm.deal(collector, 10 ether); + + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ + mintRecipient: collector, + mintComment: "", + mintReferral: mintReferral + }); + + vm.startPrank(collector); + signAndExecutePremintV1(targetPreminterProxy, makeAddr("payoutRecipientA"), mintArguments); + signAndExecutePremintV2(targetPreminterProxy, makeAddr("payoutRecipientB"), mintArguments); + + vm.stopPrank(); + + console2.log("upgrade calldata:"); + console.logBytes(preminterUpgradeCalldata); + console2.log("upgrade to address:", targetPremintImpl); + console2.log("------------------------"); + } + + console2.log("=================\n"); } function test_fork_simulateUpgrades() external { string[] memory forkTestChains = getForkTestChains(); for (uint256 i = 0; i < forkTestChains.length; i++) { - simulate1155UpgradeOnFork(forkTestChains[i]); + simulateUpgradeOnFork(forkTestChains[i]); } } } diff --git a/packages/protocol-sdk/CHANGELOG.md b/packages/protocol-sdk/CHANGELOG.md index 949addb18..b6464efb9 100644 --- a/packages/protocol-sdk/CHANGELOG.md +++ b/packages/protocol-sdk/CHANGELOG.md @@ -1,5 +1,13 @@ # @zoralabs/protocol-sdk +## 0.3.3-prerelease.0 + +### Patch Changes + +- Updated dependencies [dba9bb0] +- Updated dependencies [4c4ae23] + - @zoralabs/protocol-deployments@0.0.7-prerelease.0 + ## 0.3.2 ### Patch Changes diff --git a/packages/protocol-sdk/package.json b/packages/protocol-sdk/package.json index 43072386b..25275ad15 100644 --- a/packages/protocol-sdk/package.json +++ b/packages/protocol-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@zoralabs/protocol-sdk", - "version": "0.3.2", + "version": "0.3.3-prerelease.0", "repository": "https://github.com/ourzora/zora-protocol", "license": "MIT", "main": "./dist/index.js", @@ -15,7 +15,7 @@ "lint": "prettier --check 'src/**/*.ts'" }, "dependencies": { - "@zoralabs/protocol-deployments": "*", + "@zoralabs/protocol-deployments": "0.0.7-prerelease.0", "abitype": "^0.8.7", "vite": "4.5.0" },