becrypto/contracts/logic/NftChipLocker.sol
2022-11-04 14:57:31 +08:00

124 lines
4.0 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "../interfaces/IBEERC1155.sol";
import "../interfaces/IBEERC721.sol";
contract NftChipLocker is Ownable, ERC1155Holder{
mapping(address => bool) public nftTokenSupported;
using EnumerableSet for EnumerableSet.UintSet;
uint256 public constant MAX_CHIP_NUM = 4;
/**
* nft address => chip address => nftid => chip tokenid
*/
mapping( address => mapping(address => mapping(uint256 => EnumerableSet.UintSet))) chipPlugined;
/**
* nft address => chip address => chip tokenid => nftid
*/
mapping( address => mapping(address => mapping(uint256 => uint256))) chipOwner;
event ChipPlugin(
address nft,
uint256 nftId,
address chip,
uint256[] ids
);
event ChipUnplug(
address nft,
uint256 nftId,
address chip,
uint256[] ids
);
function addNFTTokenSupport(address nftToken) external onlyOwner {
nftTokenSupported[nftToken] = true;
}
function removeNFTTokenSupport(address nftToken) external onlyOwner {
nftTokenSupported[nftToken] = false;
}
function pluginChip(address nft, address chip, uint256 nftId, uint256[] memory chipIds)
external
{
require(nftTokenSupported[nft], "NftChipLocker: Unsupported NFT");
require(nftTokenSupported[chip], "NftChipLocker: Unsupported Chip");
require(!IBEERC721(nft).isLocked(nftId), "NftChipLocker: Can not pluin chip to locked token");
require(IERC721(nft).ownerOf(nftId) == msg.sender, "NftChipLocker: not owner of this nft now");
uint256 len = chipIds.length;
uint256 currentNum = chipPlugined[nft][chip][nftId].length();
require(len + currentNum <= MAX_CHIP_NUM, "NftChipLocker: reach max chip num");
uint256[] memory amounts = new uint256[](len);
for (uint256 i = 0; i < len; ++i) {
require(
IERC1155(chip).balanceOf(msg.sender, chipIds[i]) > 0,
"NftChipLocker: not enough chip"
);
require(
!IBEERC1155(chip).isLocked(chipIds[i]),
"NftChipLocker: chip is locked"
);
chipPlugined[nft][chip][nftId].add(chipIds[i]);
chipOwner[nft][chip][chipIds[i]] = nftId;
amounts[i] = 1;
}
IERC1155(chip).safeBatchTransferFrom(msg.sender, address(this), chipIds, amounts, "");
emit ChipPlugin(nft, nftId, chip, chipIds);
}
function unplugChip(address nft, address chip, uint256 nftId, uint256[] memory chipIds)
external
{
require(nftTokenSupported[nft], "NftChipLocker: Unsupported NFT");
require(nftTokenSupported[chip], "NftChipLocker: Unsupported Chip");
require(!IBEERC721(nft).isLocked(nftId), "NftChipLocker: Can not pluin chip to locked token");
require(IERC721(nft).ownerOf(nftId) == msg.sender, "NftChipLocker: not owner of this nft now");
uint256 len = chipIds.length;
uint256[] memory amounts = new uint256[](len);
for (uint256 i = 0; i < len; ++i) {
require(
chipPlugined[nft][chip][nftId].contains(chipIds[i]),
"NftChipLocker: chip not exists"
);
chipPlugined[nft][chip][nftId].remove(chipIds[i]);
delete chipOwner[nft][chip][chipIds[i]];
amounts[i] = 1;
}
IERC1155(chip).safeBatchTransferFrom(address(this), msg.sender, chipIds, amounts, "");
emit ChipUnplug(nft, nftId, chip, chipIds);
}
function chipOwnerTokenid(address nft, address chip, uint256 chipId)
external
view
returns(uint256)
{
return chipOwner[nft][chip][chipId];
}
function pluginedChipNum(address nft, address chip, uint256 tokenId)
public
view
returns(uint256)
{
return chipPlugined[nft][chip][tokenId].length();
}
function pluginedChips(address nft, address chip, uint256 tokenId)
external
view
returns(uint256[] memory)
{
return chipPlugined[nft][chip][tokenId].values();
}
}