Overview
S Balance
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:
GenericInstantVRFActionStrategy
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 9999999 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 {IInstantVRFActionStrategy} from "./interfaces/IInstantVRFActionStrategy.sol"; import {Skill} from "../globals/players.sol"; import {InstantVRFActionInput, InstantVRFActionType, InstantVRFRandomReward} from "../globals/rewards.sol"; import {NONE} from "../globals/items.sol"; contract GenericInstantVRFActionStrategy is UUPSUpgradeable, OwnableUpgradeable, IInstantVRFActionStrategy { error TooManyRandomRewards(); error RandomRewardSpecifiedWithoutTokenId(); error RandomRewardSpecifiedWithoutChance(); error RandomRewardSpecifiedWithoutAmount(); error RandomRewardChanceMustBeInOrder(); error RandomRewardItemNoDuplicates(); error OnlyInstantVRFActions(); struct InstantVRFAction { uint16[30] randomRewardInfo; // Can have up to 5 different random reward tokens. Order is tokenId, chance, amount etc } mapping(uint256 actionId => InstantVRFAction action) private _actions; address private _instantVRFActions; modifier onlyInstantVRFActions() { require(_instantVRFActions == _msgSender(), OnlyInstantVRFActions()); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize(address instantVRFActions) external initializer { __UUPSUpgradeable_init(); __Ownable_init(_msgSender()); _instantVRFActions = instantVRFActions; } function setAction(InstantVRFActionInput calldata input) external override onlyInstantVRFActions { (, InstantVRFRandomReward[] memory randomRewards) = abi.decode(input.data, (uint8, InstantVRFRandomReward[])); _checkRandomRewards(randomRewards); _actions[input.actionId] = _packAction(randomRewards); } function getRandomRewards( uint256 actionId, uint256 actionAmount, uint256[] calldata randomWords, uint256 randomWordStartIndex ) external view override returns ( uint256[] memory producedItemTokenIds, uint256[] memory producedItemsAmounts, uint256[] memory producedPetBaseIds ) { producedItemTokenIds = new uint256[](actionAmount); producedItemsAmounts = new uint256[](actionAmount); InstantVRFRandomReward[] memory randomRewards = _setupRandomRewards(actionId); uint256 length = randomRewards.length; if (length != 0) { uint256 numWords = actionAmount / 16 + ((actionAmount % 16) == 0 ? 0 : 1); bytes memory randomBytes = abi.encodePacked(randomWords[randomWordStartIndex:randomWordStartIndex + numWords]); for (uint256 i; i < actionAmount; ++i) { uint16 rand = _getSlice(randomBytes, i); InstantVRFRandomReward memory randomReward; for (uint256 j; j < length; ++j) { if (rand > randomRewards[j].chance) { break; } randomReward = randomRewards[j]; } producedItemTokenIds[i] = randomReward.itemTokenId; producedItemsAmounts[i] = randomReward.amount; } } } function _getSlice(bytes memory b, uint256 index) private pure returns (uint16) { uint256 key = index * 2; return uint16(b[key] | (bytes2(b[key + 1]) >> 8)); } function _setupRandomRewards(uint256 actionId) private view returns (InstantVRFRandomReward[] memory randomRewards) { // Read the strategy from the actionId InstantVRFAction storage action = _actions[actionId]; randomRewards = new InstantVRFRandomReward[](action.randomRewardInfo.length / 3); uint256 randomRewardLength; for (uint256 i; i < action.randomRewardInfo.length / 3; ++i) { if (action.randomRewardInfo[i * 3] == 0) { break; } randomRewards[randomRewardLength] = InstantVRFRandomReward( action.randomRewardInfo[i * 3], action.randomRewardInfo[i * 3 + 1], action.randomRewardInfo[i * 3 + 2] ); ++randomRewardLength; } assembly ("memory-safe") { mstore(randomRewards, randomRewardLength) } } function _checkRandomRewards(InstantVRFRandomReward[] memory randomRewards) private pure { uint256 length = randomRewards.length; // Check random rewards are correct require(length <= 10, TooManyRandomRewards()); for (uint256 i; i < length; ++i) { require(randomRewards[i].itemTokenId != 0, RandomRewardSpecifiedWithoutTokenId()); require(randomRewards[i].chance != 0, RandomRewardSpecifiedWithoutChance()); require(randomRewards[i].amount != 0, RandomRewardSpecifiedWithoutAmount()); if (i != length - 1) { require(randomRewards[i].chance > randomRewards[i + 1].chance, RandomRewardChanceMustBeInOrder()); } } } function _packAction( InstantVRFRandomReward[] memory randomRewards ) private pure returns (InstantVRFAction memory instantVRFAction) { uint256 length = randomRewards.length; instantVRFAction = InstantVRFAction({ randomRewardInfo: [ length != 0 ? randomRewards[0].itemTokenId : NONE, length != 0 ? randomRewards[0].chance : 0, length != 0 ? randomRewards[0].amount : 0, length > 1 ? randomRewards[1].itemTokenId : NONE, length > 1 ? randomRewards[1].chance : 0, length > 1 ? randomRewards[1].amount : 0, length > 2 ? randomRewards[2].itemTokenId : NONE, length > 2 ? randomRewards[2].chance : 0, length > 2 ? randomRewards[2].amount : 0, length > 3 ? randomRewards[3].itemTokenId : NONE, length > 3 ? randomRewards[3].chance : 0, length > 3 ? randomRewards[3].amount : 0, length > 4 ? randomRewards[4].itemTokenId : NONE, length > 4 ? randomRewards[4].chance : 0, length > 4 ? randomRewards[4].amount : 0, length > 5 ? randomRewards[5].itemTokenId : NONE, length > 5 ? randomRewards[5].chance : 0, length > 5 ? randomRewards[5].amount : 0, length > 6 ? randomRewards[6].itemTokenId : NONE, length > 6 ? randomRewards[6].chance : 0, length > 6 ? randomRewards[6].amount : 0, length > 7 ? randomRewards[7].itemTokenId : NONE, length > 7 ? randomRewards[7].chance : 0, length > 7 ? randomRewards[7].amount : 0, length > 8 ? randomRewards[8].itemTokenId : NONE, length > 8 ? randomRewards[8].chance : 0, length > 8 ? randomRewards[8].amount : 0, length > 9 ? randomRewards[9].itemTokenId : NONE, length > 9 ? randomRewards[9].chance : 0, length > 9 ? randomRewards[9].amount : 0 ] }); } // TODO, Delete later if there are other changes made in this file. Just to change up the bytecode for a rogue deployment function version() external pure returns (uint256) { return 1; } // 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; 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 {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; 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; import {InstantVRFActionInput, InstantVRFActionType} from "../../globals/rewards.sol"; import {Skill} from "../../globals/players.sol"; interface IInstantVRFActionStrategy { function getRandomRewards( uint256 actionId, uint256 actionAmount, uint256[] calldata randomWords, uint256 randomWordStartIndex ) external view returns ( uint256[] memory producedItemTokenIds, uint256[] memory producedItemsAmounts, uint256[] memory producedPetBaseIds ); function setAction(InstantVRFActionInput calldata input) external; }
{ "evmVersion": "cancun", "optimizer": { "enabled": true, "runs": 9999999, "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":[{"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":"NotInitializing","type":"error"},{"inputs":[],"name":"OnlyInstantVRFActions","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":"RandomRewardChanceMustBeInOrder","type":"error"},{"inputs":[],"name":"RandomRewardItemNoDuplicates","type":"error"},{"inputs":[],"name":"RandomRewardSpecifiedWithoutAmount","type":"error"},{"inputs":[],"name":"RandomRewardSpecifiedWithoutChance","type":"error"},{"inputs":[],"name":"RandomRewardSpecifiedWithoutTokenId","type":"error"},{"inputs":[],"name":"TooManyRandomRewards","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":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"actionId","type":"uint256"},{"internalType":"uint256","name":"actionAmount","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"},{"internalType":"uint256","name":"randomWordStartIndex","type":"uint256"}],"name":"getRandomRewards","outputs":[{"internalType":"uint256[]","name":"producedItemTokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"producedItemsAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"producedPetBaseIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"instantVRFActions","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","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":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"actionId","type":"uint16"},{"internalType":"uint16[]","name":"inputTokenIds","type":"uint16[]"},{"internalType":"uint24[]","name":"inputAmounts","type":"uint24[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum InstantVRFActionType","name":"actionType","type":"uint8"},{"internalType":"bool","name":"isFullModeOnly","type":"bool"},{"internalType":"bool","name":"isAvailable","type":"bool"},{"internalType":"uint16","name":"questPrerequisiteId","type":"uint16"}],"internalType":"struct InstantVRFActionInput","name":"input","type":"tuple"}],"name":"setAction","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"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
60a080604052346100c257306080525f516020611d745f395f51905f525460ff8160401c166100b3576002600160401b03196001600160401b03821601610060575b604051611cad90816100c782396080518181816105bc0152610b300152f35b6001600160401b0319166001600160401b039081175f516020611d745f395f51905f525581527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f80610041565b63f92ee8a960e01b5f5260045ffd5b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80632e28ad1714610deb5780634f1ef28614610a89578063508c72a31461063457806352d1902d1461057757806354fd4d501461053e578063715018a6146104645780638da5cb5b146103f4578063ad3cb1cc14610342578063c4d66de8146100d45763f2fde38b14610087575f80fd5b346100d05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d0576100ce6100c1611776565b6100c9611b1b565b611a01565b005b5f80fd5b346100d05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05761010b611776565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159167ffffffffffffffff82168015908161033a575b6001149081610330575b159081610327575b506102ff57818360017fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000073ffffffffffffffffffffffffffffffffffffffff9516177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556102aa575b506101ce611b87565b6101d6611b87565b6101de611b87565b6101e733611a01565b167fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015561021757005b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055836101c5565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050158461015c565b303b159150610154565b84915061014a565b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d057604080519061037f81836117d1565b6005825260208201917f352e302e3000000000000000000000000000000000000000000000000000000083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8351948593602085525180918160208701528686015e5f85828601015201168101030190f35b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d057602073ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05761049a611b1b565b5f73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300547fffffffffffffffffffffffff000000000000000000000000000000000000000081167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d057602060405160018152f35b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016300361060c5760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b346100d05760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05760243560443567ffffffffffffffff81116100d057366023820112156100d05780600401359067ffffffffffffffff82116100d0573660248360051b830101116100d057606435926106b4816118a6565b926106be826118a6565b926004355f525f60205260405f2090610160927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06040519461070081876117d1565b600a8652015f5b818110610a725750505f925f905b600a8210610982575b505082845282610798575b505050505061074b92506107599060405193849360608552606085019061184c565b90838203602085015261184c565b818103604083015260206060519182815201906080905f5b81811061077f575050500390f35b8251845285945060209384019390920191600101610771565b600f8516610973576107ba6107b460ff5f5b168760041c6118f5565b896118f5565b908189116100d05781116100d05787900396604051977f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81116100d0576108409260209260248b9360051b92839260051b010184840137810103017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018852876117d1565b5f5b83811061084f5780610729565b8060011b81810460021482151715610946577fff0000000000000000000000000000000000000000000000000000000000000061088c828a611b0a565b51169060018101809111610946576108c47eff000000000000000000000000000000000000000000000000000000000000918a611b0a565b5160081c161760f01c6108d5611902565b905f905b84821061090f575b50509061ffff6040838260019551166108fa858c6119ed565b5201511661090882886119ed565b5201610842565b909161ffff602061092085896119ed565b5101511682116109405750600161093783876119ed565b519201906108d9565b916108e1565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6107ba6107b460ff60016107aa565b909360038502858104600314861517156109465761ffff6109a38285611aee565b90549060031b1c1615610a6b5761ffff6109bd8285611aee565b90549060031b1c169060018101808211610946576109de61ffff9186611aee565b90549060031b1c169060028101809111610946576109ff61ffff9186611aee565b90549060031b1c169060405192610a1584611799565b835260208301526040820152610a2b82886119ed565b52610a3681876119ed565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610946576001809101940190610715565b509361071e565b602090610a7d611902565b82828901015201610707565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d057610abb611776565b6024359067ffffffffffffffff82116100d057366023830112156100d057816004013590610ae882611812565b91610af660405193846117d1565b808352602083019336602483830101116100d057815f9260246020930187378401015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803014908115610da9575b5061060c57610b68611b1b565b73ffffffffffffffffffffffffffffffffffffffff8116926040517f52d1902d000000000000000000000000000000000000000000000000000000008152602081600481885afa5f9181610d75575b50610be857847f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc869203610d4a5750823b15610d1f57807fffffffffffffffffffffffff00000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2825115610ced575f80916100ce945190845af43d15610ce5573d91610cc983611812565b92610cd760405194856117d1565b83523d5f602085013e611bde565b606091611bde565b50505034610cf757005b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7faa1d49a4000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9091506020813d602011610da1575b81610d91602093836117d1565b810103126100d057519086610bb7565b3d9150610d84565b905073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416141584610b5b565b346100d05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05760043567ffffffffffffffff81116100d0578036036101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126100d05773ffffffffffffffffffffffffffffffffffffffff60015416330361174e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd606483013591018112156100d05781019060048201359167ffffffffffffffff83116100d057602481019280360384136100d05781016024810193600482019291604090839003126100d0573560ff8116036100d057604481013567ffffffffffffffff81116100d05760049101019280603f850112156100d057602084013591610f248361187f565b94610f3260405196876117d1565b83865260208060608189019602830101019283116100d057604001925b8284106116fa5785858151600a81116116d2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181115f5b8381106115a2576040518587610f9f836117b5565b6040516103c093610fb085836117d1565b843683375280516040519384019084821067ffffffffffffffff83111761157557600991604052801515805f1461156c5761ffff80610fee86611920565b5151165b16865280156115635761ffff80602061100a87611920565b510151165b1660208701521561155a5761ffff80604061102986611920565b510151165b1660408601526001811180156115515761ffff8061104b8661195a565b5151165b16606087015280156115485761ffff80602061106a8761195a565b510151165b1660808701521561153f5761ffff8060406110898661195a565b510151165b1660a08601526002811180156115365761ffff806110ab8661196a565b5151165b1660c0870152801561152d5761ffff8060206110ca8761196a565b510151165b1660e0870152156115245761ffff8060406110e98661196a565b510151165b1661010086015260038111801561151b5761ffff8061110c8661197a565b5151165b1661012087015280156115125761ffff80602061112c8761197a565b510151165b16610140870152156115095761ffff80604061114c8661197a565b510151165b166101608601526004811180156115005761ffff8061116f8661198a565b5151165b1661018087015280156114f75761ffff80602061118f8761198a565b510151165b166101a0870152156114ee5761ffff8060406111af8661198a565b510151165b166101c08601526005811180156114e55761ffff806111d28661199a565b5151165b166101e087015280156114dc5761ffff8060206111f28761199a565b510151165b16610200870152156114d35761ffff8060406112128661199a565b510151165b166102208601526006811180156114ca5761ffff80611235866119aa565b5151165b1661024087015280156114c15761ffff806020611255876119aa565b510151165b16610260870152156114b85761ffff806040611275866119aa565b510151165b166102808601526007811180156114af5761ffff80611298866119ba565b5151165b166102a087015280156114a65761ffff8060206112b8876119ba565b510151165b166102c08701521561149d5761ffff8060406112d8866119ba565b510151165b166102e08601526008811180156114945761ffff806112fb866119cb565b5151165b16610300870152801561148b5761ffff80602061131b876119cb565b510151165b16610320870152156114825761ffff80604061133b866119cb565b510151165b166103408601521180156114795761ffff8061135b846119dc565b5151165b1661036085015280156114705761ffff80602061137b856119dc565b510151165b16610380850152156114665761ffff604061139b82936119dc565b510151165b166103a0830152604051916113b4836117b5565b82526004013561ffff81168091036100d0575f525f60205260405f209051905f5b6001811061142457505f915f5b600e81106113f35760018301849055005b9092602061141b60019261ffff8751169085851b61ffff809160031b9316831b921b19161790565b940191016113e2565b5f5f5b6010811061143c5750828201556001016113d5565b845160209095019461ffff908116600483901b90811b91901b199092169190911790600101611427565b5061ffff5f6113a0565b61ffff5f611380565b61ffff5f61135f565b61ffff5f611340565b61ffff5f611320565b61ffff5f6112ff565b61ffff5f6112dd565b61ffff5f6112bd565b61ffff5f61129c565b61ffff5f61127a565b61ffff5f61125a565b61ffff5f611239565b61ffff5f611217565b61ffff5f6111f7565b61ffff5f6111d6565b61ffff5f6111b4565b61ffff5f611194565b61ffff5f611173565b61ffff5f611151565b61ffff5f611131565b61ffff5f611110565b61ffff5f6110ee565b61ffff5f6110cf565b61ffff5f6110af565b61ffff5f61108e565b61ffff5f61106f565b61ffff5f61104f565b61ffff5f61102e565b61ffff5f61100f565b61ffff5f610ff2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61ffff6115af82886119ed565b515116156116aa5761ffff60206115c683896119ed565b51015116156116825761ffff60406115de83896119ed565b510151161561165a5781610946578281036115fc575b600101610f8a565b61ffff602061160b83896119ed565b510151166001820180831161094657602061162961ffff928a6119ed565b51015116106115f4577ff74c8f69000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f794f5bdd000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fcd7786c0000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f5e51b518000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f3ee22d8c000000000000000000000000000000000000000000000000000000005f5260045ffd5b6060602085840301126100d057602060609160405161171881611799565b61172187611897565b815261172e838801611897565b8382015261173e60408801611897565b6040820152815201930192610f4f565b7f2d8bbdf6000000000000000000000000000000000000000000000000000000005f5260045ffd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036100d057565b6060810190811067ffffffffffffffff82111761157557604052565b6020810190811067ffffffffffffffff82111761157557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761157557604052565b67ffffffffffffffff811161157557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b90602080835192838152019201905f5b8181106118695750505090565b825184526020938401939092019160010161185c565b67ffffffffffffffff81116115755760051b60200190565b359061ffff821682036100d057565b906118b08261187f565b6118bd60405191826117d1565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06118eb829461187f565b0190602036910137565b9190820180921161094657565b6040519061190f82611799565b5f6040838281528260208201520152565b80511561192d5760200190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80516001101561192d5760400190565b80516002101561192d5760600190565b80516003101561192d5760800190565b80516004101561192d5760a00190565b80516005101561192d5760c00190565b80516006101561192d5760e00190565b80516007101561192d576101000190565b80516008101561192d576101200190565b80516009101561192d576101400190565b805182101561192d5760209160051b010190565b73ffffffffffffffffffffffffffffffffffffffff168015611ac25773ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054827fffffffffffffffffffffffff00000000000000000000000000000000000000008216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b919091601e83101561192d57601e908360041c019260011b1690565b90815181101561192d570160200190565b73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303611b5b57565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615611bb657565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b90611c1b5750805115611bf357805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580611c6e575b611c2c575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b15611c2456fea26469706673582212203f55de83fcfa7d153606b685953cee01a3ba4b4678085993111e1a2dbd7a6dda64736f6c634300081c0033f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c80632e28ad1714610deb5780634f1ef28614610a89578063508c72a31461063457806352d1902d1461057757806354fd4d501461053e578063715018a6146104645780638da5cb5b146103f4578063ad3cb1cc14610342578063c4d66de8146100d45763f2fde38b14610087575f80fd5b346100d05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d0576100ce6100c1611776565b6100c9611b1b565b611a01565b005b5f80fd5b346100d05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05761010b611776565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460ff8160401c16159167ffffffffffffffff82168015908161033a575b6001149081610330575b159081610327575b506102ff57818360017fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000073ffffffffffffffffffffffffffffffffffffffff9516177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00556102aa575b506101ce611b87565b6101d6611b87565b6101de611b87565b6101e733611a01565b167fffffffffffffffffffffffff0000000000000000000000000000000000000000600154161760015561021757005b7fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054167ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b7fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000001668010000000000000001177ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0055836101c5565b7ff92ee8a9000000000000000000000000000000000000000000000000000000005f5260045ffd5b9050158461015c565b303b159150610154565b84915061014a565b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d057604080519061037f81836117d1565b6005825260208201917f352e302e3000000000000000000000000000000000000000000000000000000083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8351948593602085525180918160208701528686015e5f85828601015201168101030190f35b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d057602073ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c1993005416604051908152f35b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05761049a611b1b565b5f73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300547fffffffffffffffffffffffff000000000000000000000000000000000000000081167f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d057602060405160018152f35b346100d0575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000541804a42636924d0e4ed8e632bdbf91538cc12a16300361060c5760206040517f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8152f35b7fe07c8dba000000000000000000000000000000000000000000000000000000005f5260045ffd5b346100d05760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05760243560443567ffffffffffffffff81116100d057366023820112156100d05780600401359067ffffffffffffffff82116100d0573660248360051b830101116100d057606435926106b4816118a6565b926106be826118a6565b926004355f525f60205260405f2090610160927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06040519461070081876117d1565b600a8652015f5b818110610a725750505f925f905b600a8210610982575b505082845282610798575b505050505061074b92506107599060405193849360608552606085019061184c565b90838203602085015261184c565b818103604083015260206060519182815201906080905f5b81811061077f575050500390f35b8251845285945060209384019390920191600101610771565b600f8516610973576107ba6107b460ff5f5b168760041c6118f5565b896118f5565b908189116100d05781116100d05787900396604051977f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81116100d0576108409260209260248b9360051b92839260051b010184840137810103017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018852876117d1565b5f5b83811061084f5780610729565b8060011b81810460021482151715610946577fff0000000000000000000000000000000000000000000000000000000000000061088c828a611b0a565b51169060018101809111610946576108c47eff000000000000000000000000000000000000000000000000000000000000918a611b0a565b5160081c161760f01c6108d5611902565b905f905b84821061090f575b50509061ffff6040838260019551166108fa858c6119ed565b5201511661090882886119ed565b5201610842565b909161ffff602061092085896119ed565b5101511682116109405750600161093783876119ed565b519201906108d9565b916108e1565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6107ba6107b460ff60016107aa565b909360038502858104600314861517156109465761ffff6109a38285611aee565b90549060031b1c1615610a6b5761ffff6109bd8285611aee565b90549060031b1c169060018101808211610946576109de61ffff9186611aee565b90549060031b1c169060028101809111610946576109ff61ffff9186611aee565b90549060031b1c169060405192610a1584611799565b835260208301526040820152610a2b82886119ed565b52610a3681876119ed565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610946576001809101940190610715565b509361071e565b602090610a7d611902565b82828901015201610707565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d057610abb611776565b6024359067ffffffffffffffff82116100d057366023830112156100d057816004013590610ae882611812565b91610af660405193846117d1565b808352602083019336602483830101116100d057815f9260246020930187378401015273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000541804a42636924d0e4ed8e632bdbf91538cc12a16803014908115610da9575b5061060c57610b68611b1b565b73ffffffffffffffffffffffffffffffffffffffff8116926040517f52d1902d000000000000000000000000000000000000000000000000000000008152602081600481885afa5f9181610d75575b50610be857847f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc869203610d4a5750823b15610d1f57807fffffffffffffffffffffffff00000000000000000000000000000000000000007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416177f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2825115610ced575f80916100ce945190845af43d15610ce5573d91610cc983611812565b92610cd760405194856117d1565b83523d5f602085013e611bde565b606091611bde565b50505034610cf757005b7fb398979f000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4c9c8ce3000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b7faa1d49a4000000000000000000000000000000000000000000000000000000005f5260045260245ffd5b9091506020813d602011610da1575b81610d91602093836117d1565b810103126100d057519086610bb7565b3d9150610d84565b905073ffffffffffffffffffffffffffffffffffffffff7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5416141584610b5b565b346100d05760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100d05760043567ffffffffffffffff81116100d0578036036101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126100d05773ffffffffffffffffffffffffffffffffffffffff60015416330361174e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdd606483013591018112156100d05781019060048201359167ffffffffffffffff83116100d057602481019280360384136100d05781016024810193600482019291604090839003126100d0573560ff8116036100d057604481013567ffffffffffffffff81116100d05760049101019280603f850112156100d057602084013591610f248361187f565b94610f3260405196876117d1565b83865260208060608189019602830101019283116100d057604001925b8284106116fa5785858151600a81116116d2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81018181115f5b8381106115a2576040518587610f9f836117b5565b6040516103c093610fb085836117d1565b843683375280516040519384019084821067ffffffffffffffff83111761157557600991604052801515805f1461156c5761ffff80610fee86611920565b5151165b16865280156115635761ffff80602061100a87611920565b510151165b1660208701521561155a5761ffff80604061102986611920565b510151165b1660408601526001811180156115515761ffff8061104b8661195a565b5151165b16606087015280156115485761ffff80602061106a8761195a565b510151165b1660808701521561153f5761ffff8060406110898661195a565b510151165b1660a08601526002811180156115365761ffff806110ab8661196a565b5151165b1660c0870152801561152d5761ffff8060206110ca8761196a565b510151165b1660e0870152156115245761ffff8060406110e98661196a565b510151165b1661010086015260038111801561151b5761ffff8061110c8661197a565b5151165b1661012087015280156115125761ffff80602061112c8761197a565b510151165b16610140870152156115095761ffff80604061114c8661197a565b510151165b166101608601526004811180156115005761ffff8061116f8661198a565b5151165b1661018087015280156114f75761ffff80602061118f8761198a565b510151165b166101a0870152156114ee5761ffff8060406111af8661198a565b510151165b166101c08601526005811180156114e55761ffff806111d28661199a565b5151165b166101e087015280156114dc5761ffff8060206111f28761199a565b510151165b16610200870152156114d35761ffff8060406112128661199a565b510151165b166102208601526006811180156114ca5761ffff80611235866119aa565b5151165b1661024087015280156114c15761ffff806020611255876119aa565b510151165b16610260870152156114b85761ffff806040611275866119aa565b510151165b166102808601526007811180156114af5761ffff80611298866119ba565b5151165b166102a087015280156114a65761ffff8060206112b8876119ba565b510151165b166102c08701521561149d5761ffff8060406112d8866119ba565b510151165b166102e08601526008811180156114945761ffff806112fb866119cb565b5151165b16610300870152801561148b5761ffff80602061131b876119cb565b510151165b16610320870152156114825761ffff80604061133b866119cb565b510151165b166103408601521180156114795761ffff8061135b846119dc565b5151165b1661036085015280156114705761ffff80602061137b856119dc565b510151165b16610380850152156114665761ffff604061139b82936119dc565b510151165b166103a0830152604051916113b4836117b5565b82526004013561ffff81168091036100d0575f525f60205260405f209051905f5b6001811061142457505f915f5b600e81106113f35760018301849055005b9092602061141b60019261ffff8751169085851b61ffff809160031b9316831b921b19161790565b940191016113e2565b5f5f5b6010811061143c5750828201556001016113d5565b845160209095019461ffff908116600483901b90811b91901b199092169190911790600101611427565b5061ffff5f6113a0565b61ffff5f611380565b61ffff5f61135f565b61ffff5f611340565b61ffff5f611320565b61ffff5f6112ff565b61ffff5f6112dd565b61ffff5f6112bd565b61ffff5f61129c565b61ffff5f61127a565b61ffff5f61125a565b61ffff5f611239565b61ffff5f611217565b61ffff5f6111f7565b61ffff5f6111d6565b61ffff5f6111b4565b61ffff5f611194565b61ffff5f611173565b61ffff5f611151565b61ffff5f611131565b61ffff5f611110565b61ffff5f6110ee565b61ffff5f6110cf565b61ffff5f6110af565b61ffff5f61108e565b61ffff5f61106f565b61ffff5f61104f565b61ffff5f61102e565b61ffff5f61100f565b61ffff5f610ff2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b61ffff6115af82886119ed565b515116156116aa5761ffff60206115c683896119ed565b51015116156116825761ffff60406115de83896119ed565b510151161561165a5781610946578281036115fc575b600101610f8a565b61ffff602061160b83896119ed565b510151166001820180831161094657602061162961ffff928a6119ed565b51015116106115f4577ff74c8f69000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f794f5bdd000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fcd7786c0000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f5e51b518000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f3ee22d8c000000000000000000000000000000000000000000000000000000005f5260045ffd5b6060602085840301126100d057602060609160405161171881611799565b61172187611897565b815261172e838801611897565b8382015261173e60408801611897565b6040820152815201930192610f4f565b7f2d8bbdf6000000000000000000000000000000000000000000000000000000005f5260045ffd5b6004359073ffffffffffffffffffffffffffffffffffffffff821682036100d057565b6060810190811067ffffffffffffffff82111761157557604052565b6020810190811067ffffffffffffffff82111761157557604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761157557604052565b67ffffffffffffffff811161157557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b90602080835192838152019201905f5b8181106118695750505090565b825184526020938401939092019160010161185c565b67ffffffffffffffff81116115755760051b60200190565b359061ffff821682036100d057565b906118b08261187f565b6118bd60405191826117d1565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06118eb829461187f565b0190602036910137565b9190820180921161094657565b6040519061190f82611799565b5f6040838281528260208201520152565b80511561192d5760200190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b80516001101561192d5760400190565b80516002101561192d5760600190565b80516003101561192d5760800190565b80516004101561192d5760a00190565b80516005101561192d5760c00190565b80516006101561192d5760e00190565b80516007101561192d576101000190565b80516008101561192d576101200190565b80516009101561192d576101400190565b805182101561192d5760209160051b010190565b73ffffffffffffffffffffffffffffffffffffffff168015611ac25773ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054827fffffffffffffffffffffffff00000000000000000000000000000000000000008216177f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b7f1e4fbdf7000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b919091601e83101561192d57601e908360041c019260011b1690565b90815181101561192d570160200190565b73ffffffffffffffffffffffffffffffffffffffff7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930054163303611b5b57565b7f118cdaa7000000000000000000000000000000000000000000000000000000005f523360045260245ffd5b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c1615611bb657565b7fd7e6bcf8000000000000000000000000000000000000000000000000000000005f5260045ffd5b90611c1b5750805115611bf357805190602001fd5b7fd6bda275000000000000000000000000000000000000000000000000000000005f5260045ffd5b81511580611c6e575b611c2c575090565b73ffffffffffffffffffffffffffffffffffffffff907f9996b315000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b50803b15611c2456fea26469706673582212203f55de83fcfa7d153606b685953cee01a3ba4b4678085993111e1a2dbd7a6dda64736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 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.