编译器
0.8.17+commit.8df45f5f
文件 1 的 15:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 2 的 15:IArbSys.sol
pragma solidity >=0.4.21 <0.9.0;
interface ArbSys {
function arbBlockNumber() external view returns (uint256);
function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32);
function arbChainID() external view returns (uint256);
function arbOSVersion() external view returns (uint256);
function getStorageGasAvailable() external view returns (uint256);
function isTopLevelCall() external view returns (bool);
function mapL1SenderContractAddressToL2Alias(
address sender,
address unused
) external pure returns (address);
function wasMyCallersAddressAliased() external view returns (bool);
function myCallersAddressWithoutAliasing() external view returns (address);
function withdrawEth(address destination) external payable returns (uint256);
function sendTxToL1(
address destination,
bytes calldata data
) external payable returns (uint256);
function sendMerkleTreeState()
external
view
returns (uint256 size, bytes32 root, bytes32[] memory partials);
event L2ToL1Tx(
address caller,
address indexed destination,
uint256 indexed hash,
uint256 indexed position,
uint256 arbBlockNum,
uint256 ethBlockNum,
uint256 timestamp,
uint256 callvalue,
bytes data
);
event L2ToL1Transaction(
address caller,
address indexed destination,
uint256 indexed uniqueId,
uint256 indexed batchNumber,
uint256 indexInBatch,
uint256 arbBlockNum,
uint256 ethBlockNum,
uint256 timestamp,
uint256 callvalue,
bytes data
);
event SendMerkleUpdate(
uint256 indexed reserved,
bytes32 indexed hash,
uint256 indexed position
);
error InvalidBlockNumber(uint256 requested, uint256 current);
}
文件 3 的 15:IItemDataStorage.sol
pragma solidity ^0.8.17;
interface IItemDataStorage {
function obtainTokenId(
uint16[] memory _characteristics
) external returns (uint256);
function characteristics(
uint256 _tokenId,
uint16 _characteristicId
) external view returns (uint16);
function characteristics(
uint256 _tokenId
) external view returns (uint16[16] memory);
}
文件 4 的 15:ILootBox.sol
pragma solidity ^0.8.17;
interface ILootBox {
function mintFor(address _for, uint256 _id, uint256 _amount) external;
function mintBatchFor(
address _for,
uint256[] memory _ids,
uint256[] memory _amounts
) external;
function burn(uint256 _id, uint256 _amount) external;
function safeBurnBatch(
address _for,
uint256[] calldata ids,
uint256[] calldata amounts
) external;
function safeBatchTransferFrom(
address _from,
address _to,
uint256[] calldata _ids,
uint256[] calldata _amounts,
bytes calldata data
) external;
function safeTransferFrom(
address _from,
address _to,
uint256 _ids,
uint256 _amounts,
bytes calldata data
) external;
}
文件 5 的 15:ILootBoxDataStorage.sol
pragma solidity ^0.8.17;
import "../Item/IItemDataStorage.sol";
interface ILootBoxDataStorage is IItemDataStorage {
event LootBoxUpdated(uint256 _tokenId, uint16[16] characteristics);
}
文件 6 的 15:ILootBoxDispenser.sol
pragma solidity ^0.8.17;
interface ILootBoxDispenser {
function dispense(address _address, uint256 _id, uint256 _amount) external;
function dispenseBatch(
address _address,
uint256[] calldata _ids,
uint256[] calldata _amounts
) external;
event LootBoxesDispensed(address _address, uint256 _tokenId, uint256 _amount);
}
文件 7 的 15:ILootBoxRevealer.sol
pragma solidity ^0.8.17;
import "./Rewards/IRewardsPool.sol";
interface ILootBoxRevealer {
function reveal(
uint256[] calldata _lootBoxTokenIds,
uint256[] calldata _lootBoxAmount
) external;
event LootBoxRevealedEvent(
uint256 revealIndex,
address lootboxOwner,
uint256 lootboxTokenId,
uint256[] rewardTokenTypes,
address[] rewardTokenAddresses,
uint256[] rewardTokenIds,
uint256[] rewardAmounts
);
}
文件 8 的 15:IManager.sol
pragma solidity ^0.8.4;
interface IManager {
function isAdmin(address _addr) external view returns (bool);
function isManager(address _addr, uint256 _type) external view returns (bool);
function addManager(address _addr, uint256 _type) external;
function removeManager(address _addr, uint256 _type) external;
function addAdmin(address _addr) external;
function removeAdmin(address _addr) external;
}
文件 9 的 15:IRewardsPool.sol
pragma solidity ^0.8.17;
enum RewardTokenType {
ERC20,
ERC721,
ERC1155
}
struct DispensedRewards {
uint256 nextRandomBase;
DispensedReward[] rewards;
}
struct DispensedReward {
RewardTokenType tokenType;
address token;
uint256 tokenId;
uint256 amount;
}
uint256 constant DECIMAL_POINT = 1000;
uint256 constant ONE_HUNDRED = 100 * DECIMAL_POINT;
interface IRewardsPool {
function dispenseRewards(
uint64 subPoolId,
uint256 randomNumberBase,
address receiver
) external returns (DispensedRewards memory);
}
文件 10 的 15:LootBoxRevealer.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "../Manager/ManagerModifier.sol";
import "../Item/RarityItemConstants.sol";
import "./ILootBox.sol";
import "./ILootBoxDataStorage.sol";
import "./ILootBoxDispenser.sol";
import "./ILootBoxRevealer.sol";
import "../Utils/Random.sol";
import "./Rewards/IRewardsPool.sol";
contract LootBoxRevealer is
ILootBoxRevealer,
ReentrancyGuard,
Pausable,
ManagerModifier
{
struct RewardsUnwrapper {
uint256[] rewardTokenTypes;
address[] rewardTokenAddresses;
uint256[] rewardTokenIds;
uint256[] rewardAmounts;
}
ILootBox public lootBox;
ILootBoxDataStorage public lootBoxDataStorage;
IRewardsPool public lootBoxRewardsPool;
uint256 public lootBoxesRevealed;
uint256 minimumGas;
constructor(
address _manager,
address _lootBox,
address _lootBoxDataStorage,
address _lootBoxRewardsPool
) ManagerModifier(_manager) {
lootBox = ILootBox(_lootBox);
lootBoxDataStorage = ILootBoxDataStorage(_lootBoxDataStorage);
lootBoxRewardsPool = IRewardsPool(_lootBoxRewardsPool);
minimumGas = 500000;
}
function reveal(
uint256[] calldata _lootBoxTokenIds,
uint256[] calldata _lootBoxAmounts
) external nonReentrant whenNotPaused {
require(
msg.sender == tx.origin,
"Revealing is not allowed through another contract"
);
lootBox.safeBurnBatch(msg.sender, _lootBoxTokenIds, _lootBoxAmounts);
uint256 tempLootBoxesRevealed = lootBoxesRevealed;
uint256 randomBase = Random.startRandomBase(
tempLootBoxesRevealed,
uint256(uint160(msg.sender))
);
RewardsUnwrapper memory holder;
for (uint256 i = 0; i < _lootBoxTokenIds.length; i++) {
uint16 lootBoxRarity = uint16(
lootBoxDataStorage.characteristics(
_lootBoxTokenIds[i],
ITEM_CHARACTERISTIC_RARITY
)
);
for (uint256 j = 0; j < _lootBoxAmounts[i]; j++) {
require(gasleft() > minimumGas, "Manual gas reduction is not allowed");
DispensedRewards memory result = lootBoxRewardsPool.dispenseRewards(
lootBoxRarity,
randomBase,
msg.sender
);
randomBase = result.nextRandomBase;
holder.rewardTokenTypes = new uint256[](result.rewards.length);
holder.rewardTokenAddresses = new address[](result.rewards.length);
holder.rewardTokenIds = new uint256[](result.rewards.length);
holder.rewardAmounts = new uint256[](result.rewards.length);
for (uint r = 0; r < result.rewards.length; r++) {
DispensedReward memory reward = result.rewards[r];
holder.rewardTokenTypes[r] = (uint256)(reward.tokenType);
holder.rewardTokenAddresses[r] = reward.token;
holder.rewardTokenIds[r] = reward.tokenId;
holder.rewardAmounts[r] = reward.amount;
}
emit LootBoxRevealedEvent(
tempLootBoxesRevealed++,
msg.sender,
_lootBoxTokenIds[i],
holder.rewardTokenTypes,
holder.rewardTokenAddresses,
holder.rewardTokenIds,
holder.rewardAmounts
);
}
lootBoxesRevealed = tempLootBoxesRevealed;
}
}
function setMinimumGas(uint256 _minimumGas) external onlyAdmin {
minimumGas = _minimumGas;
}
function setRewardPool(address _rewardPoolAddress) external onlyAdmin {
lootBoxRewardsPool = IRewardsPool(_rewardPoolAddress);
}
function pause() external onlyAdmin {
_pause();
}
function unpause() external onlyAdmin {
_unpause();
}
}
文件 11 的 15:ManagerModifier.sol
pragma solidity ^0.8.4;
import "../Manager/IManager.sol";
abstract contract ManagerModifier {
IManager public immutable MANAGER;
constructor(address _manager) {
MANAGER = IManager(_manager);
}
modifier onlyAdmin() {
require(MANAGER.isAdmin(msg.sender), "Manager: Not an Admin");
_;
}
modifier onlyManager() {
require(MANAGER.isManager(msg.sender, 0), "Manager: Not manager");
_;
}
modifier onlyMinter() {
require(MANAGER.isManager(msg.sender, 1), "Manager: Not minter");
_;
}
modifier onlyTokenMinter() {
require(MANAGER.isManager(msg.sender, 2), "Manager: Not token minter");
_;
}
modifier onlyBinder() {
require(MANAGER.isManager(msg.sender, 3), "Manager: Not binder");
_;
}
}
文件 12 的 15:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
return _paused;
}
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 13 的 15:Random.sol
pragma solidity ^0.8.17;
import "./IArbSys.sol";
uint256 constant MIN_SAFE_NEXT_NUMBER_PRIME = 1000033;
uint256 constant HIGH_RANGE_PRIME_OFFSET = 13;
library Random {
function startRandomBase(
uint256 _highSalt,
uint256 _lowSalt
) internal view returns (uint256) {
return
uint256(
keccak256(
abi.encodePacked(
ArbSys(address(0x64)).arbBlockHash(
ArbSys(address(0x64)).arbBlockNumber() - 1
),
msg.sender,
_lowSalt,
_highSalt
)
)
);
}
function getNextRandom(
uint256 randomBase,
uint256 range
) internal view returns (uint256 random, uint256 nextBase) {
uint256 nextNumberSeparator = MIN_SAFE_NEXT_NUMBER_PRIME > range
? MIN_SAFE_NEXT_NUMBER_PRIME
: (range + HIGH_RANGE_PRIME_OFFSET);
uint256 nextBaseNumber = randomBase / nextNumberSeparator;
if (nextBaseNumber > nextNumberSeparator) {
return (randomBase % range, nextBaseNumber);
}
nextBaseNumber = uint256(
keccak256(
abi.encodePacked(
ArbSys(address(0x64)).arbBlockHash(
ArbSys(address(0x64)).arbBlockNumber() - 1
),
msg.sender,
randomBase,
range
)
)
);
return (nextBaseNumber % range, nextBaseNumber / nextNumberSeparator);
}
}
文件 14 的 15:RarityItemConstants.sol
pragma solidity ^0.8.17;
string constant ITEM_COLLECTION_NAME = "Realm Rarity items";
string constant ITEM_COLLECTION_DESCRIPTION = "Rarity items description";
uint16 constant ITEM_CHARACTERISTIC_RARITY = 0;
uint16 constant ITEM_CHARACTERISTIC_SLOT = 1;
uint16 constant ITEM_CHARACTERISTIC_CATEGORY = 2;
uint16 constant ITEM_CHARACTERISTIC_TYPE = 3;
uint16 constant ITEM_CHARACTERISTIC_PREFIX = 4;
uint16 constant ITEM_CHARACTERISTIC_SUFFIX = 5;
uint16 constant ITEM_SLOT_HEAD = 1;
uint16 constant ITEM_SLOT_CHEST = 2;
uint16 constant ITEM_SLOT_HAND = 3;
uint16 constant ITEM_SLOT_JEWELRY = 4;
uint16 constant ITEM_TYPE_HEADGEAR = 1;
uint16 constant ITEM_TYPE_ARMOR = 2;
uint16 constant ITEM_TYPE_APPAREL = 3;
uint16 constant ITEM_TYPE_JEWELRY = 4;
uint16 constant ITEM_TYPE_WEAPON = 5;
uint16 constant ITEM_RARITY_COMMON = 1;
uint16 constant ITEM_RARITY_RARE = 2;
uint16 constant ITEM_RARITY_EPIC = 3;
uint16 constant ITEM_RARITY_LEGENDARY = 4;
uint16 constant ITEM_RARITY_MYTHIC = 5;
uint16 constant ITEM_RARITY_EXOTIC = 6;
文件 15 的 15:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
}
{
"compilationTarget": {
"contracts/Lootbox/LootBoxRevealer.sol": "LootBoxRevealer"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"address","name":"_lootBox","type":"address"},{"internalType":"address","name":"_lootBoxDataStorage","type":"address"},{"internalType":"address","name":"_lootBoxRewardsPool","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"revealIndex","type":"uint256"},{"indexed":false,"internalType":"address","name":"lootboxOwner","type":"address"},{"indexed":false,"internalType":"uint256","name":"lootboxTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"rewardTokenTypes","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"rewardTokenAddresses","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"rewardTokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"rewardAmounts","type":"uint256[]"}],"name":"LootBoxRevealedEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"MANAGER","outputs":[{"internalType":"contract IManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootBox","outputs":[{"internalType":"contract ILootBox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootBoxDataStorage","outputs":[{"internalType":"contract ILootBoxDataStorage","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootBoxRewardsPool","outputs":[{"internalType":"contract IRewardsPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lootBoxesRevealed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_lootBoxTokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_lootBoxAmounts","type":"uint256[]"}],"name":"reveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minimumGas","type":"uint256"}],"name":"setMinimumGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_rewardPoolAddress","type":"address"}],"name":"setRewardPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]