forked from DecentralizedClimateFoundation/DCIPs
191 lines
7.0 KiB
Solidity
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);
|
||
|
}
|
||
|
}
|