2024-02-26 17:05:34 +08:00

129 lines
3.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract BEBadgeV2 is AccessControl, ERC721Enumerable, ERC721Burnable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
string private _baseTokenURI = "";
uint256 public immutable supplyLimit;
uint256 private _tokenIndex;
uint256 public maxBatchSize = 500;
// ============ Events ============
event MetaAddressUpdated(address indexed metaAddress);
event BatchLimitUpdated(uint256 indexed maxBatchSize);
constructor(
string memory _name,
string memory _symbol,
uint256 _supplyLimt
) ERC721(_name, _symbol) {
_setRoleAdmin(MINTER_ROLE, DEFAULT_ADMIN_ROLE);
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(MINTER_ROLE, msg.sender);
supplyLimit = _supplyLimt;
}
/**
* @dev Batch mint tokens and transfer to specified address.
*
* Requirements:
* - Caller must have `MINTER_ROLE`.
* - The total supply limit should not be exceeded if supplyLimit is greater than zero.
* - The number of tokenIds offered for minting should not exceed maxBatchSize.
*/
function batchMint(
address to,
uint256 count
) external onlyRole(MINTER_ROLE) returns (uint256[] memory) {
require(count > 0, "count is too small");
require(count <= maxBatchSize, "Exceeds the maximum batch size");
require(
(supplyLimit == 0) || (totalSupply() + count <= supplyLimit),
"Exceeds the total supply"
);
uint256[] memory tokenIds = new uint256[](count);
for (uint256 i = 0; i < count; i++) {
_tokenIndex += 1;
_safeMint(to, _tokenIndex);
tokenIds[i] = _tokenIndex;
}
return tokenIds;
}
/**
* @dev Safely mints a new token and assigns it to the specified address.
* Only the account with the MINTER_ROLE can call this function.
*
* @param to The address to which the newly minted token will be assigned.
*/
function safeMint(address to) external onlyRole(MINTER_ROLE) returns (uint256){
require(
(supplyLimit == 0) || (totalSupply() < supplyLimit),
"Exceeds the total supply"
);
uint256 tokenId = ++_tokenIndex;
_safeMint(to, tokenId);
return tokenId;
}
/**
* @dev Set token URI
*/
function updateBaseURI(
string calldata baseTokenURI
) external onlyRole(DEFAULT_ADMIN_ROLE) {
_baseTokenURI = baseTokenURI;
}
function _baseURI() internal view virtual override returns (string memory) {
return _baseTokenURI;
}
/**
* @dev Updates the maximum batch size for a batch operation.
* @param valNew The new maximum batch size.
* Requirements:
* - The caller must have the DEFAULT_ADMIN_ROLE.
* - The new batch size must be greater than 0.
*/
function updateBatchLimit(
uint256 valNew
) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(valNew > 0, "Batch size is too short");
maxBatchSize = valNew;
emit BatchLimitUpdated(valNew);
}
/**
* @dev See {IERC165-_beforeTokenTransfer}.
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual override(ERC721, ERC721Enumerable) {
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(
bytes4 interfaceId
)
public
view
virtual
override(ERC721, AccessControl, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
}