Contract Name:
MintpadFactory
Contract Source Code:
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/Clones.sol)
pragma solidity ^0.8.0;
/**
* @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
* deploying minimal proxy contracts, also known as "clones".
*
* > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
* > a minimal bytecode implementation that delegates all calls to a known, fixed address.
*
* The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
* (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
* deterministic method.
*
* _Available since v3.4._
*/
library Clones {
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create opcode, which should never revert.
*/
function clone(address implementation) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
// Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
// of the `implementation` address with the bytecode before the address.
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
// Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create(0, 0x09, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy
* the clone. Using the same `implementation` and `salt` multiple time will revert, since
* the clones cannot be deployed twice at the same address.
*/
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
// Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
// of the `implementation` address with the bytecode before the address.
mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
// Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
instance := create2(0, 0x09, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(add(ptr, 0x38), deployer)
mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
mstore(add(ptr, 0x14), implementation)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
mstore(add(ptr, 0x58), salt)
mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
predicted := keccak256(add(ptr, 0x43), 0x55)
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt
) internal view returns (address predicted) {
return predictDeterministicAddress(implementation, salt, address(this));
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import "@openzeppelin/contracts/proxy/Clones.sol";
import "../utils/Versioning.sol";
contract MintpadFactory is Versioning {
// Event emitted when a clone is created
event CloneCreated(address indexed cloneAddress, address indexed creator);
// Platform address to receive the transaction fee
address public platformAddress;
// Fee in wei (equivalent to $1 in ETH at a fixed rate, e.g., 1 ETH = $2000)
uint256 public constant TRANSACTION_FEE = 0.00030 ether;
// Set the platform address of the contract
constructor(address _platformAddress) {
require(_platformAddress != address(0), "MintpadFactory: Invalid platform address");
platformAddress = _platformAddress;
_setVersion("1.0.0");
}
/**
* @dev Creates a clone of the implementation contract and transfers the transaction fee.
* @param _implementation The address of the implementation contract to clone.
* @param _initData Initialization data for the cloned contract.
* @return cloneAddress The address of the newly created clone.
*/
function clone(
address _implementation,
bytes memory _initData
) external payable returns (address cloneAddress) {
require(_implementation != address(0), "MintpadFactory: Invalid implementation address");
require(msg.value >= TRANSACTION_FEE, "MintpadFactory: Insufficient transaction fee");
// Transfer the transaction fee to the platform address
payable(platformAddress).transfer(TRANSACTION_FEE);
// Clone the implementation contract
cloneAddress = Clones.clone(_implementation);
// Initialize the clone
(bool success, ) = cloneAddress.call(_initData);
require(success, "MintpadFactory: Failed to initialize clone");
// Emit an event for the new clone
emit CloneCreated(cloneAddress, msg.sender);
// Refund any excess ETH sent
if (msg.value > TRANSACTION_FEE) {
payable(msg.sender).transfer(msg.value - TRANSACTION_FEE);
}
}
/**
* @dev Updates the platform address to receive the transaction fee.
* @param _platformAddress The new platform address.
*/
function setPlatformAddress(address _platformAddress) external {
require(_platformAddress != address(0), "MintpadFactory: Invalid platform address");
require(msg.sender == platformAddress, "MintpadFactory: Only current platform can update address");
platformAddress = _platformAddress;
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
abstract contract Versioning {
// The version of the contract
string public version;
constructor() {}
// Set the version of the contract
function _setVersion(string memory _version) internal {
version = _version;
}
}