Hey guys! I'm trying to extend ERC721Consecutive to have blacklist functionality, this approach was working well with just ERC721 but with the Consecutive extension, I have an unexpected error on deploy time.
Error: Transaction reverted: function returned an unexpected amount of data
at ERC721CollectionBlacklist._beforeTokenTransfer (contracts/Mechanics/Collection/ERC721CollectionBlacklist.sol:27)
at ERC721CollectionBlacklist._mintConsecutive (@openzeppelin/contracts/token/ERC721/extensions/ERC721Consecutive.sol:94)
at ERC721CollectionBlacklist.constructor (contracts/Mechanics/Collection/ERC721CollectionSimple.sol:14)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
It seems don't like the call of this.isBlacklisted(from), in _beforeTokenTransfer, but I don't understand how to work around it. Please advice!
Code to reproduce
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Consecutive.sol";
contract ERC721CollectionSimple is ERC721, ERC721Consecutive {
constructor(string memory name, string memory symbol, uint96 batchSize, address owner) ERC721(name, symbol) {
_mintConsecutive(owner, batchSize);
}
function _mint(address to, uint256 tokenId) internal virtual override(ERC721, ERC721Consecutive) {
super._mint(to, tokenId);
}
function _ownerOf(uint256 tokenId) internal view virtual override(ERC721, ERC721Consecutive) returns (address) {
return super._ownerOf(tokenId);
}
function _afterTokenTransfer(
address from,
address to,
uint256 firstTokenId,
uint256 batchSize
) internal virtual override(ERC721, ERC721Consecutive) {
super._afterTokenTransfer(from, to, firstTokenId, batchSize);
}
}
import "./ERC721CollectionSimple.sol";
import "./BlackList.sol";
contract ERC721CollectionBlacklist is ERC721CollectionSimple, BlackList {
constructor(
string memory name,
string memory symbol,
uint96 batchSize,
address owner
) ERC721CollectionSimple(name, symbol, batchSize, owner) {}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, AccessControl) returns (bool) {
return super.supportsInterface(interfaceId);
}
function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize) internal override {
require(from == address(0) || !this.isBlacklisted(from), "Blacklist: sender is blacklisted");
require(to == address(0) || !this.isBlacklisted(to), "Blacklist: receiver is blacklisted");
super._beforeTokenTransfer(from, to, firstTokenId, batchSize);
}
}
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/access/AccessControl.sol";
interface IBlackList {
error BlackListError(address account);
event Blacklisted(address indexed account);
event UnBlacklisted(address indexed account);
function blacklist(address account) external;
function unBlacklist(address account) external;
function isBlacklisted(address account) external view returns (bool);
}
abstract contract BlackList is IBlackList, AccessControl {
mapping(address => bool) blackList;
function blacklist(address account) external onlyRole(DEFAULT_ADMIN_ROLE) {
blackList[account] = true;
emit Blacklisted(account);
}
function unBlacklist(address account) external onlyRole(DEFAULT_ADMIN_ROLE) {
blackList[account] = false;
emit UnBlacklisted(account);
}
function isBlacklisted(address account) external view returns (bool) {
return blackList[account];
}
function _blacklist(address account) internal view {
if (this.isBlacklisted(account)) {
revert BlackListError(account);
}
}
modifier onlyNotBlackListed() {
_blacklist(_msgSender());
_;
}
}
Environment
"ethers": "5.7.2",
"hardhat": "2.14.0",
"hardhat-contract-sizer": "2.8.0",
"hardhat-deploy": "0.11.26",
"hardhat-gas-reporter": "1.0.9",
"solidity-coverage": "0.8.2",
"web3": "1.9.0",
"chai": "4.3.7"