DCIPs/assets/eip-6672/contracts/ERC6672.sol

62 lines
2.9 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "./interfaces/IERC6672.sol";
contract ERC6672 is ERC721, IERC6672 {
using EnumerableSet for EnumerableSet.Bytes32Set;
bytes4 public constant IERC6672_ID = type(IERC6672).interfaceId;
mapping(address => mapping(uint256 => mapping(bytes32 => bool))) redemptionStatus;
mapping(address => mapping(uint256 => mapping(bytes32 => string))) public memos;
mapping(address => mapping(uint256 => EnumerableSet.Bytes32Set)) redemptions;
constructor() ERC721("Multiple RedeemableNFT", "mrNFT") {}
function isRedeemed(address _operator, bytes32 _redemptionId, uint256 _tokenId) external view returns (bool) {
return _isRedeemed(_operator, _redemptionId, _tokenId);
}
function getRedemptionIds(address _operator, uint256 _tokenId) external view returns (bytes32[] memory) {
require(redemptions[_operator][_tokenId].length() > 0, "ERC6672: token doesn't have any redemptions.");
return redemptions[_operator][_tokenId].values();
}
function redeem(bytes32 _redemptionId, uint256 _tokenId, string memory _memo) external {
address _operator = msg.sender;
require(!_isRedeemed(_operator, _redemptionId, _tokenId), "ERC6672: token already redeemed.");
_update(_operator, _redemptionId, _tokenId, _memo, true);
redemptions[_operator][_tokenId].add(_redemptionId);
}
function cancel(bytes32 _redemptionId, uint256 _tokenId, string memory _memo) external {
address _operator = msg.sender;
require(_isRedeemed(_operator, _redemptionId, _tokenId), "ERC6672: token doesn't redeemed.");
_update(_operator, _redemptionId, _tokenId, _memo, false);
_removeRedemption(_operator, _redemptionId, _tokenId);
}
function _isRedeemed(address _operator, bytes32 _redemptionId, uint256 _tokenId) internal view returns (bool) {
require(_exists(_tokenId), "ERC6672: token doesn't exists.");
return redemptionStatus[_operator][_tokenId][_redemptionId];
}
function _update(address _operator, bytes32 _redemptionId, uint256 _tokenId, string memory _memo, bool isRedeemed_) internal {
redemptionStatus[_operator][_tokenId][_redemptionId] = isRedeemed_;
memos[_operator][_tokenId][_redemptionId] = _memo;
}
function _removeRedemption(address _operator, bytes32 _redemptionId, uint256 _tokenId) internal {
redemptions[_operator][_tokenId].remove(_redemptionId);
}
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, IERC165) returns (bool) {
return
interfaceId == type(IERC721).interfaceId ||
interfaceId == type(IERC6672).interfaceId ||
super.supportsInterface(interfaceId);
}
}