DCIPs/assets/eip-4886/contracts/examples/EPSGenesis.sol

191 lines
7.0 KiB
Solidity

// SPDX-License-Identifier: CC0-1.0
// EPSProxy Contracts v1.8.0 (epsproxy/contracts/examples/EPSGenesis.sol)
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol";
import "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";
import "@epsproxy/contracts/Proxiable.sol";
/**
* @dev Contract instance for the EPS Genesis ERC-1155. This contract provides two token
* types designed to showcase the capabilities of the Eternal Proxy Service.
* - Open mint: Every proxy address can mint ONE of these tokens. Delivery will be to the
* delivery address. This demonstrates:
* (a) Retrieval of information and processing based on information in the EPS Register.
* (b) Delivery of new assets to the delivery address specified on the register.
* - Gated mint: Every proxy address that acts for a nominator one of three pre-determined
* NFTs can mint the 'gated' token. This will again be delivered to the delivery address
* specified on the EPS register. In addition this demonstrates:
* (c) Checking of the contract balance of the Nominator to determine eligibility. In
* this use of the EPS register risk to the eligibility asset is entirely eliminated
* as the contract interaction is with the proxy address, which does not hold the
* asset, not the nominator.
*/
contract EPSGenesis is ERC1155, Ownable, ERC1155Burnable, ERC1155Supply, Proxiable {
/**
* @dev Not required, but provided to give consistency with ERC-721 in terms of display
* in tools like etherscan:
*/
string public constant NAME = "EPSGenesis";
string public constant SYMBOL = "EPSGEN";
/**
* @dev Definition of token classes and max supply of each:
*/
uint256 public constant OPEN_TOKEN = 0;
uint256 public constant GATED_TOKEN = 1;
uint256 public constant MAX_SUPPLY_OPEN = 10000;
uint256 public constant MAX_SUPPLY_GATED = 10000;
/**
* @dev tokens that need to be held to mint the gated tokens, provided on the constructor:
*/
address public immutable GATE_1;
address public immutable GATE_2;
address public immutable GATE_3;
/**
* @dev each address is entitled to just ONE of each type. Each is free, except gas.
*/
mapping (address => bool) minterHasMintedOpen;
mapping (address => bool) minterHasMintedGated;
constructor(address _epsRegisterAddress, address _GATE_1, address _GATE_2, address _GATE_3, string memory _contractURI)
ERC1155(_contractURI)
Proxiable(_epsRegisterAddress) {
GATE_1 = _GATE_1;
GATE_2 = _GATE_2;
GATE_3 = _GATE_3;
}
/**
* @dev modifiers to control access based on previous minting:
*/
modifier hasNotAlreadyMintedOpen(address _receivedAddress) {
require(minterHasMintedOpen[_receivedAddress] != true, "Address has already minted in open mint, allocation exhausted");
_;
}
modifier hasNotAlreadyMintedGated(address _receivedAddress) {
require(minterHasMintedGated[_receivedAddress] != true, "Address has already minted in gated mint, allocation exhausted");
_;
}
/**
* @dev modifier to only allow minting from a proxy address:
*/
modifier isProxyAddress(address _receivedAddress) {
require(proxyRecordExists(_receivedAddress), "Only a proxy address can mint this token - go to app.epsproxy.com");
_;
}
/**
* @dev modifier to ensure supply(s) is not exhausted:
*/
modifier supplyNotExhaustedOpen() {
require(totalSupply(OPEN_TOKEN) < MAX_SUPPLY_OPEN, "Max supply reached for open mint - cannot be minted");
_;
}
modifier supplyNotExhaustedGated() {
require(totalSupply(GATED_TOKEN) < MAX_SUPPLY_GATED, "Max supply reached for gated mint - cannot be minted");
_;
}
/**
* @dev perform minting of the open tokens:
*/
function proxyMintOpen(address _receivedAddress) internal hasNotAlreadyMintedOpen(_receivedAddress) isProxyAddress(_receivedAddress) supplyNotExhaustedOpen() {
address nominator;
address delivery;
bool isProxied;
(nominator, delivery, isProxied) = getAddresses(_receivedAddress);
_mint(delivery, OPEN_TOKEN, 1, "");
minterHasMintedOpen[_receivedAddress] = true;
}
/**
* @dev perform minting of the gated tokens:
*/
function proxyMintGated(address _receivedAddress) internal hasNotAlreadyMintedGated(_receivedAddress) isProxyAddress(_receivedAddress) supplyNotExhaustedGated() {
address nominator;
address delivery;
bool isProxied;
(nominator, delivery, isProxied) = getAddresses(_receivedAddress);
require((IERC721(GATE_1).balanceOf(nominator) >= 1 || IERC721(GATE_2).balanceOf(nominator) >= 1 || IERC721(GATE_3).balanceOf(nominator) >= 1), "Must hold an eligible token for this mint");
_mint(delivery, GATED_TOKEN, 1, "");
minterHasMintedGated[_receivedAddress] = true;
}
/**
* @dev external function for minting calls. Required boolean values for open and gated minting (can pass both as true to perform both)
*/
function mintEPSGenesis(bool mintOpen, bool mintGated) external {
if (mintOpen) {
proxyMintOpen(msg.sender);
}
if (mintGated) {
proxyMintGated(msg.sender);
}
}
/**
* @dev external and public functions to determine eligibility off-chain:
*/
function hasMintedOpen(address _receivedAddress) external view returns (bool) {
return(minterHasMintedOpen[_receivedAddress]);
}
function hasMintedGated(address _receivedAddress) external view returns (bool) {
return(minterHasMintedGated[_receivedAddress]);
}
function hasAProxyRecord(address _receivedAddress) external view returns (bool) {
return(proxyRecordExists(_receivedAddress));
}
function hasNominatorWithEligibleToken(address _receivedAddress) public view returns (bool) {
address nominator;
address delivery;
bool isProxied;
(nominator, delivery, isProxied) = getAddresses(_receivedAddress);
return((IERC721(GATE_1).balanceOf(nominator) >= 1 || IERC721(GATE_2).balanceOf(nominator) >= 1 || IERC721(GATE_3).balanceOf(nominator) >= 1));
}
function addressStatus(address _receivedAddress) public view returns (bool open, bool gated, bool proxy, bool eligible) {
return(minterHasMintedOpen[_receivedAddress], minterHasMintedGated[_receivedAddress], proxyRecordExists(_receivedAddress), hasNominatorWithEligibleToken(_receivedAddress));
}
/**
* @dev name, max and total supply for tools like etherscan:
*/
function name() public pure returns (string memory) {
return NAME;
}
function symbol() public pure returns (string memory) {
return SYMBOL;
}
function totalSupply() public pure returns (uint256) {
return (MAX_SUPPLY_OPEN + MAX_SUPPLY_GATED);
}
// The following functions are overrides required by Solidity.
function _beforeTokenTransfer(address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data)
internal
override(ERC1155, ERC1155Supply)
{
super._beforeTokenTransfer(operator, from, to, ids, amounts, data);
}
}