文件 1 的 6:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 2 的 6:ISuper1155.sol
pragma solidity 0.7.6;
interface ISuper1155 {
function BURN ( ) external view returns ( bytes32 );
function CONFIGURE_GROUP ( ) external view returns ( bytes32 );
function LOCK_CREATION ( ) external view returns ( bytes32 );
function LOCK_ITEM_URI ( ) external view returns ( bytes32 );
function LOCK_URI ( ) external view returns ( bytes32 );
function MANAGER ( ) external view returns ( bytes32 );
function MINT ( ) external view returns ( bytes32 );
function SET_METADATA ( ) external view returns ( bytes32 );
function SET_PROXY_REGISTRY ( ) external view returns ( bytes32 );
function SET_URI ( ) external view returns ( bytes32 );
function UNIVERSAL ( ) external view returns ( bytes32 );
function ZERO_RIGHT ( ) external view returns ( bytes32 );
function balanceOf ( address _owner, uint256 _id ) external view returns ( uint256 );
function balanceOfBatch ( address[] memory _owners, uint256[] memory _ids ) external view returns ( uint256[] memory );
function burn ( address _burner, uint256 _id, uint256 _amount ) external;
function burnBatch ( address _burner, uint256[] memory _ids, uint256[] memory _amounts ) external;
function burnCount ( uint256 ) external view returns ( uint256 );
function circulatingSupply ( uint256 ) external view returns ( uint256 );
function configureGroup ( uint256 _groupId, bytes calldata _data ) external;
function groupBalances ( uint256, address ) external view returns ( uint256 );
function hasRightUntil ( address _address, bytes32 _circumstance, bytes32 _right ) external view returns ( uint256 );
function isApprovedForAll ( address _owner, address _operator ) external view returns ( bool );
function itemGroups ( uint256 ) external view returns ( bool initialized, string memory _name, uint8 supplyType, uint256 supplyData, uint8 itemType, uint256 itemData, uint8 burnType, uint256 burnData, uint256 _circulatingSupply, uint256 _mintCount, uint256 _burnCount );
function lock ( ) external;
function lockURI ( string memory _uri, uint256 _id ) external;
function lockURI ( string memory _uri ) external;
function locked ( ) external view returns ( bool );
function managerRight ( bytes32 ) external view returns ( bytes32 );
function metadata ( uint256 ) external view returns ( string memory );
function metadataFrozen ( uint256 ) external view returns ( bool );
function metadataUri ( ) external view returns ( string memory );
function mintBatch ( address _recipient, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data ) external;
function mintCount ( uint256 ) external view returns ( uint256 );
function name ( ) external view returns ( string memory );
function owner ( ) external view returns ( address );
function permissions ( address, bytes32, bytes32 ) external view returns ( uint256 );
function proxyRegistryAddress ( ) external view returns ( address );
function renounceOwnership ( ) external;
function safeBatchTransferFrom ( address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data ) external;
function safeTransferFrom ( address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data ) external;
function setApprovalForAll ( address _operator, bool _approved ) external;
function setManagerRight ( bytes32 _managedRight, bytes32 _managerRight ) external;
function setMetadata ( uint256 _id, string memory _metadata ) external;
function setPermit ( address _address, bytes32 _circumstance, bytes32 _right, uint256 _expirationTime ) external;
function setProxyRegistry ( address _proxyRegistryAddress ) external;
function setURI ( string memory _uri ) external;
function supportsInterface ( bytes4 interfaceId ) external view returns ( bool );
function totalBalances ( address ) external view returns ( uint256 );
function transferOwnership ( address newOwner ) external;
function uri ( uint256 ) external view returns ( string memory );
function uriLocked ( ) external view returns ( bool );
function version ( ) external view returns ( uint256 );
}
文件 3 的 6:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 4 的 6:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 5 的 6:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 6 的 6:TokenRedeemer.sol
pragma solidity 0.7.6;
pragma abicoder v2;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "./ISuper1155.sol";
contract TokenRedeemer is Ownable, ReentrancyGuard {
using SafeMath for uint256;
ISuper1155 public super1155;
address public burnAddress;
bool public customBurn;
struct RedemptionConfig {
uint256 groupIdOut;
uint256 amountOut;
bool burnOnRedemption;
}
mapping (uint256 => mapping(address => RedemptionConfig)) public redemptionConfigs;
mapping (address => mapping (uint256 => address)) public redeemer;
event TokenRedemption(address indexed user, uint256 indexed tokenIn, address indexed contractOut, uint256[] tokensOut);
event ConfigUpdate(uint256 groupIdIn, uint256 groupIdOut, address tokenOut, uint256 amountOut, bool burnOnRedemption);
constructor(ISuper1155 _super1155, address _burnTarget, bool _customBurn) public {
super1155 = _super1155;
customBurn = _customBurn;
if (customBurn) {
require(_burnTarget != address(0), "TokenRedeemer::constructor: Custom burn address cannot be 0 address");
burnAddress = _burnTarget;
}
}
function redeem(uint256 _tokenId, address _tokenOut) external nonReentrant {
_redeemToken(_tokenId, _tokenOut);
}
function redeemMult(uint256[] calldata _tokenIds, address _tokenOut) external nonReentrant {
for(uint256 n = 0; n < _tokenIds.length; n++){
_redeemToken(_tokenIds[n], _tokenOut);
}
}
function _redeemToken(uint256 _tokenId, address _tokenOut) internal {
uint256 _groupIdIn = _tokenId >> 128;
require(redeemer[_tokenOut][_tokenId] == address(0), "TokenRedeemer::redeem: token has already been redeemed for this group" );
RedemptionConfig memory config = redemptionConfigs[_groupIdIn][_tokenOut];
uint256 redemptionAmount = config.amountOut;
uint256 groupIdOut = config.groupIdOut;
{
require(groupIdOut != uint256(0), "TokenRedeemer::redeem: invalid group id from token");
require(redemptionAmount != uint256(0), "TokenRedeemer::redeem: invalid redemption amount");
uint256 balanceOfSender = super1155.balanceOf(_msgSender(), _tokenId);
require(balanceOfSender != 0, "TokenRedeemer::redeem: msg sender is not token owner");
}
(bool groupInit, , , , , , , , , uint256 mintCount,) = ISuper1155(_tokenOut).itemGroups(groupIdOut);
require(groupInit, "TokenRedeemer::redeem: item group not initialized");
uint256[] memory ids = new uint256[](redemptionAmount);
uint256[] memory amounts = new uint[](redemptionAmount);
uint256 newgroupIdPrep = groupIdOut << 128;
for(uint256 i = 0; i < redemptionAmount; i++) {
ids[i] = newgroupIdPrep.add(mintCount).add(1).add(i);
amounts[i] = uint256(1);
}
redeemer[_tokenOut][_tokenId] = _msgSender();
if (config.burnOnRedemption) {
if (customBurn) {
super1155.safeTransferFrom(msg.sender, burnAddress, _tokenId, 1, "");
} else {
super1155.burnBatch(msg.sender, _asSingletonArray(_tokenId), _asSingletonArray(1));
}
}
ISuper1155(_tokenOut).mintBatch(msg.sender, ids, amounts, "");
emit TokenRedemption(msg.sender, _tokenId, _tokenOut, ids);
}
function setRedemptionConfig(uint256 _groupIdIn, uint256 _groupIdOut, address _tokenOut, RedemptionConfig calldata _data) external onlyOwner {
redemptionConfigs[_groupIdIn][_tokenOut] = RedemptionConfig({
groupIdOut: _groupIdOut,
amountOut: _data.amountOut,
burnOnRedemption: _data.burnOnRedemption
});
emit ConfigUpdate(_groupIdIn, _groupIdOut, _tokenOut, _data.amountOut, _data.burnOnRedemption);
}
function _asSingletonArray(uint256 _element) private pure returns (uint256[] memory) {
uint256[] memory array = new uint256[](1);
array[0] = _element;
return array;
}
}
{
"compilationTarget": {
"contracts/TokenRedeemer.sol": "TokenRedeemer"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 0
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ISuper1155","name":"_super1155","type":"address"},{"internalType":"address","name":"_burnTarget","type":"address"},{"internalType":"bool","name":"_customBurn","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"groupIdIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"groupIdOut","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"},{"indexed":false,"internalType":"bool","name":"burnOnRedemption","type":"bool"}],"name":"ConfigUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenIn","type":"uint256"},{"indexed":true,"internalType":"address","name":"contractOut","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokensOut","type":"uint256[]"}],"name":"TokenRedemption","type":"event"},{"inputs":[],"name":"burnAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"customBurn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_tokenOut","type":"address"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address","name":"_tokenOut","type":"address"}],"name":"redeemMult","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"redeemer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"redemptionConfigs","outputs":[{"internalType":"uint256","name":"groupIdOut","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bool","name":"burnOnRedemption","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_groupIdIn","type":"uint256"},{"internalType":"uint256","name":"_groupIdOut","type":"uint256"},{"internalType":"address","name":"_tokenOut","type":"address"},{"components":[{"internalType":"uint256","name":"groupIdOut","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"bool","name":"burnOnRedemption","type":"bool"}],"internalType":"struct TokenRedeemer.RedemptionConfig","name":"_data","type":"tuple"}],"name":"setRedemptionConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"super1155","outputs":[{"internalType":"contract ISuper1155","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]