Skip to content

Commit ddcea1d

Browse files
authored
Deploy MagicDropV1.0.2 (#187)
1 parent cd314bc commit ddcea1d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+5714
-168
lines changed

README.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,33 +49,35 @@ The composability of the stages is generic enough to enable flexible and complic
4949
| ERC1155M | The basic minting contract based on ERC1155. |
5050
| MagicDropTokenImplRegistry | The implementation registry for MagicDrop contracts. |
5151
| MagicDropCloneFactory | The factory contract for cloning MagicDrop contracts. |
52-
| ERC721MInitializableV1_0_1 | The initializable implementation for ERC721M. |
53-
| ERC721CMInitializableV1_0_1 | The initializable implementation for ERC721CM. |
54-
| ERC1155MInitializableV1_0_1 | The initializable implementation for ERC1155M. |
52+
| ERC721MInitializableV1_0_2 | The initializable implementation for ERC721M. |
53+
| ERC721CMInitializableV1_0_2 | The initializable implementation for ERC721CM. |
54+
| ERC1155MInitializableV1_0_2 | The initializable implementation for ERC1155M. |
5555
| ERC721MagicDropCloneable | A simple cloneable implementation of ERC721 with public and private stages. |
5656
| ERC1155MagicDropCloneable | A simple cloneable implementation of ERC1155 with public and private stages. |
5757

5858
## Deployment Address & Salts (Non-ZKSync Chains)
5959
| Name | Address | Salt |
6060
|-----------------------------|-------------------------------------------|-----------------------------------------|
61-
| MagicDropTokenImplRegistry | 0x00000000caF1E3978e291c5Fb53FeedB957eC146 |0x78c643228c532b1aee1930fedd4a4b0e6d3d8723987c0809d76a222b0d59b461 |
62-
| MagicDropCloneFactory | 0x000000009e44eBa131196847C685F20Cd4b68aC4 | 0xd8c5a3057ccf31c5fd5cee4e4a5ad9005d0a9a7f4983365010b8785805b44eb1
63-
| ERC721MInitializableV1_0_1 | 0x000000f463fc9825682F484D3D5cDF5Aa6B16f59 | 0x403062abd5dc450d08ecd8aaaa1ec0ddca9c82f127cb4c45f34202ea27b6a4b1
64-
| ERC721CMInitializableV1_0_1 | 0x000000c2b388C25a544258E4d8EEDD31e0E59611 | 0x68e3c267b3ddb63ff8e85f7d593c2e041710a2dd142f07b0c8f5020f46284a22
65-
| ERC1155MInitializableV1_0_1 | 0x000000d076bc17cb89e11825c060d2f329fc9083 | 0x5549e6a920f24bb3665381d9b0174fe9a0337e0eb771ee600da7b0cf1b63fa24
66-
| ERC721MagicDropCloneable | 0x000000FB0f19714B7B75A73F8484061aCde05bDC | 0xa63b2c7e4254d68d54ef7eb831dec5fb7ac7fd23aa5beb68ae12235abd33823d
67-
| ERC1155MagicDropCloneable | 0x00000089adfC1a3CAa6A5a6C869E2Dfdd22F7E13 | 0xf8c38b152c86dd9aeafb566f64b579ce3332f118fb6ec058c5e1deecc9f5b7d8
61+
| MagicDropTokenImplRegistry Implementation | 0x00000000a5837C1EeD8145A831c8e69C81112da0 |0x38f7e43d7b4b0493bb35918ede2a002486e822173f68e1c7c4e9a7a9af451ac2 |
62+
| MagicDropTokenImplRegistry Proxy | 0x000000000e447e71b2EC36CD62048Dd2a1Cd0a57 |0xc9b080cde9332d8feb50c92fb198b503b9f90ca09a83429194ad8ef8928aca79 |
63+
| MagicDropCloneFactory Implementation | 0x0000000067502A08Cc4307672A1d4dc48f08a444 | 0x3ad1a60297b1c9e825cdf7e9452a4e9b109c404a4f9f8069e77c6a916096aa0a
64+
| MagicDropCloneFactory Proxy | 0x00000000bEa935F8315156894Aa4a45D3c7a0075 | 0xdcb4ae77dc30804459a9a9bcc9bb1a271049553639fdf5c47e4a6a0c3fd97c7b
65+
| ERC721MInitializableV1_0_2 | 0x00000000df57029C0628F946f37a4CBaa417d1d9 | 0x56c09d9f6a0b39a14e082b2ee9329f2d07e0d2a57900d4d24797d0bb95f521a9
66+
| ERC721CMInitializableV1_0_2 | 0x00000000E7aEc12181Cb4C1D8474634e3fCEe456 | 0x958674b386d1433f28e925ecd473b9ff8ca9cf8b1d4e5a0f417a1d731da7c565
67+
| ERC1155MInitializableV1_0_2 | 0x0000000055E6c029AD855Af4a30a0f0fA73b6c5E | 0xab66c31281be63f79c25e30ef51a6293b25eea4a86beb47b323525497c4612af
68+
| ERC721MagicDropCloneable | 0x000000002A1351440079144BF9e40869092576f1 | 0x802853f87f3efa7109bd4a3b7b9ac3daf75f98a3fc97a8fce04d8c17ed2e85c7
69+
| ERC1155MagicDropCloneable | 0x00000000b03D92E78432FB3377A171655Afdb5bb | 0x0b6a866fa283524661d3b4a0f7f5b85636819e32e1384b395d5454edc7d9299a
6870

6971
### Abstract Deployed Addresses
7072
| Contract | Address |
7173
|-----------------------------|-------------------------------------------|
72-
| MagicDropTokenImplRegistry | 0x9b60ad31F145ec7EE3c559153bB57928B65C0F87 |
73-
| MagicDropCloneFactory | 0x4a08d3F6881c4843232EFdE05baCfb5eAaB35d19 |
74-
| ERC721MInitializableV1_0_1 | 0xb6049C5eaD766E6BBe26F505c01C329B899d8f55 |
75-
| ERC721CMInitializableV1_0_1 | 0x42C25f4165a4310Bd029323dAFc7254546cC97f9 |
76-
| ERC1155MInitializableV1_0_1 | 0x13405abe50EFE5b564B40E1f52F5598C845C4aCD |
77-
| ERC721MagicDropCloneable | 0xc7E86760d1A533d1251585710F589AFc14A30618 |
78-
| ERC1155MagicDropCloneable | 0xEC489BC18E4F08f460aff3b4a5dB65e562DA5c32 |
74+
| MagicDropTokenImplRegistry | 0x17c9921D99c1Fa6d3dC992719DA1123dCb2CaedA |
75+
| MagicDropCloneFactory | 0x01c1C2f5271aDeA338dAfba77121Fc20B5176620 |
76+
| ERC721MInitializableV1_0_2 | 0x92578FCA9eaBEe0f5Bb3E5ea8e291612B75C8748 |
77+
| ERC721CMInitializableV1_0_2 | 0x96e5Ed4446E7652C4306290099C6760fA2332EeC |
78+
| ERC1155MInitializableV1_0_2 | 0x3Cd56fB82B34Bf4AD8f94c29EeDDB7bC132E41De |
79+
| ERC721MagicDropCloneable | 0xd929CE55a5Ea307FED843E145aFbcC261e2691d8 |
80+
| ERC1155MagicDropCloneable | 0xDb56d1512C0E885B9b1Ddf704eA83C82654a5B61 |
7981

8082

8183
### Supported Chains
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.22;
3+
4+
import {Ownable} from "solady/src/auth/Ownable.sol";
5+
import {TokenStandard} from "contracts/common/Structs.sol";
6+
import {MagicDropTokenImplRegistry} from "contracts/registry/MagicDropTokenImplRegistry.sol";
7+
import {Proxy} from "contracts/factory/zksync/Proxy.sol";
8+
9+
/// @title MagicDropCloneFactory
10+
/// @notice A factory contract for creating and managing clones of MagicDrop contracts
11+
/// @dev This contract uses the UUPS proxy pattern
12+
/// @dev ZKsync compatible version
13+
contract MagicDropCloneFactory is Ownable {
14+
/*==============================================================
15+
= STORAGE =
16+
==============================================================*/
17+
18+
/// @notice The registry contract
19+
MagicDropTokenImplRegistry private _registry;
20+
21+
/*==============================================================
22+
= CONSTANTS =
23+
==============================================================*/
24+
25+
bytes4 private constant INITIALIZE_SELECTOR = bytes4(keccak256("initialize(string,string,address,uint256)"));
26+
27+
/*==============================================================
28+
= EVENTS =
29+
==============================================================*/
30+
31+
event MagicDropFactoryInitialized();
32+
event NewContractInitialized(
33+
address contractAddress,
34+
address initialOwner,
35+
uint32 implId,
36+
TokenStandard standard,
37+
string name,
38+
string symbol,
39+
uint256 mintFee
40+
);
41+
event Withdrawal(address to, uint256 amount);
42+
43+
/*==============================================================
44+
= ERRORS =
45+
==============================================================*/
46+
47+
error InitializationFailed();
48+
error RegistryAddressCannotBeZero();
49+
error InsufficientDeploymentFee();
50+
error WithdrawalFailed();
51+
error InitialOwnerCannotBeZero();
52+
error NewImplementationCannotBeZero();
53+
54+
/*==============================================================
55+
= INITIALIZER =
56+
==============================================================*/
57+
58+
/// @dev MagicDropCloneFactory constructor.
59+
/// @param initialOwner The address of the initial owner
60+
/// @param registry The address of the registry contract
61+
constructor(address initialOwner, address registry) {
62+
if (registry == address(0)) {
63+
revert RegistryAddressCannotBeZero();
64+
}
65+
66+
_registry = MagicDropTokenImplRegistry(registry);
67+
_initializeOwner(initialOwner);
68+
69+
emit MagicDropFactoryInitialized();
70+
}
71+
72+
/*==============================================================
73+
= PUBLIC WRITE METHODS =
74+
==============================================================*/
75+
76+
/// @notice Creates a new deterministic clone of a MagicDrop contract
77+
/// @param name The name of the new contract
78+
/// @param symbol The symbol of the new contract
79+
/// @param standard The token standard of the new contract
80+
/// @param initialOwner The initial owner of the new contract
81+
/// @param implId The implementation ID
82+
/// @param salt A unique salt for deterministic address generation
83+
/// @return The address of the newly created contract
84+
function createContractDeterministic(
85+
string calldata name,
86+
string calldata symbol,
87+
TokenStandard standard,
88+
address payable initialOwner,
89+
uint32 implId,
90+
bytes32 salt
91+
) external payable returns (address) {
92+
address impl;
93+
// Retrieve the implementation address from the registry
94+
if (implId == 0) {
95+
impl = _registry.getDefaultImplementation(standard);
96+
} else {
97+
impl = _registry.getImplementation(standard, implId);
98+
}
99+
100+
if (initialOwner == address(0)) {
101+
revert InitialOwnerCannotBeZero();
102+
}
103+
104+
// Retrieve the deployment fee for the implementation and ensure the caller has sent the correct amount
105+
uint256 deploymentFee = _registry.getDeploymentFee(standard, implId);
106+
if (msg.value < deploymentFee) {
107+
revert InsufficientDeploymentFee();
108+
}
109+
110+
// Retrieve the mint fee for the implementation
111+
uint256 mintFee = _registry.getMintFee(standard, implId);
112+
113+
// Create a unique salt by combining original salt with chain ID and sender
114+
bytes32 _salt = keccak256(abi.encode(salt, block.chainid, msg.sender));
115+
// Create a deterministic clone of the implementation contract
116+
address instance = address(new Proxy{salt: _salt}(impl));
117+
118+
// Initialize the newly created contract
119+
(bool success,) =
120+
instance.call(abi.encodeWithSelector(INITIALIZE_SELECTOR, name, symbol, initialOwner, mintFee));
121+
if (!success) {
122+
revert InitializationFailed();
123+
}
124+
125+
emit NewContractInitialized({
126+
contractAddress: instance,
127+
initialOwner: initialOwner,
128+
implId: implId,
129+
standard: standard,
130+
name: name,
131+
symbol: symbol,
132+
mintFee: mintFee
133+
});
134+
135+
return instance;
136+
}
137+
138+
/// @notice Creates a new clone of a MagicDrop contract
139+
/// @param name The name of the new contract
140+
/// @param symbol The symbol of the new contract
141+
/// @param standard The token standard of the new contract
142+
/// @param initialOwner The initial owner of the new contract
143+
/// @param implId The implementation ID
144+
/// @return The address of the newly created contract
145+
function createContract(
146+
string calldata name,
147+
string calldata symbol,
148+
TokenStandard standard,
149+
address payable initialOwner,
150+
uint32 implId
151+
) external payable returns (address) {
152+
address impl;
153+
// Retrieve the implementation address from the registry
154+
if (implId == 0) {
155+
impl = _registry.getDefaultImplementation(standard);
156+
} else {
157+
impl = _registry.getImplementation(standard, implId);
158+
}
159+
160+
if (initialOwner == address(0)) {
161+
revert InitialOwnerCannotBeZero();
162+
}
163+
164+
// Retrieve the deployment fee for the implementation and ensure the caller has sent the correct amount
165+
uint256 deploymentFee = _registry.getDeploymentFee(standard, implId);
166+
if (msg.value < deploymentFee) {
167+
revert InsufficientDeploymentFee();
168+
}
169+
170+
// Retrieve the mint fee for the implementation
171+
uint256 mintFee = _registry.getMintFee(standard, implId);
172+
173+
// Create a non-deterministic clone of the implementation contract
174+
address instance = address(new Proxy(impl));
175+
176+
// Initialize the newly created contract
177+
(bool success,) =
178+
instance.call(abi.encodeWithSelector(INITIALIZE_SELECTOR, name, symbol, initialOwner, mintFee));
179+
if (!success) {
180+
revert InitializationFailed();
181+
}
182+
183+
emit NewContractInitialized({
184+
contractAddress: instance,
185+
initialOwner: initialOwner,
186+
implId: implId,
187+
standard: standard,
188+
name: name,
189+
symbol: symbol,
190+
mintFee: mintFee
191+
});
192+
193+
return instance;
194+
}
195+
196+
/*==============================================================
197+
= PUBLIC VIEW METHODS =
198+
==============================================================*/
199+
200+
/// @notice Retrieves the address of the registry contract
201+
/// @return The address of the registry contract
202+
function getRegistry() external view returns (address) {
203+
return address(_registry);
204+
}
205+
206+
/*==============================================================
207+
= ADMIN OPERATIONS =
208+
==============================================================*/
209+
210+
/// @notice Withdraws the contract's balance
211+
function withdraw(address to) external onlyOwner {
212+
(bool success,) = to.call{value: address(this).balance}("");
213+
if (!success) {
214+
revert WithdrawalFailed();
215+
}
216+
217+
emit Withdrawal(to, address(this).balance);
218+
}
219+
220+
/// @dev Overriden to prevent double-initialization of the owner.
221+
function _guardInitializeOwner() internal pure virtual override returns (bool) {
222+
return true;
223+
}
224+
225+
/// @notice Receives ETH
226+
receive() external payable {}
227+
228+
/// @notice Fallback function to receive ETH
229+
fallback() external payable {}
230+
}

contracts/factory/zksync/Proxy.sol

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.22;
3+
4+
/// @title Proxy
5+
/// @notice ZKsync proxy replacement for OZ ERC1167 clones
6+
/// @dev https://github.com/zkSync-Community-Hub/zksync-developers/discussions/561#discussioncomment-9887461
7+
contract Proxy {
8+
address immutable implementation;
9+
10+
constructor(address _implementation) {
11+
implementation = _implementation;
12+
}
13+
14+
fallback() external payable {
15+
address impl = implementation;
16+
assembly {
17+
// The pointer to the free memory slot
18+
let ptr := mload(0x40)
19+
// Copy function signature and arguments from calldata at zero position into memory at pointer position
20+
calldatacopy(ptr, 0, calldatasize())
21+
// Delegatecall method of the implementation contract returns 0 on error
22+
let result := delegatecall(gas(), impl, ptr, calldatasize(), 0, 0)
23+
// Get the size of the last return data
24+
let size := returndatasize()
25+
// Copy the size length of bytes from return data at zero position to pointer position
26+
returndatacopy(ptr, 0, size)
27+
// Depending on the result value
28+
switch result
29+
case 0 {
30+
// End execution and revert state changes
31+
revert(ptr, size)
32+
}
33+
default {
34+
// Return data with length of size at pointers position
35+
return(ptr, size)
36+
}
37+
}
38+
}
39+
}

contracts/nft/erc1155m/clones/ERC1155MagicDropCloneable.sol

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,7 @@ contract ERC1155MagicDropCloneable is ERC1155MagicDropMetadataCloneable {
276276
publicStage: _publicStages[tokenId],
277277
payoutRecipient: _payoutRecipient,
278278
royaltyRecipient: _royaltyReceiver,
279-
royaltyBps: _royaltyBps,
280-
mintFee: mintFee
279+
royaltyBps: _royaltyBps
281280
});
282281

283282
return newConfig;
@@ -504,7 +503,7 @@ contract ERC1155MagicDropCloneable is ERC1155MagicDropMetadataCloneable {
504503
/// @dev Useful for external tools or metadata standards.
505504
/// @return The contract name and version strings.
506505
function contractNameAndVersion() public pure returns (string memory, string memory) {
507-
return ("ERC1155MagicDropCloneable", "1.0.0");
506+
return ("ERC1155MagicDropCloneable", "1.0.2");
508507
}
509508

510509
/*==============================================================

contracts/nft/erc1155m/clones/Types.sol

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,4 @@ struct SetupConfig {
4646
address royaltyRecipient;
4747
/// @dev The royalty basis points of the token.
4848
uint96 royaltyBps;
49-
/// @dev The mint fee of the token.
50-
uint256 mintFee;
5149
}

0 commit comments

Comments
 (0)