编译器
0.8.20+commit.a1b79de6
文件 1 的 21:BattleRewardsDispenser.sol
pragma solidity ^0.8.17;
import "./IBattleRewardsDispenser.sol";
import "../Manager/ManagerModifier.sol";
import "../Lootbox/ILootBoxDispenser.sol";
import "../Utils/Random.sol";
import "../lib/FloatingPointConstants.sol";
import "./IBattleVersusV3.sol";
import "../Renown/IBattleRenown.sol";
import "../Adventurer/IBatchAdventurerData.sol";
import "../Adventurer/TraitConstants.sol";
import "../ERC20/IGloballyStakedTokenCalculator.sol";
struct LootBoxRewardRarityConfig {
uint256 lootBoxTotalChance;
uint256[] lootBoxChances;
uint256[] lootBoxTokenIds;
uint256[] lootBoxMinimumLevels;
}
contract BattleRewardsDispenser is ManagerModifier, IBattleRewardsDispenser {
event BattleRewards(
uint fightId,
int adventurerRenown,
int opponentRenown,
uint lootBoxId,
uint xp
);
IBattleRenown public immutable BATTLE_RENOWN;
ILootBoxDispenser public immutable LOOTBOX_DISPENSER;
IBatchAdventurerData public immutable ADVENTURER_DATA;
IGloballyStakedTokenCalculator public STAKED_TOKEN_CALCULATOR;
LootBoxRewardRarityConfig public lootBoxRewardRarityConfig;
uint256 public LOOTBOX_MIN_DROP_RATE;
uint256 public LOOTBOX_MAX_DROP_RATE;
uint256 public LOOTBOX_SPREAD;
uint256 public currentLootBoxChanceModifier;
uint256 public currentLootBoxChanceModifierLastUpdate;
uint256 public AVERAGE_STAKED_EPOCH_SPAN = 30;
constructor(
address _manager,
address _battleRenown,
address _lootboxDispenser,
address _adventurerData,
address _stakedTokenCalculator
) ManagerModifier(_manager) {
BATTLE_RENOWN = IBattleRenown(_battleRenown);
LOOTBOX_DISPENSER = ILootBoxDispenser(_lootboxDispenser);
ADVENTURER_DATA = IBatchAdventurerData(_adventurerData);
STAKED_TOKEN_CALCULATOR = IGloballyStakedTokenCalculator(
_stakedTokenCalculator
);
}
function dispenseRewards(
address _owner,
uint256 _fightId,
uint256 _battleEpoch,
address _adventurerAddress,
uint256 _adventurerTokenId,
address _opponentAddress,
uint256 _opponentTokenId,
uint256[] calldata _params,
FightResult calldata result
) external onlyManager returns (uint256 randomBase) {
RenownDelta memory delta = BATTLE_RENOWN.updateRenown(
_adventurerAddress,
_adventurerTokenId,
_opponentAddress,
_opponentTokenId,
result
);
int deltaAdventurer = delta.adventurer;
int deltaOpponent = delta.opponent;
uint lootBoxId;
(lootBoxId, randomBase) = _dispenseLootBox(
_owner,
result.adventurerLevel,
result.probability,
result.nextRandomBase
);
uint xpAmount;
if (result.overallWin) {
xpAmount = result.losses == 0 ? 2 : 1;
ADVENTURER_DATA.add(
_adventurerAddress,
_adventurerTokenId,
traits.ADV_TRAIT_GROUP_BASE,
traits.ADV_TRAIT_BASE_XP,
xpAmount
);
}
emit BattleRewards(
_fightId,
deltaAdventurer,
deltaOpponent,
lootBoxId,
xpAmount
);
}
function _dispenseLootBox(
address _owner,
uint _adventurerLevel,
uint _probability,
uint _randomBase
) internal returns (uint256 lootBoxId, uint256 randomBase) {
lootBoxId = 0;
randomBase = _randomBase;
uint dropRate = _calculateDropRate(_probability);
if (dropRate < ONE_HUNDRED) {
uint roll;
(roll, randomBase) = Random.getNextRandom(randomBase, ONE_HUNDRED);
if (roll <= dropRate) {
(roll, randomBase) = Random.getNextRandom(
randomBase,
lootBoxRewardRarityConfig.lootBoxTotalChance
);
lootBoxId = _getLootBoxId(roll, _adventurerLevel);
LOOTBOX_DISPENSER.dispense(_owner, lootBoxId, 1);
}
}
}
function currentDropRate(uint _probability) external view returns (uint) {
uint globalChance = LOOTBOX_MIN_DROP_RATE +
((currentLootBoxChanceModifier * LOOTBOX_SPREAD) / ONE_HUNDRED);
return ((ONE_HUNDRED - _probability) * globalChance) / ONE_HUNDRED;
}
function _calculateDropRate(uint _probability) private returns (uint) {
uint globalChance = LOOTBOX_MIN_DROP_RATE +
((_getModifier() * LOOTBOX_SPREAD) / ONE_HUNDRED);
return ((ONE_HUNDRED - _probability) * globalChance) / ONE_HUNDRED;
}
function _getModifier() private returns (uint) {
if (block.timestamp - 1 hours < currentLootBoxChanceModifierLastUpdate) {
return currentLootBoxChanceModifier;
}
(, , , , currentLootBoxChanceModifier) = STAKED_TOKEN_CALCULATOR
.currentGloballyStakedAverage(AVERAGE_STAKED_EPOCH_SPAN);
currentLootBoxChanceModifierLastUpdate = block.timestamp;
return currentLootBoxChanceModifier;
}
function _getLootBoxId(uint roll, uint level) private view returns (uint256) {
for (
uint256 i = 0;
i < lootBoxRewardRarityConfig.lootBoxChances.length;
i++
) {
if (roll >= lootBoxRewardRarityConfig.lootBoxChances[i]) {
roll -= lootBoxRewardRarityConfig.lootBoxChances[i];
continue;
}
if (level < lootBoxRewardRarityConfig.lootBoxMinimumLevels[i]) {
roll = 0;
continue;
}
return lootBoxRewardRarityConfig.lootBoxTokenIds[i];
}
return 0;
}
function updateLootboxConfig(
uint256 _minDropRate,
uint256 _maxDropRate,
uint256[] calldata _chances,
uint256[] calldata _minimumLevels,
uint256[] calldata _tokenIds
) external onlyAdmin {
uint256 totalChance;
require(_minDropRate <= _maxDropRate, "Invalid drop rate");
LOOTBOX_MIN_DROP_RATE = _minDropRate;
LOOTBOX_MAX_DROP_RATE = _maxDropRate;
LOOTBOX_SPREAD = _maxDropRate - _minDropRate;
for (uint256 i = 0; i < _chances.length; i++) {
totalChance += _chances[i];
}
lootBoxRewardRarityConfig = LootBoxRewardRarityConfig(
totalChance,
_chances,
_tokenIds,
_minimumLevels
);
}
}
文件 2 的 21: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;
}
}
文件 3 的 21:Epoch.sol
pragma solidity ^0.8.17;
import "../lib/FloatingPointConstants.sol";
uint256 constant MASK_128 = ((1 << 128) - 1);
uint128 constant MASK_64 = ((1 << 64) - 1);
library Epoch {
function toEpochNumber(
uint256 _timestamp,
uint256 _duration,
uint256 _offset
) internal pure returns (uint256) {
return (_timestamp + _offset) / _duration;
}
function toEpochNumber(uint256 _timestamp, uint128 _config) internal pure returns (uint256) {
return (_timestamp + (_config & MASK_64)) / ((_config >> 64) & MASK_64);
}
function toEpochCompleteness(
uint256 _timestamp,
uint128 _config
) internal pure returns (uint256 result) {
result = (_config >> 64) & MASK_64;
result = (ONE_HUNDRED * ((_timestamp + (_config & MASK_64)) % result)) / result;
}
function epochToTimestamp(
uint256 _epoch,
uint128 _config
) internal pure returns (uint256 result) {
result = _epoch * ((_config >> 64) & MASK_64);
if (result > 0) {
result -= (_config & MASK_64);
}
}
function toConfig(uint64 _duration, uint64 _offset) internal pure returns (uint128) {
return (uint128(_duration) << 64) | uint128(_offset);
}
function packEpoch(uint256 _epochNumber, uint128 _config) internal pure returns (uint256) {
return (uint256(_config) << 128) | uint128(_epochNumber);
}
function packTimestampToEpoch(
uint256 _timestamp,
uint128 _config
) internal pure returns (uint256) {
return packEpoch(toEpochNumber(_timestamp, _config), _config);
}
function unpack(
uint256 _packedEpoch
) internal pure returns (uint256 epochNumber, uint128 config) {
config = uint128(_packedEpoch >> 128);
epochNumber = _packedEpoch & MASK_128;
}
}
文件 4 的 21:EpochConfigurable.sol
pragma solidity ^0.8.17;
import "./Epoch.sol";
import "../Manager/ManagerModifier.sol";
import "./IEpochConfigurable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
contract EpochConfigurable is Pausable, ManagerModifier, IEpochConfigurable {
uint128 public EPOCH_CONFIG;
constructor(
address _manager,
uint64 _epochDuration,
uint64 _epochOffset
) ManagerModifier(_manager) {
EPOCH_CONFIG = Epoch.toConfig(_epochDuration, _epochOffset);
}
function currentEpoch() public view returns (uint) {
return epochAtTimestamp(block.timestamp);
}
function epochAtTimestamp(uint _timestamp) public view returns (uint) {
return Epoch.toEpochNumber(_timestamp, EPOCH_CONFIG);
}
function pause() external onlyAdmin {
_pause();
}
function unpause() external onlyAdmin {
_unpause();
}
function updateEpochConfig(uint64 duration, uint64 offset) external onlyAdmin {
EPOCH_CONFIG = Epoch.toConfig(duration, offset);
}
}
文件 5 的 21:FloatingPointConstants.sol
pragma solidity ^0.8.17;
uint256 constant DECIMAL_POINT = 10 ** 3;
uint256 constant ROUNDING_ADJUSTER = DECIMAL_POINT - 1;
int256 constant SIGNED_DECIMAL_POINT = int256(DECIMAL_POINT);
uint256 constant ONE_HUNDRED = 100 * DECIMAL_POINT;
uint256 constant ONE_HUNDRED_SQUARE = ONE_HUNDRED * ONE_HUNDRED;
int256 constant SIGNED_ONE_HUNDRED = 100 * SIGNED_DECIMAL_POINT;
int256 constant SIGNED_ONE_HUNDRED_SQUARE = SIGNED_ONE_HUNDRED * SIGNED_ONE_HUNDRED;
int256 constant SIGNED_ZERO = 0;
文件 6 的 21: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);
}
文件 7 的 21:IBatchAdventurerData.sol
pragma solidity ^0.8.4;
uint constant ADVENTURER_DATA_BASE = 0;
uint constant ADVENTURER_DATA_AOV = 1;
uint constant ADVENTURER_DATA_EXTENSION = 2;
interface IBatchAdventurerData {
function STORAGE(
address _addr,
uint256 _id,
uint256 _type,
uint256 _prop
) external view returns (uint24);
function add(address _addr, uint256 _id, uint256 _type, uint256 _prop, uint256 _val) external;
function addBatch(
address[] calldata _addr,
uint256[] calldata _id,
uint256 _type,
uint256[][] calldata _prop,
uint256[][] calldata _val
) external;
function addBatch(
address[] calldata _addr,
uint256[] calldata _id,
uint256 _type,
uint256 _prop,
uint256 _val
) external;
function addBatch(
address[] calldata _addr,
uint256[] calldata _id,
uint256 _type,
uint256 _prop,
uint256[] calldata _val
) external;
function update(address _addr, uint256 _id, uint256 _type, uint256 _prop, uint256 _val) external;
function updateRaw(address _addr, uint256 _id, uint256 _type, uint24[10] calldata _val) external;
function updateBatch(
address[] calldata _addr,
uint256[] calldata _id,
uint256 _type,
uint256 _prop,
uint256[] calldata _val
) external;
function updateBatchRaw(
address[] calldata _addr,
uint256[] calldata _id,
uint256 _type,
uint24[10][] calldata _val
) external;
function remove(address _addr, uint256 _id, uint256 _type, uint256 _prop, uint256 _val) external;
function removeBatch(
address[] calldata _addr,
uint256[] calldata _id,
uint256 _type,
uint256[][] calldata _prop,
uint256[][] calldata _val
) external;
function get(address _addr, uint256 _id, uint256 _type, uint256 _prop) external returns (uint256);
function getRaw(address _addr, uint256 _id, uint256 _type) external returns (uint24[10] memory);
function getMulti(
address _addr,
uint256 _id,
uint256 _type,
uint256[] calldata _prop
) external returns (uint256[] memory result);
function getBatch(
address[] calldata _addr,
uint256[] calldata _id,
uint256 _type,
uint256 _prop
) external returns (uint256[] memory);
function getBatchMulti(
address[] calldata _addrs,
uint256[] calldata _ids,
uint256 _type,
uint256[] calldata _props
) external returns (uint256[][] memory);
function getRawBatch(
address[] calldata _addrs,
uint256[] calldata _ids,
uint256 _type
) external returns (uint24[10][] memory result);
}
文件 8 的 21:IBattlePowerScouter.sol
pragma solidity ^0.8.17;
import "../lib/SigmoidFunction.sol";
struct BattlePowerScan {
uint256 probability;
int256 attackerBase;
int256 attackerFinal;
uint256 attackerLevel;
int256 opponentBase;
int256 opponentFinal;
uint256 opponentLevel;
}
enum DataType {
BASE,
ADVANCED,
EXTENSION,
ACTIONS
}
struct LevelAdjustment {
uint32 levelThreshold;
uint32 adjustmentCoefficient;
uint32 reverseAdjustmentCoefficient;
}
struct PeripheralRestriction {
DataType requirementType;
uint32 requirementId;
uint32 value;
}
struct PeripheralAdditiveBonus {
DataType bonusType;
uint32 bonusId;
uint32 value;
PeripheralRestriction[] restrictions;
StatAffinity affinity;
}
struct PeripheralMultiplicativeBonus {
DataType baseStatType;
uint32 baseStatId;
DataType bonusType;
uint32 bonusId;
uint32 value;
PeripheralRestriction[] restrictions;
}
struct StatAffinity {
bool enabled;
uint16[6] baseStats;
int24[6] coefficient;
RangeConfig sigmoidRange;
}
struct BattleUtility {
bool enabled;
LevelAdjustment adjustment;
PeripheralAdditiveBonus[] additiveBonuses;
PeripheralMultiplicativeBonus[] multiplicativeBonuses;
}
interface IBattlePowerScouter {
function baseBattlePower(
address _adventurerAddr,
uint256 _adventurerId
) external returns (int256 battlePower, uint256 level);
function scanBattlePower(
uint _fightEpoch,
address _adventurerAddr,
uint256 _adventurerId,
address _opponentAddr,
uint256 _opponentId,
uint256[] calldata _params
) external returns (BattlePowerScan memory);
function invalidateCache(address _adventurerAddr, uint256 _adventurerId) external;
function invalidateCaches(
address[] calldata _adventurerAddr,
uint256[] calldata _adventurerId
) external;
}
文件 9 的 21:IBattleRenown.sol
pragma solidity ^0.8.17;
import "../Manager/ManagerModifier.sol";
import "./IRenown.sol";
import "../lib/FloatingPointConstants.sol";
import "../Utils/Epoch.sol";
import "../Battle/IBattleVersusV3.sol";
import "../Utils/EpochConfigurable.sol";
struct RenownDelta {
int adventurer;
int opponent;
}
interface IBattleRenown {
function getRenown(
address _adventurerAddress,
uint256 _adventurerTokenId,
uint256 _level
) external returns (int renown);
function updateRenown(
address _adventurerAddress,
uint256 _adventurerTokenId,
address _opponentAddress,
uint256 _opponentTokenId,
FightResult calldata _fightResult
) external returns (RenownDelta memory result);
}
文件 10 的 21:IBattleRewardsDispenser.sol
pragma solidity ^0.8.17;
import "./IBattleVersusV3.sol";
interface IBattleRewardsDispenser {
function dispenseRewards(
address _owner,
uint256 _fightId,
uint256 _battleEpoch,
address _adventurerAddress,
uint256 _adventurerTokenId,
address _opponentAddress,
uint256 _opponentTokenId,
uint256[] calldata _params,
FightResult calldata result
) external returns (uint256 randomBase);
}
文件 11 的 21:IBattleVersusV3.sol
pragma solidity ^0.8.20;
import "./IBattlePowerScouter.sol";
struct FightData {
address advAddress;
uint256 advTokenId;
address oppAddress;
uint256 oppTokenId;
uint256[] params;
BattlePowerScan scan;
uint256 attackerRenown;
uint256 defenderRenown;
}
struct FightRequest {
address[] advAddresses;
uint256[] advTokenIds;
uint256[][] addEquipmentToArmoryIds;
uint256[][] addEquipmentToArmoryAmounts;
uint256[][] equipmentIds;
bytes32[][] advProofs;
address[] oppAddresses;
uint256[] oppTokenIds;
bytes32[][] oppProofs;
uint256[] slots;
uint256[][] params;
}
struct FightResult {
uint adventurerLevel;
int adventurerBp;
uint opponentLevel;
int opponentBp;
uint rounds;
uint wins;
uint losses;
bool overallWin;
uint[] rolls;
uint probability;
uint nextRandomBase;
}
文件 12 的 21:IEpochConfigurable.sol
pragma solidity ^0.8.17;
interface IEpochConfigurable {
function currentEpoch() external view returns (uint);
function epochAtTimestamp(uint _timestamp) external view returns (uint);
}
文件 13 的 21:IGloballyStakedTokenCalculator.sol
pragma solidity ^0.8.17;
interface IGloballyStakedTokenCalculator {
function currentGloballyStakedAverage(
uint _epochSpan
)
external
returns (
uint rawTotalStaked,
int totalStaked,
uint circulatingSupply,
int effectiveSupply,
uint percentage
);
function globallyStakedAverageView(
uint _epoch,
uint _epochSpan,
bool _includeCurrent
)
external
view
returns (
uint rawTotalStaked,
int totalStaked,
uint circulatingSupply,
int effectiveSupply,
uint percentage
);
function globallyStakedAverageBatch(
uint _epochStart,
uint _epochEnd,
uint _epochSpan
)
external
view
returns (
uint[] memory rawTotalStaked,
int[] memory totalStaked,
uint[] memory circulatingSupply,
int[] memory effectiveSupply,
uint[] memory percentage
);
function stakedAmountsBatch(
uint _epochStart,
uint _epochEnd
)
external
view
returns (address[] memory stakingAddresses, uint[][] memory stakedAmounts);
function circulatingSupplyBatch(
uint _epochStart,
uint _epochEnd
) external view returns (uint[] memory circulatingSupplies);
}
文件 14 的 21: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);
}
文件 15 的 21: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;
}
文件 16 的 21:IRenown.sol
pragma solidity ^0.8.17;
interface IRenown {
event RenownInitialized(address adventurerAddress, uint adventurerId, uint level, int baseAmount);
event RenownChange(address adventurerAddress, uint adventurerId, uint level, int delta);
function currentRenown(
address _tokenAddress,
uint256 _tokenId,
uint256 _level
) external view returns (int);
function currentRenowns(
address _tokenAddress1,
uint256 _tokenId1,
uint _level1,
address _tokenAddress2,
uint256 _tokenId2,
uint _level2
) external view returns (int, int);
function currentRenownBatch(
address[] calldata _tokenAddresses,
uint256[] calldata _tokenIds,
uint256[] calldata _levels
) external view returns (int[] memory);
function forceInitIfNeeded(
address _tokenAddress,
uint256 _tokenId,
uint _level
) external returns (int);
function change(address _tokenAddress, uint256 _tokenId, uint _level, int _delta) external;
function changeBatch(
address[] calldata _tokenAddresses,
uint256[] calldata _tokenIds,
uint256[] calldata _levels,
int[] calldata _deltas
) external;
function changeBatch(
address[] calldata _tokenAddresses,
uint256[] calldata _tokenIds,
uint256[] calldata _levels,
int _delta
) external;
}
文件 17 的 21: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");
_;
}
modifier onlyConfigManager() {
require(MANAGER.isManager(msg.sender, 4), "Manager: Not config manager");
_;
}
modifier onlyTokenSpender() {
require(MANAGER.isManager(msg.sender, 5), "Manager: Not token spender");
_;
}
modifier onlyTokenEmitter() {
require(MANAGER.isManager(msg.sender, 6), "Manager: Not token emitter");
_;
}
modifier onlyPauser() {
require(
MANAGER.isAdmin(msg.sender) || MANAGER.isManager(msg.sender, 6),
"Manager: Not pauser"
);
_;
}
}
文件 18 的 21: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());
}
}
文件 19 的 21:Random.sol
pragma solidity ^0.8.17;
import "./IArbSys.sol";
uint256 constant MIN_SAFE_NEXT_NUMBER_PRIME = 200033;
uint256 constant HIGH_RANGE_PRIME_OFFSET = 13;
library Random {
function startRandomBase(uint256 _highSalt, uint256 _lowSalt) internal view returns (uint256) {
return
uint256(
keccak256(
abi.encodePacked(
_getPreviousBlockhash(),
block.timestamp,
msg.sender,
_lowSalt,
_highSalt
)
)
);
}
function getNextRandom(
uint256 _randomBase,
uint256 _range
) internal view returns (uint256, uint256) {
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(_getPreviousBlockhash(), msg.sender, _randomBase, _range))
);
return (nextBaseNumber % _range, nextBaseNumber / nextNumberSeparator);
}
function _getPreviousBlockhash() internal view returns (bytes32) {
if (
block.chainid == 42161 ||
block.chainid == 42170 ||
block.chainid == 421613 ||
block.chainid == 421614 ||
block.chainid == 23011913 ||
block.chainid == 421611
) {
return ArbSys(address(0x64)).arbBlockHash(ArbSys(address(0x64)).arbBlockNumber() - 1);
} else {
return blockhash(block.number - 1);
}
}
}
文件 20 的 21:SigmoidFunction.sol
pragma solidity ^0.8.17;
import "./FloatingPointConstants.sol";
struct RangeConfig {
int24 leftCurveX;
int24 mid;
int24 rightCurveX;
}
struct SigmoidConfig {
int24 shiftY;
CurveConfig leftCurve;
CurveConfig rightCurve;
}
struct CurveConfig {
bool ascending;
int24 rangeY;
int24 yAdjustment;
int24 steepness;
int24 steepnessCoefficient;
}
library SigmoidFunction {
function calculate(
SigmoidConfig memory config,
RangeConfig memory range,
int x
) internal pure returns (int) {
if (x >= range.mid) {
return
_calculateCurve(config.rightCurve, int(range.rightCurveX), x - int(range.mid), -1) +
config.shiftY;
} else {
return
_calculateCurve(config.leftCurve, (range.leftCurveX), int(range.mid) - x, 1) +
config.shiftY;
}
}
function _calculateCurve(
CurveConfig memory config,
int rangeX,
int x,
int sign
) internal pure returns (int) {
if (!config.ascending) {
sign *= -1;
}
return
config.yAdjustment +
((SIGNED_ONE_HUNDRED +
((sign *
((rangeX * SIGNED_ONE_HUNDRED_SQUARE) /
(rangeX * SIGNED_ONE_HUNDRED + x * int(config.steepness)) -
SIGNED_ONE_HUNDRED)) * int(config.steepnessCoefficient)) /
SIGNED_ONE_HUNDRED) * int(config.rangeY)) /
SIGNED_ONE_HUNDRED;
}
}
文件 21 的 21:TraitConstants.sol
pragma solidity ^0.8.17;
library traits {
uint256 public constant ADV_TRAIT_GROUP_BASE = 0;
uint256 public constant ADV_TRAIT_BASE_LEVEL = 0;
uint256 public constant ADV_TRAIT_BASE_XP = 1;
uint256 public constant ADV_TRAIT_BASE_STRENGTH = 2;
uint256 public constant ADV_TRAIT_BASE_DEXTERITY = 3;
uint256 public constant ADV_TRAIT_BASE_CONSTITUTION = 4;
uint256 public constant ADV_TRAIT_BASE_INTELLIGENCE = 5;
uint256 public constant ADV_TRAIT_BASE_WISDOM = 6;
uint256 public constant ADV_TRAIT_BASE_CHARISMA = 7;
uint256 public constant ADV_TRAIT_BASE_CLASS = 8;
uint256 public constant ADV_TRAIT_GROUP_ADVANCED = 1;
uint256 public constant ADV_TRAIT_ADVANCED_ARCHETYPE = 0;
uint256 public constant ADV_TRAIT_ADVANCED_PROFESSION = 1;
uint256 public constant ADV_TRAIT_ADVANCED_TRAINING_POINTS = 2;
uint256 public constant LEGACY_ADV_BASE_TRAIT_XP = 0;
uint256 public constant LEGACY_ADV_BASE_TRAIT_XP_BROKEN = 1;
uint256 public constant LEGACY_ADV_BASE_TRAIT_STRENGTH = 2;
uint256 public constant LEGACY_ADV_BASE_TRAIT_DEXTERITY = 3;
uint256 public constant LEGACY_ADV_BASE_TRAIT_CONSTITUTION = 4;
uint256 public constant LEGACY_ADV_BASE_TRAIT_INTELLIGENCE = 5;
uint256 public constant LEGACY_ADV_BASE_TRAIT_WISDOM = 6;
uint256 public constant LEGACY_ADV_BASE_TRAIT_CHARISMA = 7;
uint256 public constant LEGACY_ADV_BASE_TRAIT_HP = 8;
uint256 public constant LEGACY_ADV_BASE_TRAIT_HP_USED = 9;
uint256 public constant LEGACY_ADV_AOV_TRAIT_LEVEL = 0;
uint256 public constant LEGACY_ADV_AOV_TRAIT_ARCHETYPE = 1;
uint256 public constant LEGACY_ADV_AOV_TRAIT_CLASS = 2;
uint256 public constant LEGACY_ADV_AOV_TRAIT_PROFESSION = 3;
function baseTraitNames() public pure returns (string[10] memory) {
return [
"Level",
"XP",
"Strength",
"Dexterity",
"Constitution",
"Intelligence",
"Wisdom",
"Charisma",
"Class",
""
];
}
function advancedTraitNames() public pure returns (string[2] memory) {
return ["Archetype", "Profession"];
}
function baseTraitName(uint256 traitId) public pure returns (string memory) {
return baseTraitNames()[traitId];
}
function advancedTraitName(uint256 traitId) public pure returns (string memory) {
return advancedTraitNames()[traitId];
}
}
{
"compilationTarget": {
"contracts/Battle/BattleRewardsDispenser.sol": "BattleRewardsDispenser"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_manager","type":"address"},{"internalType":"address","name":"_battleRenown","type":"address"},{"internalType":"address","name":"_lootboxDispenser","type":"address"},{"internalType":"address","name":"_adventurerData","type":"address"},{"internalType":"address","name":"_stakedTokenCalculator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fightId","type":"uint256"},{"indexed":false,"internalType":"int256","name":"adventurerRenown","type":"int256"},{"indexed":false,"internalType":"int256","name":"opponentRenown","type":"int256"},{"indexed":false,"internalType":"uint256","name":"lootBoxId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"xp","type":"uint256"}],"name":"BattleRewards","type":"event"},{"inputs":[],"name":"ADVENTURER_DATA","outputs":[{"internalType":"contract IBatchAdventurerData","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"AVERAGE_STAKED_EPOCH_SPAN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BATTLE_RENOWN","outputs":[{"internalType":"contract IBattleRenown","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOOTBOX_DISPENSER","outputs":[{"internalType":"contract ILootBoxDispenser","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOOTBOX_MAX_DROP_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOOTBOX_MIN_DROP_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOOTBOX_SPREAD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER","outputs":[{"internalType":"contract IManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKED_TOKEN_CALCULATOR","outputs":[{"internalType":"contract IGloballyStakedTokenCalculator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_probability","type":"uint256"}],"name":"currentDropRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentLootBoxChanceModifier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentLootBoxChanceModifierLastUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_fightId","type":"uint256"},{"internalType":"uint256","name":"_battleEpoch","type":"uint256"},{"internalType":"address","name":"_adventurerAddress","type":"address"},{"internalType":"uint256","name":"_adventurerTokenId","type":"uint256"},{"internalType":"address","name":"_opponentAddress","type":"address"},{"internalType":"uint256","name":"_opponentTokenId","type":"uint256"},{"internalType":"uint256[]","name":"_params","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"adventurerLevel","type":"uint256"},{"internalType":"int256","name":"adventurerBp","type":"int256"},{"internalType":"uint256","name":"opponentLevel","type":"uint256"},{"internalType":"int256","name":"opponentBp","type":"int256"},{"internalType":"uint256","name":"rounds","type":"uint256"},{"internalType":"uint256","name":"wins","type":"uint256"},{"internalType":"uint256","name":"losses","type":"uint256"},{"internalType":"bool","name":"overallWin","type":"bool"},{"internalType":"uint256[]","name":"rolls","type":"uint256[]"},{"internalType":"uint256","name":"probability","type":"uint256"},{"internalType":"uint256","name":"nextRandomBase","type":"uint256"}],"internalType":"struct FightResult","name":"result","type":"tuple"}],"name":"dispenseRewards","outputs":[{"internalType":"uint256","name":"randomBase","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lootBoxRewardRarityConfig","outputs":[{"internalType":"uint256","name":"lootBoxTotalChance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minDropRate","type":"uint256"},{"internalType":"uint256","name":"_maxDropRate","type":"uint256"},{"internalType":"uint256[]","name":"_chances","type":"uint256[]"},{"internalType":"uint256[]","name":"_minimumLevels","type":"uint256[]"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"updateLootboxConfig","outputs":[],"stateMutability":"nonpayable","type":"function"}]