Overview
S Balance
0 S
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
RandomnessBeacon
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 1000 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import {SkillLibrary} from "./libraries/SkillLibrary.sol"; import {IOracleCB} from "./interfaces/IOracleCB.sol"; import {ISamWitchVRF} from "./interfaces/ISamWitchVRF.sol"; import {IWorldActions} from "./interfaces/IWorldActions.sol"; // solhint-disable-next-line no-global-import import "./globals/all.sol"; contract RandomnessBeacon is UUPSUpgradeable, OwnableUpgradeable { using SkillLibrary for uint8; using SkillLibrary for Skill; event RequestSent(uint256 requestId, uint256 numWords, uint256 lastRandomWordsUpdatedTime); event RequestFulfilled(uint256 requestId, uint256 randomWord); error RandomWordsCannotBeUpdatedYet(); error CanOnlyRequestAfterTheNextCheckpoint(uint256 currentTime, uint256 checkpoint); error RequestAlreadyFulfilled(); error NoValidRandomWord(); error LengthMismatch(); error CallbackGasLimitTooHigh(); error CallerNotSamWitchVRF(); error RandomWordsAlreadyInitialized(); uint256 private constant NUM_WORDS = 1; uint256 public constant MIN_RANDOM_WORDS_UPDATE_TIME = 1 days; uint256 public constant NUM_DAYS_RANDOM_WORDS_INITIALIZED = 3; uint40 private _lastRandomWordsUpdatedTime; uint40 private _startTime; uint24 private _expectedGasLimitFulfill; ISamWitchVRF private _samWitchVRF; IOracleCB private _wishingWell; IOracleCB private _dailyRewardsScheduler; uint256 private _isRandomWordsInitialized; // Doesn't need to be packed with anything, only called on initialization uint256[] private _requestIds; // Each one is a set of random words for 1 day mapping(uint256 requestId => uint256 randomWord) private _randomWords; /// @dev Reverts if the caller is not the SamWitchVRF contract. modifier onlySamWitchVRF() { require(_msgSender() == address(_samWitchVRF), CallerNotSamWitchVRF()); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize(address vrf) external initializer { __Ownable_init(_msgSender()); __UUPSUpgradeable_init(); uint40 startTime = uint40( (block.timestamp / MIN_RANDOM_WORDS_UPDATE_TIME) * MIN_RANDOM_WORDS_UPDATE_TIME - (NUM_DAYS_RANDOM_WORDS_INITIALIZED + 1) * 1 days ); _startTime = startTime; // Floor to the nearest day 00:00 UTC _lastRandomWordsUpdatedTime = uint40(startTime + NUM_DAYS_RANDOM_WORDS_INITIALIZED * 1 days); _expectedGasLimitFulfill = 600_000; _samWitchVRF = ISamWitchVRF(vrf); } function requestIds(uint256 requestId) external view returns (uint256) { return _requestIds[requestId]; } function randomWords(uint256 requestId) external view returns (uint256) { return _randomWords[requestId]; } function lastRandomWordsUpdatedTime() external view returns (uint256) { return _lastRandomWordsUpdatedTime; } function requestRandomWords() external returns (uint256 requestId) { // Last one has not been fulfilled yet require( _requestIds.length == 0 || _randomWords[_requestIds[_requestIds.length - 1]] != 0, RandomWordsCannotBeUpdatedYet() ); uint40 newLastRandomWordsUpdatedTime = uint40(_lastRandomWordsUpdatedTime + MIN_RANDOM_WORDS_UPDATE_TIME); require( newLastRandomWordsUpdatedTime <= block.timestamp, CanOnlyRequestAfterTheNextCheckpoint(block.timestamp, newLastRandomWordsUpdatedTime) ); requestId = uint256(_samWitchVRF.requestRandomWords(NUM_WORDS, _expectedGasLimitFulfill)); _requestIds.push(requestId); _lastRandomWordsUpdatedTime = newLastRandomWordsUpdatedTime; emit RequestSent(requestId, NUM_WORDS, newLastRandomWordsUpdatedTime); return requestId; } function fulfillRandomWords(bytes32 requestId, uint256[] memory words) external onlySamWitchVRF { _fulfillRandomWords(uint256(requestId), words); } function _getRandomWordOffset(uint256 timestamp) private view returns (int) { if (timestamp < _startTime) { return -1; } return int((timestamp - _startTime) / MIN_RANDOM_WORDS_UPDATE_TIME); } function _getRandomWord(uint256 timestamp) private view returns (uint256) { int _offset = _getRandomWordOffset(timestamp); if (_offset < 0 || _requestIds.length <= uint256(_offset)) { return 0; } return _randomWords[_requestIds[uint256(_offset)]]; } function _getRandomComponent( bytes32 word, uint256 startTimestamp, uint256 endTimestamp, uint256 id ) private pure returns (bytes32) { return keccak256(abi.encodePacked(word, startTimestamp, endTimestamp, id)); } function _fulfillRandomWords(uint256 requestId, uint256[] memory fulfilledRandomWords) internal { require(_randomWords[requestId] == 0, RequestAlreadyFulfilled()); require(fulfilledRandomWords.length == NUM_WORDS, LengthMismatch()); uint256 randomWord = fulfilledRandomWords[0]; _randomWords[requestId] = randomWord; _wishingWell.newOracleRandomWords(randomWord); _dailyRewardsScheduler.newOracleRandomWords(randomWord); emit RequestFulfilled(requestId, randomWord); } function initializeAddresses(IOracleCB wishingWell, IOracleCB dailyRewardsScheduler) external onlyOwner { _wishingWell = IOracleCB(wishingWell); _dailyRewardsScheduler = IOracleCB(dailyRewardsScheduler); } function hasRandomWord(uint256 timestamp) external view returns (bool) { return _getRandomWord(timestamp) != 0; } function getRandomWord(uint256 timestamp) public view returns (uint256 randomWord) { randomWord = _getRandomWord(timestamp); require(randomWord != 0, NoValidRandomWord()); } function getMultipleWords(uint256 timestamp) public view returns (uint256[4] memory words) { for (uint256 i; i < 4; ++i) { words[i] = getRandomWord(timestamp - (i * 1 days)); } } function getRandomBytes( uint256 numTickets, uint256 startTimestamp, uint256 endTimestamp, uint256 id // player or pet id for instance ) external view returns (bytes memory randomBytes) { if (numTickets <= 16) { // 32 bytes bytes32 word = bytes32(getRandomWord(endTimestamp)); randomBytes = abi.encodePacked(_getRandomComponent(word, startTimestamp, endTimestamp, id)); } else if (numTickets <= MAX_UNIQUE_TICKETS) { // 4 * 32 bytes uint256[4] memory multipleWords = getMultipleWords(endTimestamp); for (uint256 i; i < 4; ++i) { multipleWords[i] = uint256(_getRandomComponent(bytes32(multipleWords[i]), startTimestamp, endTimestamp, id)); // XOR all the words with the first fresh random number to give more randomness to the existing random words if (i != 0) { multipleWords[i] = uint256(keccak256(abi.encodePacked(multipleWords[i] ^ multipleWords[0]))); } } randomBytes = abi.encodePacked(multipleWords); } else { assert(false); } } function getStartTime() external view returns (uint256) { return _startTime; } function initializeRandomWords() external onlyOwner { // Initialize a few days worth of random words so that we have enough data to fetch the first day require(_isRandomWordsInitialized == 0, RandomWordsAlreadyInitialized()); _isRandomWordsInitialized = 1; for (uint256 i; i < NUM_DAYS_RANDOM_WORDS_INITIALIZED; ++i) { uint256 requestId = 200 + i; _requestIds.push(requestId); emit RequestSent(requestId, NUM_WORDS, _startTime + (i * 1 days) + 1 days); uint256[] memory words = new uint256[](1); words[0] = uint256(keccak256(abi.encodePacked(block.chainid == 31337 ? address(31337) : address(this), i))); _fulfillRandomWords(requestId, words); } } function setExpectedGasLimitFulfill(uint256 gasLimit) external onlyOwner { require(gasLimit <= 3_000_000, CallbackGasLimitTooHigh()); _expectedGasLimitFulfill = uint24(gasLimit); } // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly ("memory-safe") { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly ("memory-safe") { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.20; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC-1967 compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC-1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.20; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.21; import {IBeacon} from "../beacon/IBeacon.sol"; import {IERC1967} from "../../interfaces/IERC1967.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This library provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots. */ library ERC1967Utils { /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit IERC1967.Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit IERC1967.AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the ERC-1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit IERC1967.BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC-1967 implementation slot: * ```solidity * contract ERC1967 { * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot. * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * TIP: Consider using this library along with {SlotDerivation}. */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct Int256Slot { int256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Int256Slot` with member `value` located at `slot`. */ function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } /** * @dev Returns a `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {Skill, Attire, CombatStyle, CombatStats} from "./misc.sol"; import {GuaranteedReward, RandomReward} from "./rewards.sol"; enum ActionQueueStrategy { OVERWRITE, APPEND, KEEP_LAST_IN_PROGRESS } struct QueuedActionInput { Attire attire; uint16 actionId; uint16 regenerateId; // Food (combat), maybe something for non-combat later uint16 choiceId; // Melee/Ranged/Magic (combat), logs, ore (non-combat) uint16 rightHandEquipmentTokenId; // Axe/Sword/bow, can be empty uint16 leftHandEquipmentTokenId; // Shield, can be empty uint24 timespan; // How long to queue the action for uint8 combatStyle; // CombatStyle specific style of combat uint40 petId; // id of the pet (can be empty) } struct QueuedAction { uint16 actionId; uint16 regenerateId; // Food (combat), maybe something for non-combat later uint16 choiceId; // Melee/Ranged/Magic (combat), logs, ore (non-combat) uint16 rightHandEquipmentTokenId; // Axe/Sword/bow, can be empty uint16 leftHandEquipmentTokenId; // Shield, can be empty uint24 timespan; // How long to queue the action for uint24 prevProcessedTime; // How long the action has been processed for previously uint24 prevProcessedXPTime; // How much XP has been gained for this action so far uint64 queueId; // id of this queued action bytes1 packed; // 1st bit is isValid (not used yet), 2nd bit is for hasPet (decides if the 2nd storage slot is read) uint8 combatStyle; uint24 reserved; // Next storage slot uint40 petId; // id of the pet (can be empty) } // This is only used as an input arg (and events) struct ActionInput { uint16 actionId; ActionInfo info; GuaranteedReward[] guaranteedRewards; RandomReward[] randomRewards; CombatStats combatStats; } struct ActionInfo { uint8 skill; bool actionChoiceRequired; // If true, then the user must choose an action choice uint24 xpPerHour; uint32 minXP; uint24 numSpawned; // Mostly for combat, capped respawn rate for xp/drops. Per hour, base 10000 uint16 handItemTokenIdRangeMin; // Inclusive uint16 handItemTokenIdRangeMax; // Inclusive uint8 successPercent; // 0-100 uint8 worldLocation; // 0 is the main starting world bool isFullModeOnly; bool isAvailable; uint16 questPrerequisiteId; } uint16 constant ACTIONCHOICE_MELEE_BASIC_SWORD = 1500; uint16 constant ACTIONCHOICE_MAGIC_SHADOW_BLAST = 2000; uint16 constant ACTIONCHOICE_RANGED_BASIC_BOW = 3000; // Allows for 2, 4 or 8 hour respawn time uint256 constant SPAWN_MUL = 1000; uint256 constant RATE_MUL = 1000; uint256 constant GUAR_MUL = 10; // Guaranteeded reward multiplier (1 decimal, allows for 2 hour action times) uint256 constant MAX_QUEUEABLE_ACTIONS = 3; // Available slots to queue actions
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import "./actions.sol"; import "./items.sol"; import "./misc.sol"; import "./players.sol"; import "./rewards.sol"; import "./quests.sol"; import "./promotions.sol"; import "./clans.sol"; import "./pets.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {IBank} from "../interfaces/IBank.sol"; enum ClanRank { NONE, // Not in a clan COMMONER, // Member of the clan SCOUT, // Invite and kick commoners COLONEL, // Can launch attacks and assign combatants TREASURER, // Can withdraw from bank LEADER, // Can edit clan details OWNER // Can do everything and transfer ownership } enum BattleResultEnum { DRAW, WIN, LOSE } struct ClanBattleInfo { uint40 lastClanIdAttackOtherClanIdCooldownTimestamp; uint8 numReattacks; uint40 lastOtherClanIdAttackClanIdCooldownTimestamp; uint8 numReattacksOtherClan; } // Packed for gas efficiency struct Vault { bool claimed; // Only applies to the first one, if it's claimed without the second one being claimed uint40 timestamp; uint80 amount; uint40 timestamp1; uint80 amount1; } struct VaultClanInfo { IBank bank; uint96 totalBrushLocked; // New storage slot uint40 attackingCooldownTimestamp; uint40 assignCombatantsCooldownTimestamp; bool currentlyAttacking; uint24 defendingVaultsOffset; uint40 blockAttacksTimestamp; uint8 blockAttacksCooldownHours; bool isInMMRArray; uint40 superAttackCooldownTimestamp; uint64[] playerIds; Vault[] defendingVaults; // Append only, and use defendingVaultsOffset to decide where the real start is } uint256 constant MAX_CLAN_COMBATANTS = 20; uint256 constant CLAN_WARS_GAS_PRICE_WINDOW_SIZE = 4; bool constant XP_EMITTED_ELSEWHERE = true;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; uint16 constant NONE = 0; uint16 constant COMBAT_BASE = 2048; // Melee uint16 constant SWORD_BASE = COMBAT_BASE; uint16 constant BRONZE_SWORD = SWORD_BASE; // Woodcutting (2816 - 3071) uint16 constant WOODCUTTING_BASE = 2816; uint16 constant BRONZE_AXE = WOODCUTTING_BASE; // Firemaking (3328 - 3583) uint16 constant FIRE_BASE = 3328; uint16 constant MAGIC_FIRE_STARTER = FIRE_BASE; uint16 constant FIRE_MAX = FIRE_BASE + 255; // Fishing (3072 - 3327) uint16 constant FISHING_BASE = 3072; uint16 constant NET_STICK = FISHING_BASE; // Mining (2560 - 2815) uint16 constant MINING_BASE = 2560; uint16 constant BRONZE_PICKAXE = MINING_BASE; // Magic uint16 constant STAFF_BASE = COMBAT_BASE + 50; uint16 constant TOTEM_STAFF = STAFF_BASE; // Ranged uint16 constant BOW_BASE = COMBAT_BASE + 100; uint16 constant BASIC_BOW = BOW_BASE; // Cooked fish uint16 constant COOKED_FISH_BASE = 11008; uint16 constant COOKED_FEOLA = COOKED_FISH_BASE + 3; // Scrolls uint16 constant SCROLL_BASE = 12032; uint16 constant SHADOW_SCROLL = SCROLL_BASE; // Boosts uint16 constant BOOST_BASE = 12800; uint16 constant COMBAT_BOOST = BOOST_BASE; uint16 constant XP_BOOST = BOOST_BASE + 1; uint16 constant GATHERING_BOOST = BOOST_BASE + 2; uint16 constant SKILL_BOOST = BOOST_BASE + 3; uint16 constant ABSENCE_BOOST = BOOST_BASE + 4; uint16 constant LUCKY_POTION = BOOST_BASE + 5; uint16 constant LUCK_OF_THE_DRAW = BOOST_BASE + 6; uint16 constant PRAY_TO_THE_BEARDIE = BOOST_BASE + 7; uint16 constant PRAY_TO_THE_BEARDIE_2 = BOOST_BASE + 8; uint16 constant PRAY_TO_THE_BEARDIE_3 = BOOST_BASE + 9; uint16 constant BOOST_RESERVED_1 = BOOST_BASE + 10; uint16 constant BOOST_RESERVED_2 = BOOST_BASE + 11; uint16 constant BOOST_RESERVED_3 = BOOST_BASE + 12; uint16 constant GO_OUTSIDE = BOOST_BASE + 13; uint16 constant RAINING_RARES = BOOST_BASE + 14; uint16 constant CLAN_BOOSTER = BOOST_BASE + 15; uint16 constant CLAN_BOOSTER_2 = BOOST_BASE + 16; uint16 constant CLAN_BOOSTER_3 = BOOST_BASE + 17; uint16 constant BOOST_RESERVED_4 = BOOST_BASE + 18; uint16 constant BOOST_RESERVED_5 = BOOST_BASE + 19; uint16 constant BOOST_RESERVED_6 = BOOST_BASE + 20; uint16 constant BOOST_MAX = 13055; // Eggs uint16 constant EGG_BASE = 12544; uint16 constant SECRET_EGG_1_TIER1 = EGG_BASE; uint16 constant SECRET_EGG_2_TIER1 = EGG_BASE + 1; uint16 constant EGG_MAX = 12799; // Miscs uint16 constant MISC_BASE = 65535; uint16 constant RAID_PASS = MISC_BASE - 1; struct BulkTransferInfo { uint256[] tokenIds; uint256[] amounts; address to; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; enum BoostType { NONE, ANY_XP, COMBAT_XP, NON_COMBAT_XP, GATHERING, ABSENCE, PASSIVE_SKIP_CHANCE, // Clan wars PVP_BLOCK, PVP_REATTACK, PVP_SUPER_ATTACK, // Combat stats COMBAT_FIXED } struct Equipment { uint16 itemTokenId; uint24 amount; } enum Skill { NONE, COMBAT, // This is a helper which incorporates all combat skills, attack <-> magic, defence, health etc MELEE, RANGED, MAGIC, DEFENCE, HEALTH, RESERVED_COMBAT, MINING, WOODCUTTING, FISHING, SMITHING, THIEVING, CRAFTING, COOKING, FIREMAKING, FARMING, ALCHEMY, FLETCHING, FORGING, RESERVED2, RESERVED3, RESERVED4, RESERVED5, RESERVED6, RESERVED7, RESERVED8, RESERVED9, RESERVED10, RESERVED11, RESERVED12, RESERVED13, RESERVED14, RESERVED15, RESERVED16, RESERVED17, RESERVED18, RESERVED19, RESERVED20, TRAVELING // Helper Skill for travelling } struct Attire { uint16 head; uint16 neck; uint16 body; uint16 arms; uint16 legs; uint16 feet; uint16 ring; uint16 reserved1; } struct CombatStats { // From skill points int16 meleeAttack; int16 magicAttack; int16 rangedAttack; int16 health; // These include equipment int16 meleeDefence; int16 magicDefence; int16 rangedDefence; } enum CombatStyle { NONE, ATTACK, DEFENCE }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {Skill} from "./misc.sol"; enum PetSkin { NONE, DEFAULT, OG, ONEKIN, FROST, CRYSTAL, ANNIV1, KRAGSTYR } enum PetEnhancementType { NONE, MELEE, MAGIC, RANGED, DEFENCE, HEALTH, MELEE_AND_DEFENCE, MAGIC_AND_DEFENCE, RANGED_AND_DEFENCE } struct Pet { Skill skillEnhancement1; uint8 skillFixedEnhancement1; uint8 skillPercentageEnhancement1; Skill skillEnhancement2; uint8 skillFixedEnhancement2; uint8 skillPercentageEnhancement2; uint40 lastAssignmentTimestamp; address owner; // Will be used as an optimization to avoid having to look up the owner of the pet in another storage slot bool isTransferable; // New storage slot uint24 baseId; // These are used when training a pet uint40 lastTrainedTimestamp; uint8 skillFixedEnhancementMax1; // The maximum possible value for skillFixedEnhancement1 when training uint8 skillFixedEnhancementMax2; uint8 skillPercentageEnhancementMax1; uint8 skillPercentageEnhancementMax2; uint64 xp; } struct BasePetMetadata { string description; uint8 tier; PetSkin skin; PetEnhancementType enhancementType; Skill skillEnhancement1; uint8 skillFixedMin1; uint8 skillFixedMax1; uint8 skillFixedIncrement1; uint8 skillPercentageMin1; uint8 skillPercentageMax1; uint8 skillPercentageIncrement1; uint8 skillMinLevel1; Skill skillEnhancement2; uint8 skillFixedMin2; uint8 skillFixedMax2; uint8 skillFixedIncrement2; uint8 skillPercentageMin2; uint8 skillPercentageMax2; uint8 skillPercentageIncrement2; uint8 skillMinLevel2; uint16 fixedStarThreshold; uint16 percentageStarThreshold; bool isTransferable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {QueuedAction} from "./actions.sol"; import {Skill, BoostType, CombatStats, Equipment} from "./misc.sol"; import {PlayerQuest} from "./quests.sol"; // 4 bytes for each level. 0x00000000 is the first level, 0x00000054 is the second, etc. bytes constant XP_BYTES = hex"0000000000000054000000AE0000010E00000176000001E60000025E000002DE00000368000003FD0000049B00000546000005FC000006C000000792000008730000096400000A6600000B7B00000CA400000DE100000F36000010A200001229000013CB0000158B0000176B0000196E00001B9400001DE20000205A000022FF000025D5000028DD00002C1E00002F99000033540000375200003B9A000040300000451900004A5C00004FFF0000560900005C810000637000006ADD000072D100007B570000847900008E42000098BE0000A3F90000B0020000BCE70000CAB80000D9860000E9630000FA6200010C990001201D0001350600014B6F0001637300017D2E000198C10001B64E0001D5F80001F7E600021C430002433B00026CFD000299BE0002C9B30002FD180003342B00036F320003AE730003F23D00043AE3000488BE0004DC2F0005359B000595700005FC2400066A360006E02D00075E990007E6160008774C000912EB0009B9B4000A6C74000B2C06000BF956000CD561000DC134000EBDF3000FCCD40010EF2400122648001373BF0014D9230016582C0017F2B00019AAA9001B8234001D7B95001F99390021DDBC00244BE60026E6B60029B15F002CAF51002FE43A0033540D00370303003AF5A4003F30CC0043B9B0004895E3004DCB600053609100595C53005FC6030066A585006E034D0075E86C007E5E980087703B0091287D009B935300A6BD8F00B2B4EE00BF882800CD470500DC026F00EBCC8500FCB8B7010EDBD5"; uint256 constant MAX_LEVEL = 140; // Original max level uint256 constant MAX_LEVEL_1 = 160; // TODO: Update later uint256 constant MAX_LEVEL_2 = 190; // TODO: Update later enum EquipPosition { NONE, HEAD, NECK, BODY, ARMS, LEGS, FEET, RING, SPARE2, LEFT_HAND, RIGHT_HAND, BOTH_HANDS, QUIVER, MAGIC_BAG, FOOD, AUX, // wood, seeds etc.. BOOST_VIAL, EXTRA_BOOST_VIAL, GLOBAL_BOOST_VIAL, CLAN_BOOST_VIAL, PASSIVE_BOOST_VIAL, LOCKED_VAULT, TERRITORY } struct Player { uint40 currentActionStartTimestamp; // The in-progress start time of the first queued action Skill currentActionProcessedSkill1; // The skill that the queued action has already gained XP in uint24 currentActionProcessedXPGained1; // The amount of XP that the queued action has already gained Skill currentActionProcessedSkill2; uint24 currentActionProcessedXPGained2; Skill currentActionProcessedSkill3; uint24 currentActionProcessedXPGained3; uint16 currentActionProcessedFoodConsumed; uint16 currentActionProcessedBaseInputItemsConsumedNum; // e.g scrolls, crafting materials etc Skill skillBoosted1; // The first skill that is boosted Skill skillBoosted2; // The second skill that is boosted (if applicable) uint48 totalXP; uint16 totalLevel; // Doesn't not automatically add new skills to it bytes1 packedData; // Contains worldLocation in first 6 bits (0 is the main starting randomnessBeacon), and full mode unlocked in the upper most bit // TODO: Can be up to 7 QueuedAction[] actionQueue; string name; // Raw name } struct Item { EquipPosition equipPosition; bytes1 packedData; // 0x1 exists, upper most bit is full mode uint16 questPrerequisiteId; // Can it be transferred? bool isTransferable; // TODO: Move into packedData // Food uint16 healthRestored; // Boost vial BoostType boostType; uint16 boostValue; // Varies, could be the % increase uint24 boostDuration; // How long the effect of the boost last // Combat stats int16 meleeAttack; int16 magicAttack; int16 rangedAttack; int16 meleeDefence; int16 magicDefence; int16 rangedDefence; int16 health; // Minimum requirements in this skill to use this item (can be NONE) Skill skill; uint32 minXP; } // Used for events struct BoostInfo { uint40 startTime; uint24 duration; uint16 value; uint16 itemTokenId; // Get the effect of it BoostType boostType; } struct PlayerBoostInfo { uint40 startTime; uint24 duration; uint16 value; uint16 itemTokenId; // Get the effect of it BoostType boostType; // Another boost slot (for global/clan boosts this is the "last", for users it is the "extra") uint40 extraOrLastStartTime; uint24 extraOrLastDuration; uint16 extraOrLastValue; uint16 extraOrLastItemTokenId; BoostType extraOrLastBoostType; uint40 cooldown; // Just put here for packing } // This is effectively a ratio to produce 1 of outputTokenId. // Available choices that can be undertaken for an action struct ActionChoiceInput { uint8 skill; // Skill that this action choice is related to uint24 rate; // Rate of output produced per hour (base 1000) 3 decimals uint24 xpPerHour; uint16[] inputTokenIds; uint24[] inputAmounts; uint16 outputTokenId; uint8 outputAmount; uint8 successPercent; // 0-100 uint16 handItemTokenIdRangeMin; // Inclusive uint16 handItemTokenIdRangeMax; // Inclusive bool isFullModeOnly; bool isAvailable; uint16 questPrerequisiteId; uint8[] skills; // Skills required to do this action choice uint32[] skillMinXPs; // Min XP in the corresponding skills to be able to do this action choice int16[] skillDiffs; // How much the skill is increased/decreased by this action choice } struct ActionChoice { uint8 skill; // Skill that this action choice is related to uint24 rate; // Rate of output produced per hour (base 1000) 3 decimals uint24 xpPerHour; uint16 inputTokenId1; uint24 inputAmount1; uint16 inputTokenId2; uint24 inputAmount2; uint16 inputTokenId3; uint24 inputAmount3; uint16 outputTokenId; uint8 outputAmount; uint8 successPercent; // 0-100 uint8 skill1; // Skills required to do this action choice, commonly the same as skill uint32 skillMinXP1; // Min XP in the skill to be able to do this action choice int16 skillDiff1; // How much the skill is increased/decreased by this action choice uint8 skill2; uint32 skillMinXP2; int16 skillDiff2; uint8 skill3; uint32 skillMinXP3; int16 skillDiff3; uint16 handItemTokenIdRangeMin; // Inclusive uint16 handItemTokenIdRangeMax; // Inclusive uint16 questPrerequisiteId; // FullMode is last bit, first 6 bits is worldLocation, // 2nd last bit is if there are other skills in next storage slot to check, // 3rd last bit if the input amounts should be used bytes1 packedData; } // Must be in the same order as Skill enum struct PackedXP { uint40 melee; uint40 ranged; uint40 magic; uint40 defence; uint40 health; uint40 reservedCombat; bytes2 packedDataIsMaxed; // 2 bits per skill to indicate whether the maxed skill is reached. I think this was added in case we added a new max level which a user had already passed so old & new levels are the same and it would not trigger a level up event. // Next slot uint40 mining; uint40 woodcutting; uint40 fishing; uint40 smithing; uint40 thieving; uint40 crafting; bytes2 packedDataIsMaxed1; // 2 bits per skill to indicate whether the maxed skill is reached // Next slot uint40 cooking; uint40 firemaking; uint40 farming; uint40 alchemy; uint40 fletching; uint40 forging; bytes2 packedDataIsMaxed2; // 2 bits per skill to indicate whether the maxed skill is reached } struct AvatarInfo { string name; string description; string imageURI; Skill[2] startSkills; // Can be NONE } struct PastRandomRewardInfo { uint16 itemTokenId; uint24 amount; uint64 queueId; } struct PendingQueuedActionEquipmentState { uint256[] consumedItemTokenIds; uint256[] consumedAmounts; uint256[] producedItemTokenIds; uint256[] producedAmounts; } struct PendingQueuedActionMetadata { uint32 xpGained; // total xp gained uint32 rolls; bool died; uint16 actionId; uint64 queueId; uint24 elapsedTime; uint24 xpElapsedTime; uint8 checkpoint; } struct PendingQueuedActionData { // The amount of XP that the queued action has already gained Skill skill1; uint24 xpGained1; Skill skill2; // Most likely health uint24 xpGained2; Skill skill3; // Could come uint24 xpGained3; // How much food is consumed in the current action so far uint16 foodConsumed; // How many base consumables are consumed in the current action so far uint16 baseInputItemsConsumedNum; } struct PendingQueuedActionProcessed { // XP gained during this session Skill[] skills; uint32[] xpGainedSkills; // Data for the current action which has been previously processed, this is used to store on the Player PendingQueuedActionData currentAction; } struct QuestState { uint256[] consumedItemTokenIds; uint256[] consumedAmounts; uint256[] rewardItemTokenIds; uint256[] rewardAmounts; PlayerQuest[] activeQuestInfo; uint256[] questsCompleted; Skill[] skills; // Skills gained XP in uint32[] xpGainedSkills; // XP gained in these skills } struct LotteryWinnerInfo { uint16 lotteryId; uint24 raffleId; uint16 itemTokenId; uint16 amount; bool instantConsume; uint64 playerId; } struct PendingQueuedActionState { // These 2 are in sync. Separated to reduce gas/deployment costs as these are passed down many layers. PendingQueuedActionEquipmentState[] equipmentStates; PendingQueuedActionMetadata[] actionMetadatas; QueuedAction[] remainingQueuedActions; PastRandomRewardInfo[] producedPastRandomRewards; uint256[] xpRewardItemTokenIds; uint256[] xpRewardAmounts; uint256[] dailyRewardItemTokenIds; uint256[] dailyRewardAmounts; PendingQueuedActionProcessed processedData; bytes32 dailyRewardMask; QuestState quests; uint256 numPastRandomRewardInstancesToRemove; uint8 worldLocation; LotteryWinnerInfo lotteryWinner; } struct FullAttireBonusInput { Skill skill; uint8 bonusXPPercent; uint8 bonusRewardsPercent; // 3 = 3% uint16[5] itemTokenIds; // 0 = head, 1 = body, 2 arms, 3 body, 4 = feet } // Contains everything you need to create an item struct ItemInput { CombatStats combatStats; uint16 tokenId; EquipPosition equipPosition; bool isTransferable; bool isFullModeOnly; bool isAvailable; uint16 questPrerequisiteId; // Minimum requirements in this skill Skill skill; uint32 minXP; // Food uint16 healthRestored; // Boost BoostType boostType; uint16 boostValue; // Varies, could be the % increase uint24 boostDuration; // How long the effect of the boost vial last // uri string metadataURI; string name; } /* Order head, neck, body, arms, legs, feet, ring, reserved1, leftHandEquipment, rightHandEquipment, Not used yet: input1, input2,input3, regenerate, reserved2, reserved3 */ struct CheckpointEquipments { uint16[16] itemTokenIds; uint16[16] balances; } struct ActivePlayerInfo { uint64 playerId; uint40 checkpoint; uint24 timespan; uint24 timespan1; uint24 timespan2; } uint8 constant START_LEVEL = 17; // Needs updating when there is a new skill. Only useful for new heroes. uint256 constant MAX_UNIQUE_TICKETS = 64; // Used in a bunch of places uint256 constant IS_FULL_MODE_BIT = 7; // Passive/Instant/InstantVRF/Actions/ActionChoices/Item action uint256 constant IS_AVAILABLE_BIT = 6; // Passive actions uint256 constant HAS_RANDOM_REWARDS_BIT = 5; // The rest use world location for first 4 bits // Queued action uint256 constant HAS_PET_BIT = 2; uint256 constant IS_VALID_BIT = 1;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; enum Promotion { NONE, STARTER, HALLOWEEN_2023, XMAS_2023, HALLOWEEN_2024, HOLIDAY4, // Just have placeholders for now HOLIDAY5, HOLIDAY6, HOLIDAY7, HOLIDAY8, HOLIDAY9, HOLIDAY10 } enum PromotionMintStatus { NONE, SUCCESS, PROMOTION_ALREADY_CLAIMED, ORACLE_NOT_CALLED, MINTING_OUTSIDE_AVAILABLE_DATE, PLAYER_DOES_NOT_QUALIFY, PLAYER_NOT_HIT_ENOUGH_CLAIMS_FOR_STREAK_BONUS, DEPENDENT_QUEST_NOT_COMPLETED } struct PromotionInfoInput { Promotion promotion; uint40 startTime; uint40 endTime; // Exclusive uint8 numDailyRandomItemsToPick; // Number of items to pick uint40 minTotalXP; // Minimum xp required to claim uint256 tokenCost; // Cost in brush to start the promotion, max 16mil // Special promotion specific (like 1kin) uint8 redeemCodeLength; // Length of the redeem code bool adminOnly; // Only admins can mint the promotion, like for 1kin (Not used yet) bool promotionTiedToUser; // If the promotion is tied to a user bool promotionTiedToPlayer; // If the promotion is tied to the player bool promotionMustOwnPlayer; // Must own the player to get the promotion // Evolution specific bool evolvedHeroOnly; // Only allow evolved heroes to claim // Multiday specific bool isMultiday; // The promotion is multi-day uint256 brushCostMissedDay; // Cost in brush to mint the promotion if they miss a day (in ether), max 25.6 (base 100) uint8 numDaysHitNeededForStreakBonus; // How many days to hit for the streak bonus uint8 numDaysClaimablePeriodStreakBonus; // If there is a streak bonus, how many days to claim it after the promotion ends. If no final day bonus, set to 0 uint8 numRandomStreakBonusItemsToPick1; // Number of items to pick for the streak bonus uint8 numRandomStreakBonusItemsToPick2; // Number of random items to pick for the streak bonus uint16[] randomStreakBonusItemTokenIds1; uint32[] randomStreakBonusAmounts1; uint16[] randomStreakBonusItemTokenIds2; uint32[] randomStreakBonusAmounts2; uint16[] guaranteedStreakBonusItemTokenIds; uint16[] guaranteedStreakBonusAmounts; // Single and multiday uint16[] guaranteedItemTokenIds; // Guaranteed items for the promotions each day, if empty then they are handled in a specific way for the promotion like daily rewards uint32[] guaranteedAmounts; // Corresponding amounts to the itemTokenIds uint16[] randomItemTokenIds; // Possible items for the promotions each day, if empty then they are handled in a specific way for the promotion like daily rewards uint32[] randomAmounts; // Corresponding amounts to the randomItemTokenIds // Quests uint16 questPrerequisiteId; } struct PromotionInfo { Promotion promotion; uint40 startTime; uint8 numDays; uint8 numDailyRandomItemsToPick; // Number of items to pick uint40 minTotalXP; // Minimum xp required to claim uint24 tokenCost; // Cost in brush to mint the promotion (in ether), max 16mil // Quests uint16 questPrerequisiteId; // Special promotion specific (like 1kin), could pack these these later uint8 redeemCodeLength; // Length of the redeem code bool adminOnly; // Only admins can mint the promotion, like for 1kin bool promotionTiedToUser; // If the promotion is tied to a user bool promotionTiedToPlayer; // If the promotion is tied to the player bool promotionMustOwnPlayer; // Must own the player to get the promotion // Evolution specific bool evolvedHeroOnly; // Only allow evolved heroes to claim // Multiday specific bool isMultiday; // The promotion is multi-day uint8 brushCostMissedDay; // Cost in brush to mint the promotion if they miss a day (in ether), max 25.5, base 100 uint8 numDaysHitNeededForStreakBonus; // How many days to hit for the streak bonus uint8 numDaysClaimablePeriodStreakBonus; // If there is a streak bonus, how many days to claim it after the promotion ends. If no final day bonus, set to 0 uint8 numRandomStreakBonusItemsToPick1; // Number of items to pick for the streak bonus uint8 numRandomStreakBonusItemsToPick2; // Number of random items to pick for the streak bonus // Misc uint16[] randomStreakBonusItemTokenIds1; uint32[] randomStreakBonusAmounts1; uint16[] randomStreakBonusItemTokenIds2; // Not used yet uint32[] randomStreakBonusAmounts2; // Not used yet uint16[] guaranteedStreakBonusItemTokenIds; // Not used yet uint16[] guaranteedStreakBonusAmounts; // Not used yet // Single and multiday uint16[] guaranteedItemTokenIds; // Guaranteed items for the promotions each day, if empty then they are handled in a specific way for the promotion like daily rewards uint32[] guaranteedAmounts; // Corresponding amounts to the itemTokenIds uint16[] randomItemTokenIds; // Possible items for the promotions each day, if empty then they are handled in a specific way for the promotion like daily rewards uint32[] randomAmounts; // Corresponding amounts to the randomItemTokenIds } uint256 constant BRUSH_COST_MISSED_DAY_MUL = 10;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {Skill} from "./misc.sol"; struct QuestInput { uint16 dependentQuestId; // The quest that must be completed before this one can be started uint16 actionId1; // action to do uint16 actionNum1; // how many (up to 65535) uint16 actionId2; // another action to do uint16 actionNum2; // how many (up to 65535) uint16 actionChoiceId; // actionChoice to perform uint16 actionChoiceNum; // how many to do (base number), (up to 65535) Skill skillReward; // The skill to reward XP to uint24 skillXPGained; // The amount of XP to give (up to 65535) uint16 rewardItemTokenId1; // Reward an item uint16 rewardAmount1; // amount of the reward (up to 65535) uint16 rewardItemTokenId2; // Reward another item uint16 rewardAmount2; // amount of the reward (up to 65535) uint16 burnItemTokenId; // Burn an item uint16 burnAmount; // amount of the burn (up to 65535) uint16 questId; // Unique id for this quest bool isFullModeOnly; // If true this quest requires the user be evolved uint8 worldLocation; // 0 is the main starting world } struct Quest { uint16 dependentQuestId; // The quest that must be completed before this one can be started uint16 actionId1; // action to do uint16 actionNum1; // how many (up to 65535) uint16 actionId2; // another action to do uint16 actionNum2; // how many (up to 65535) uint16 actionChoiceId; // actionChoice to perform uint16 actionChoiceNum; // how many to do (base number), (up to 65535) Skill skillReward; // The skill to reward XP to uint24 skillXPGained; // The amount of XP to give (up to 65535) uint16 rewardItemTokenId1; // Reward an item uint16 rewardAmount1; // amount of the reward (up to 65535) uint16 rewardItemTokenId2; // Reward another item uint16 rewardAmount2; // amount of the reward (up to 65535) uint16 burnItemTokenId; // Burn an item uint16 burnAmount; // amount of the burn (up to 65535) uint16 reserved; // Reserved for future use (previously was questId and cleared) bytes1 packedData; // FullMode is last bit, first 6 bits is worldLocation } struct PlayerQuest { uint32 questId; uint16 actionCompletedNum1; uint16 actionCompletedNum2; uint16 actionChoiceCompletedNum; uint16 burnCompletedAmount; } uint256 constant QUEST_PURSE_STRINGS = 5; // MAKE SURE THIS MATCHES definitions
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {BoostType, Equipment} from "./misc.sol"; struct GuaranteedReward { uint16 itemTokenId; uint16 rate; // num per hour (base 10, 1 decimal) for actions and num per duration for passive actions } struct RandomReward { uint16 itemTokenId; uint16 chance; // out of 65535 uint8 amount; // out of 255 } struct PendingRandomReward { uint16 actionId; uint40 startTime; uint24 xpElapsedTime; uint16 boostItemTokenId; uint24 elapsedTime; uint40 boostStartTime; // When the boost was started uint24 sentinelElapsedTime; // Full equipment at the time this was generated uint8 fullAttireBonusRewardsPercent; uint64 queueId; // TODO: Could reduce this if more stuff is needed } struct ActionRewards { uint16 guaranteedRewardTokenId1; uint16 guaranteedRewardRate1; // Num per hour base 10 (1 decimal) for actions (Max 6553.5 per hour), num per duration for passive actions uint16 guaranteedRewardTokenId2; uint16 guaranteedRewardRate2; uint16 guaranteedRewardTokenId3; uint16 guaranteedRewardRate3; // Random chance rewards uint16 randomRewardTokenId1; uint16 randomRewardChance1; // out of 65535 uint8 randomRewardAmount1; // out of 255 uint16 randomRewardTokenId2; uint16 randomRewardChance2; uint8 randomRewardAmount2; uint16 randomRewardTokenId3; uint16 randomRewardChance3; uint8 randomRewardAmount3; uint16 randomRewardTokenId4; uint16 randomRewardChance4; uint8 randomRewardAmount4; // No more room in this storage slot! } struct XPThresholdReward { uint32 xpThreshold; Equipment[] rewards; } enum InstantVRFActionType { NONE, GENERIC, FORGING, EGG } struct InstantVRFActionInput { uint16 actionId; uint16[] inputTokenIds; uint24[] inputAmounts; bytes data; InstantVRFActionType actionType; bool isFullModeOnly; bool isAvailable; uint16 questPrerequisiteId; } struct InstantVRFRandomReward { uint16 itemTokenId; uint16 chance; // out of 65535 uint16 amount; // out of 65535 } uint256 constant MAX_GUARANTEED_REWARDS_PER_ACTION = 3; uint256 constant MAX_RANDOM_REWARDS_PER_ACTION = 4; uint256 constant MAX_REWARDS_PER_ACTION = MAX_GUARANTEED_REWARDS_PER_ACTION + MAX_RANDOM_REWARDS_PER_ACTION; uint256 constant MAX_CONSUMED_PER_ACTION = 3; uint256 constant MAX_QUEST_REWARDS = 2; uint256 constant TIER_1_DAILY_REWARD_START_XP = 0; uint256 constant TIER_2_DAILY_REWARD_START_XP = 7_650; uint256 constant TIER_3_DAILY_REWARD_START_XP = 33_913; uint256 constant TIER_4_DAILY_REWARD_START_XP = 195_864; uint256 constant TIER_5_DAILY_REWARD_START_XP = 784_726; uint256 constant TIER_6_DAILY_REWARD_START_XP = 2_219_451; // 4 bytes for each threshold, starts at 500 xp in decimal bytes constant XP_THRESHOLD_REWARDS = hex"00000000000001F4000003E8000009C40000138800002710000075300000C350000186A00001D4C0000493E0000557300007A120000927C0000B71B0000DBBA0000F424000124F800016E360001B7740001E8480002625A0002932E0002DC6C0003567E0003D0900004C4B40005B8D80006ACFC0007A1200008954400098968000A7D8C000B71B0000C65D4000D59F8000E4E1C0";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IBank { function initialize() external; function initializeAddresses( uint256 clanId, address bankRegistry, address bankRelay, address playerNFT, address itemNFT, address clans, address players, address lockedBankVaults, address raids ) external; function depositToken(address sender, address from, uint256 playerId, address token, uint256 amount) external; function setAllowBreachedCapacity(bool allow) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface IOracleCB { function newOracleRandomWords(uint256 randomWord) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; interface ISamWitchVRF { function requestRandomWords(uint256 numWords, uint256 callbackGasLimit) external returns (bytes32 requestId); function fulfillRandomWords( bytes32 requestId, address oracle, address fulfillAddress, uint256 callbackGasLimit, uint256 numWords, uint256[2] calldata publicKey, uint256[4] calldata proof, uint256[2] calldata uPoint, uint256[4] calldata vComponents ) external returns (bool callSuccess); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {CombatStats, Skill} from "../globals/misc.sol"; import {ActionChoice} from "../globals/players.sol"; import {ActionRewards} from "../globals/rewards.sol"; import {ActionInfo} from "../globals/actions.sol"; interface IWorldActions { function getXPPerHour(uint16 actionId, uint16 actionChoiceId) external view returns (uint24 xpPerHour); function getNumSpawn(uint16 actionId) external view returns (uint256 numSpawned); function getActionSuccessPercentAndMinXP(uint16 actionId) external view returns (uint8 successPercent, uint32 minXP); function getCombatStats(uint16 actionId) external view returns (CombatStats memory stats); function getActionChoice(uint16 actionId, uint16 choiceId) external view returns (ActionChoice memory choice); function getRewardsHelper( uint16 actionId ) external view returns (ActionRewards memory, Skill skill, uint256 numSpawned); // , uint8 worldLocation); function getSkill(uint256 actionId) external view returns (Skill skill); function getActionRewards(uint256 actionId) external view returns (ActionRewards memory); function getActionInfo(uint256 actionId) external view returns (ActionInfo memory info); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {Skill} from "../globals/misc.sol"; library SkillLibrary { error InvalidSkillId(uint8 skill); function _asSkill(uint8 skill) internal pure returns (Skill) { require(skill >= uint8(type(Skill).min) && skill <= uint8(type(Skill).max), InvalidSkillId(skill)); return Skill(skill); } function _isSkill(uint8 skill) internal pure returns (bool) { return _isSkill(_asSkill(skill)); } function _isSkill(uint8 skill, Skill check) internal pure returns (bool) { return _isSkill(_asSkill(skill), check); } function _isSkillCombat(uint8 skill) internal pure returns (bool) { return _isSkillCombat(_asSkill(skill)); } function _isSkillNone(uint8 skill) internal pure returns (bool) { return _isSkillNone(_asSkill(skill)); } function _asUint8(Skill skill) internal pure returns (uint8) { return uint8(skill); } function _isSkill(Skill skill) internal pure returns (bool) { return !_isSkill(skill, Skill.NONE); } function _isSkill(Skill skill, Skill check) internal pure returns (bool) { return skill == check; } function _isSkillCombat(Skill skill) internal pure returns (bool) { return _isSkill(skill, Skill.COMBAT); } function _isSkillNone(Skill skill) internal pure returns (bool) { return _isSkill(skill, Skill.NONE); } }
{ "evmVersion": "cancun", "optimizer": { "enabled": true, "runs": 1000, "details": { "yul": true } }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"CallbackGasLimitTooHigh","type":"error"},{"inputs":[],"name":"CallerNotSamWitchVRF","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentTime","type":"uint256"},{"internalType":"uint256","name":"checkpoint","type":"uint256"}],"name":"CanOnlyRequestAfterTheNextCheckpoint","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"LengthMismatch","type":"error"},{"inputs":[],"name":"NoValidRandomWord","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"RandomWordsAlreadyInitialized","type":"error"},{"inputs":[],"name":"RandomWordsCannotBeUpdatedYet","type":"error"},{"inputs":[],"name":"RequestAlreadyFulfilled","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","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":false,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"randomWord","type":"uint256"}],"name":"RequestFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numWords","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastRandomWordsUpdatedTime","type":"uint256"}],"name":"RequestSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"MIN_RANDOM_WORDS_UPDATE_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NUM_DAYS_RANDOM_WORDS_INITIALIZED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256[]","name":"words","type":"uint256[]"}],"name":"fulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getMultipleWords","outputs":[{"internalType":"uint256[4]","name":"words","type":"uint256[4]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTickets","type":"uint256"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getRandomBytes","outputs":[{"internalType":"bytes","name":"randomBytes","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"getRandomWord","outputs":[{"internalType":"uint256","name":"randomWord","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"hasRandomWord","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"vrf","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IOracleCB","name":"wishingWell","type":"address"},{"internalType":"contract IOracleCB","name":"dailyRewardsScheduler","type":"address"}],"name":"initializeAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastRandomWordsUpdatedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"randomWords","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"requestIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"requestRandomWords","outputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasLimit","type":"uint256"}],"name":"setExpectedGasLimitFulfill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a080604052346100c257306080525f5160206116e05f395f51905f525460ff8160401c166100b3576002600160401b03196001600160401b03821601610060575b60405161161990816100c78239608051818181610c420152610d360152f35b6001600160401b0319166001600160401b039081175f5160206116e05f395f51905f525581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f80610041565b63f92ee8a960e01b5f5260045ffd5b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80631929f7b314610ff357806330b7bdad14610f8d5780634f1ef28614610cba57806352d1902d14610c28578063604fefb714610ace5780636528f09a14610ab1578063715018a614610a1a578063770d0441146109ff5780637fe4cf6b146108b25780638796ba8c146108855780638da5cb5b14610840578063ad3cb1cc146107dd578063b8e719a714610762578063be52e34f1461067e578063beff730f14610654578063c4d66de8146103eb578063c828371e146103c5578063cc76b9111461039f578063debde2841461037c578063e0c8628914610180578063e5df71fc1461013a5763f2fde38b1461010b575f80fd5b346101365760203660031901126101365761013461012761101b565b61012f6112d5565b6111d3565b005b5f80fd5b3461013657602036600319011261013657610156600435611172565b604051905f825b6004821061016a57608084f35b602080600192855181520193019101909161015d565b34610136575f36600319011261013657600554801590811561034c575b5015610324575f5464ffffffffff81166201518081018091116103105764ffffffffff164281116102e157602062ffffff60446001600160a01b0360015416945f60405196879485937f1b739ef10000000000000000000000000000000000000000000000000000000085526001600486015260501c1660248401525af19182156102d6575f92610282575b6020837ff98e18bb2828ff6fd29ca6214d585469dd4c2f311d2b765ab247985ba08b111b606085610259846110bf565b8064ffffffffff195f5416175f55604051908482526001868301526040820152a1604051908152f35b91506020823d6020116102ce575b8161029d60209383611031565b81010312610136579051907ff98e18bb2828ff6fd29ca6214d585469dd4c2f311d2b765ab247985ba08b111b610229565b3d9150610290565b6040513d5f823e3d90fd5b7f1351c940000000000000000000000000000000000000000000000000000000005f524260045260245260445ffd5b634e487b7160e01b5f52601160045260245ffd5b7f974b4f8a000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f198101915081116103105761036190611093565b90549060031b1c5f52600660205260405f205415158161019d565b34610136575f36600319011261013657602064ffffffffff5f5416604051908152f35b346101365760203660031901126101365760206103bd600435611138565b604051908152f35b34610136575f36600319011261013657602064ffffffffff5f5460281c16604051908152f35b346101365760203660031901126101365761040461101b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549060ff8260401c16159167ffffffffffffffff81168015908161064c575b6001149081610642575b159081610639575b506106115767ffffffffffffffff1981166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055826105d2575b5061049b611500565b6104a3611500565b6104ac336111d3565b6104b4611500565b620151804204906201518082029180830462015180149015171561031057620545ff1982019182116103105764ffffffffff82165f54906203f48081018091116103105764ffffffffff6c0927c0000000000000000000009269ffffffffff00000000006001600160a01b039660281b16906cffffffffffffffffffffffffff191617911617175f55166001600160a01b0319600154161760015561055557005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005582610492565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b90501584610456565b303b15915061044e565b849150610444565b34610136576020366003190112610136576004355f526006602052602060405f2054604051908152f35b346101365760403660031901126101365760243567ffffffffffffffff811161013657366023820112156101365780600401359067ffffffffffffffff821161074e578160051b60208101926106d76040519485611031565b8352602460208401918301019136831161013657602401905b82821061073e57836001600160a01b036001541633036107165761013490600435611334565b7f580ae425000000000000000000000000000000000000000000000000000000005f5260045ffd5b81358152602091820191016106f0565b634e487b7160e01b5f52604160045260245ffd5b346101365760203660031901126101365760043561077e6112d5565b622dc6c081116107b5576cffffff000000000000000000005f549160501b16906cffffff000000000000000000001916175f555f80f35b7fbfbc293b000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610136575f3660031901126101365761083c6040516107fe604082611031565b600581527f352e302e30000000000000000000000000000000000000000000000000000000602082015260405191829160208352602083019061106f565b0390f35b34610136575f3660031901126101365760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101365760203660031901126101365760206108a3600435611093565b90549060031b1c604051908152f35b34610136576080366003190112610136576044356064356024356004356010811161091b575090826108ef926108ea61083c95611138565b6114a1565b60405190602082015260208152610907604082611031565b60405191829160208352602083019061106f565b9091906040106109eb5761092e83611172565b925f5b60048110610981575050505060405190602082015f905b6004821061096b5750505080608061083c925261096660a082611031565b610907565b6020806001928551815201930191019091610948565b8061099a8484876109946001968b61111a565b516114a1565b6109a4828861111a565b52806109b1575b01610931565b6109bb818761111a565b5186511860405160208101918252602081526109d8604082611031565b5190206109e5828861111a565b526109ab565b634e487b7160e01b5f52600160045260245ffd5b34610136575f36600319011261013657602060405160038152f35b34610136575f36600319011261013657610a326112d5565b5f6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610136575f366003190112610136576020604051620151808152f35b34610136575f36600319011261013657610ae66112d5565b600454610c0057600160045546617a6914602060405f5b60038110610b0757005b8060c801908160c81161031057610b1d826110bf565b64ffffffffff5f5460281c1662015180820282810462015180148315171561031057810180911161031057620151808101809111610310576001927ff98e18bb2828ff6fd29ca6214d585469dd4c2f311d2b765ab247985ba08b111b6060610bf49387519084825287602083015288820152a1845190610b9d8683611031565b848252863660208401378715610bfa57617a695b865160208101916bffffffffffffffffffffffff199060601b16825285603482015260348152610be2605482611031565b519020610bee8361110d565b52611334565b01610afd565b30610bb1565b7fbb4ae23d000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610136575f366003190112610136576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610c925760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b604036600319011261013657610cce61101b565b6024359067ffffffffffffffff8211610136573660238301121561013657816004013590610cfb82611053565b91610d096040519384611031565b8083526020830193366024838301011161013657815f926024602093018737840101526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016803014908115610f58575b50610c9257610d6e6112d5565b6001600160a01b038116926040517f52d1902d000000000000000000000000000000000000000000000000000000008152602081600481885afa5f9181610f24575b50610dc85784634c9c8ce360e01b5f5260045260245ffd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc869203610ef95750823b15610ee757806001600160a01b03197f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2825115610eb5575f8091610134945190845af43d15610ead573d91610e9183611053565b92610e9f6040519485611031565b83523d5f602085013e611557565b606091611557565b50505034610ebf57005b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b7faa1d49a4000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9091506020813d602011610f50575b81610f4060209383611031565b8101031261013657519086610db0565b3d9150610f33565b90506001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416141584610d61565b3461013657604036600319011261013657610fa661101b565b602435906001600160a01b038216809203610136576001600160a01b0390610fcc6112d5565b166001600160a01b031960025416176002556001600160a01b031960035416176003555f80f35b3461013657602036600319011261013657602061101160043561128e565b1515604051908152f35b600435906001600160a01b038216820361013657565b90601f8019910116810190811067ffffffffffffffff82111761074e57604052565b67ffffffffffffffff811161074e57601f01601f191660200190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6005548110156110ab5760055f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b6005546801000000000000000081101561074e57600181016005556005548110156110ab5760055f527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00155565b8051156110ab5760200190565b9060048110156110ab5760051b0190565b9190820391821161031057565b6111419061128e565b90811561114a57565b7fb4190460000000000000000000000000000000000000000000000000000000005f5260045ffd5b9060405191611182608084611031565b6080368437825f5b6004811061119757505050565b62015180810290808204620151801481151715610310576111c26111bd6001938661112b565b611138565b6111cc828561111a565b520161118a565b6001600160a01b03168015611262576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b611297906114d3565b5f811280156112c9575b6112c4576112ae90611093565b90549060031b1c5f52600660205260405f205490565b505f90565b508060055411156112a1565b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416330361130857565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b905f90825f52600660205260405f20546114795760018151036114515761135a9061110d565b5190825f5260066020528160405f20556001600160a01b0360025416803b15610136575f80916024604051809481936327fe556d60e21b83528860048401525af180156102d65761143e575b506001600160a01b0360035416803b1561143a578180916024604051809481936327fe556d60e21b83528860048401525af1801561142f57611417575b50507f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d59160409182519182526020820152a1565b611422828092611031565b61142c57806113e3565b80fd5b6040513d84823e3d90fd5b5080fd5b61144a91505f90611031565b5f5f6113a6565b7fff633a38000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f533d99dd000000000000000000000000000000000000000000000000000000005f5260045ffd5b9290916040519260208401948552604084015260608301526080820152608081526114cd60a082611031565b51902090565b64ffffffffff5f5460281c16908181106114f95762015180916114f59161112b565b0490565b50505f1990565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561152f57565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b90611594575080511561156c57805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b815115806115da575b6115a5575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b1561159d56fea2646970667358221220b9ce35991d2db9cf3f4c8239582d4e7d7b416b59700c3ea6e86f326132a53f8e64736f6c634300081c0033f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c80631929f7b314610ff357806330b7bdad14610f8d5780634f1ef28614610cba57806352d1902d14610c28578063604fefb714610ace5780636528f09a14610ab1578063715018a614610a1a578063770d0441146109ff5780637fe4cf6b146108b25780638796ba8c146108855780638da5cb5b14610840578063ad3cb1cc146107dd578063b8e719a714610762578063be52e34f1461067e578063beff730f14610654578063c4d66de8146103eb578063c828371e146103c5578063cc76b9111461039f578063debde2841461037c578063e0c8628914610180578063e5df71fc1461013a5763f2fde38b1461010b575f80fd5b346101365760203660031901126101365761013461012761101b565b61012f6112d5565b6111d3565b005b5f80fd5b3461013657602036600319011261013657610156600435611172565b604051905f825b6004821061016a57608084f35b602080600192855181520193019101909161015d565b34610136575f36600319011261013657600554801590811561034c575b5015610324575f5464ffffffffff81166201518081018091116103105764ffffffffff164281116102e157602062ffffff60446001600160a01b0360015416945f60405196879485937f1b739ef10000000000000000000000000000000000000000000000000000000085526001600486015260501c1660248401525af19182156102d6575f92610282575b6020837ff98e18bb2828ff6fd29ca6214d585469dd4c2f311d2b765ab247985ba08b111b606085610259846110bf565b8064ffffffffff195f5416175f55604051908482526001868301526040820152a1604051908152f35b91506020823d6020116102ce575b8161029d60209383611031565b81010312610136579051907ff98e18bb2828ff6fd29ca6214d585469dd4c2f311d2b765ab247985ba08b111b610229565b3d9150610290565b6040513d5f823e3d90fd5b7f1351c940000000000000000000000000000000000000000000000000000000005f524260045260245260445ffd5b634e487b7160e01b5f52601160045260245ffd5b7f974b4f8a000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f198101915081116103105761036190611093565b90549060031b1c5f52600660205260405f205415158161019d565b34610136575f36600319011261013657602064ffffffffff5f5416604051908152f35b346101365760203660031901126101365760206103bd600435611138565b604051908152f35b34610136575f36600319011261013657602064ffffffffff5f5460281c16604051908152f35b346101365760203660031901126101365761040461101b565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00549060ff8260401c16159167ffffffffffffffff81168015908161064c575b6001149081610642575b159081610639575b506106115767ffffffffffffffff1981166001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055826105d2575b5061049b611500565b6104a3611500565b6104ac336111d3565b6104b4611500565b620151804204906201518082029180830462015180149015171561031057620545ff1982019182116103105764ffffffffff82165f54906203f48081018091116103105764ffffffffff6c0927c0000000000000000000009269ffffffffff00000000006001600160a01b039660281b16906cffffffffffffffffffffffffff191617911617175f55166001600160a01b0319600154161760015561055557005b68ff0000000000000000197ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b68ffffffffffffffffff191668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005582610492565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b90501584610456565b303b15915061044e565b849150610444565b34610136576020366003190112610136576004355f526006602052602060405f2054604051908152f35b346101365760403660031901126101365760243567ffffffffffffffff811161013657366023820112156101365780600401359067ffffffffffffffff821161074e578160051b60208101926106d76040519485611031565b8352602460208401918301019136831161013657602401905b82821061073e57836001600160a01b036001541633036107165761013490600435611334565b7f580ae425000000000000000000000000000000000000000000000000000000005f5260045ffd5b81358152602091820191016106f0565b634e487b7160e01b5f52604160045260245ffd5b346101365760203660031901126101365760043561077e6112d5565b622dc6c081116107b5576cffffff000000000000000000005f549160501b16906cffffff000000000000000000001916175f555f80f35b7fbfbc293b000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610136575f3660031901126101365761083c6040516107fe604082611031565b600581527f352e302e30000000000000000000000000000000000000000000000000000000602082015260405191829160208352602083019061106f565b0390f35b34610136575f3660031901126101365760206001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346101365760203660031901126101365760206108a3600435611093565b90549060031b1c604051908152f35b34610136576080366003190112610136576044356064356024356004356010811161091b575090826108ef926108ea61083c95611138565b6114a1565b60405190602082015260208152610907604082611031565b60405191829160208352602083019061106f565b9091906040106109eb5761092e83611172565b925f5b60048110610981575050505060405190602082015f905b6004821061096b5750505080608061083c925261096660a082611031565b610907565b6020806001928551815201930191019091610948565b8061099a8484876109946001968b61111a565b516114a1565b6109a4828861111a565b52806109b1575b01610931565b6109bb818761111a565b5186511860405160208101918252602081526109d8604082611031565b5190206109e5828861111a565b526109ab565b634e487b7160e01b5f52600160045260245ffd5b34610136575f36600319011261013657602060405160038152f35b34610136575f36600319011261013657610a326112d5565b5f6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031981167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610136575f366003190112610136576020604051620151808152f35b34610136575f36600319011261013657610ae66112d5565b600454610c0057600160045546617a6914602060405f5b60038110610b0757005b8060c801908160c81161031057610b1d826110bf565b64ffffffffff5f5460281c1662015180820282810462015180148315171561031057810180911161031057620151808101809111610310576001927ff98e18bb2828ff6fd29ca6214d585469dd4c2f311d2b765ab247985ba08b111b6060610bf49387519084825287602083015288820152a1845190610b9d8683611031565b848252863660208401378715610bfa57617a695b865160208101916bffffffffffffffffffffffff199060601b16825285603482015260348152610be2605482611031565b519020610bee8361110d565b52611334565b01610afd565b30610bb1565b7fbb4ae23d000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610136575f366003190112610136576001600160a01b037f00000000000000000000000050590a161d5c11b157b2a11097b32117622939c6163003610c925760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b604036600319011261013657610cce61101b565b6024359067ffffffffffffffff8211610136573660238301121561013657816004013590610cfb82611053565b91610d096040519384611031565b8083526020830193366024838301011161013657815f926024602093018737840101526001600160a01b037f00000000000000000000000050590a161d5c11b157b2a11097b32117622939c616803014908115610f58575b50610c9257610d6e6112d5565b6001600160a01b038116926040517f52d1902d000000000000000000000000000000000000000000000000000000008152602081600481885afa5f9181610f24575b50610dc85784634c9c8ce360e01b5f5260045260245ffd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc869203610ef95750823b15610ee757806001600160a01b03197f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2825115610eb5575f8091610134945190845af43d15610ead573d91610e9183611053565b92610e9f6040519485611031565b83523d5f602085013e611557565b606091611557565b50505034610ebf57005b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b7faa1d49a4000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9091506020813d602011610f50575b81610f4060209383611031565b8101031261013657519086610db0565b3d9150610f33565b90506001600160a01b037f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416141584610d61565b3461013657604036600319011261013657610fa661101b565b602435906001600160a01b038216809203610136576001600160a01b0390610fcc6112d5565b166001600160a01b031960025416176002556001600160a01b031960035416176003555f80f35b3461013657602036600319011261013657602061101160043561128e565b1515604051908152f35b600435906001600160a01b038216820361013657565b90601f8019910116810190811067ffffffffffffffff82111761074e57604052565b67ffffffffffffffff811161074e57601f01601f191660200190565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b6005548110156110ab5760055f5260205f2001905f90565b634e487b7160e01b5f52603260045260245ffd5b6005546801000000000000000081101561074e57600181016005556005548110156110ab5760055f527f036b6384b5eca791c62761152d0c79bb0604c104a5fb6f4eb0703f3154bb3db00155565b8051156110ab5760200190565b9060048110156110ab5760051b0190565b9190820391821161031057565b6111419061128e565b90811561114a57565b7fb4190460000000000000000000000000000000000000000000000000000000005f5260045ffd5b9060405191611182608084611031565b6080368437825f5b6004811061119757505050565b62015180810290808204620151801481151715610310576111c26111bd6001938661112b565b611138565b6111cc828561111a565b520161118a565b6001600160a01b03168015611262576001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054826001600160a01b03198216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b611297906114d3565b5f811280156112c9575b6112c4576112ae90611093565b90549060031b1c5f52600660205260405f205490565b505f90565b508060055411156112a1565b6001600160a01b037f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416330361130857565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b905f90825f52600660205260405f20546114795760018151036114515761135a9061110d565b5190825f5260066020528160405f20556001600160a01b0360025416803b15610136575f80916024604051809481936327fe556d60e21b83528860048401525af180156102d65761143e575b506001600160a01b0360035416803b1561143a578180916024604051809481936327fe556d60e21b83528860048401525af1801561142f57611417575b50507f5c69e7026b653d8606b5613bb00fd8c4b0504b1cbe8db600c406faac180924d59160409182519182526020820152a1565b611422828092611031565b61142c57806113e3565b80fd5b6040513d84823e3d90fd5b5080fd5b61144a91505f90611031565b5f5f6113a6565b7fff633a38000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f533d99dd000000000000000000000000000000000000000000000000000000005f5260045ffd5b9290916040519260208401948552604084015260608301526080820152608081526114cd60a082611031565b51902090565b64ffffffffff5f5460281c16908181106114f95762015180916114f59161112b565b0490565b50505f1990565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561152f57565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b90611594575080511561156c57805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b815115806115da575b6115a5575090565b6001600160a01b03907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b1561159d56fea2646970667358221220b9ce35991d2db9cf3f4c8239582d4e7d7b416b59700c3ea6e86f326132a53f8e64736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.