Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 116,038 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Toggle Forge Sta... | 1675997 | 384 days ago | IN | 0 ETH | 0 | ||||
Forge Unit | 1675954 | 384 days ago | IN | 0 ETH | 0.00000074 | ||||
Forge Unit | 1675776 | 384 days ago | IN | 0 ETH | 0.0000006 | ||||
Forge Unit | 1675753 | 384 days ago | IN | 0 ETH | 0.00000062 | ||||
Forge Unit | 1675739 | 384 days ago | IN | 0 ETH | 0.00000059 | ||||
Forge Unit | 1675432 | 384 days ago | IN | 0 ETH | 0.00000065 | ||||
Forge Unit | 1675389 | 384 days ago | IN | 0 ETH | 0.00000062 | ||||
Forge Unit | 1675235 | 384 days ago | IN | 0 ETH | 0.00000063 | ||||
Forge Artifact | 1675226 | 384 days ago | IN | 0 ETH | 0.00000033 | ||||
Forge Unit | 1675219 | 384 days ago | IN | 0 ETH | 0.00000067 | ||||
Forge Unit | 1675194 | 384 days ago | IN | 0 ETH | 0.00000061 | ||||
Forge Unit | 1675188 | 384 days ago | IN | 0 ETH | 0.00000062 | ||||
Forge Unit | 1675123 | 384 days ago | IN | 0 ETH | 0.0000007 | ||||
Forge Unit | 1675063 | 384 days ago | IN | 0 ETH | 0.00000067 | ||||
Forge Unit | 1675054 | 384 days ago | IN | 0 ETH | 0.00000066 | ||||
Forge Unit | 1675027 | 384 days ago | IN | 0 ETH | 0.00000063 | ||||
Forge Unit | 1675015 | 384 days ago | IN | 0 ETH | 0.00000062 | ||||
Forge Unit | 1675012 | 384 days ago | IN | 0 ETH | 0.00000062 | ||||
Forge Unit | 1675002 | 384 days ago | IN | 0 ETH | 0.0000006 | ||||
Forge Unit | 1674956 | 384 days ago | IN | 0 ETH | 0.0000006 | ||||
Forge Artifact | 1674949 | 384 days ago | IN | 0 ETH | 0.00000033 | ||||
Forge Unit | 1674930 | 384 days ago | IN | 0 ETH | 0.00000061 | ||||
Forge Unit | 1674919 | 384 days ago | IN | 0 ETH | 0.00000068 | ||||
Forge Artifact | 1674907 | 384 days ago | IN | 0 ETH | 0.00000033 | ||||
Forge Unit | 1674906 | 384 days ago | IN | 0 ETH | 0.00000072 |
Loading...
Loading
Contract Name:
CardForge
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import { OwnableRoles } from "@solady/src/auth/OwnableRoles.sol"; import { ECDSA } from "@solady/src/utils/ECDSA.sol"; import { AccessRoles } from "./access/AccessRoles.sol"; import { ICardForge } from "./interfaces/ICardForge.sol"; import { ISeeder } from "./interfaces/ISeeder.sol"; import { IGameCards } from "./interfaces/IGameCards.sol"; import { IBaseCards } from "./interfaces/IBaseCards.sol"; import { IBlast } from "./interfaces/IBlast.sol"; import { Game } from "./types/Game.sol"; /** * @title CardForge * @notice This contract handles all functionality related to card forging. Units can be forged by incinerating * two equivalent unit cards of the same tier whilst artifacts can be forged using items. */ contract CardForge is ICardForge, OwnableRoles { using ECDSA for bytes32; uint256 private constant _WEIGHT_SUM = 10_000; uint256 private constant _MAX_RATE = 10_000; IBlast public immutable BLAST = IBlast(0x4300000000000000000000000000000000000002); uint256[] public forgeCards; uint256[] public cardWeights; address public signer; ISeeder public seeder; IGameCards public gameCards; IBaseCards public baseCards; ForgeState public forgeState; mapping(Game.CardTier cardTier => uint256 rate) public forgeRates; mapping(uint256 nonce => bool used) public nonceUsed; constructor( address _gameMaster, address _signer, address _seeder, address _gameCards, address _baseCards, address _blastGovernor ) { if ( _gameMaster == address(0) || _signer == address(0) || _seeder == address(0) || _gameCards == address(0) || _baseCards == address(0) || _blastGovernor == address(0) ) revert ZeroAddress(); BLAST.configureClaimableGas(); BLAST.configureGovernor({ _governor: _blastGovernor }); _initializeOwner({ newOwner: msg.sender }); _grantRoles({ user: _gameMaster, roles: AccessRoles.GAME_MASTER_ROLE }); signer = _signer; seeder = ISeeder(_seeder); gameCards = IGameCards(_gameCards); baseCards = IBaseCards(_baseCards); } /** * @inheritdoc ICardForge */ function forgeUnit(uint256 cardOneId, uint256 cardTwoId) external checkForgeState(ForgeState.ACTIVE) { if (msg.sender != tx.origin) revert CallerNotOrigin(); if (cardOneId == cardTwoId) revert DuplicateCardId(); /// Ensure caller owns both gameCards. if (msg.sender != gameCards.ownerOf({ tokenId: cardOneId })) revert CallerNotOwner(); if (msg.sender != gameCards.ownerOf({ tokenId: cardTwoId })) revert CallerNotOwner(); /// Ensure tiers are equal. Game.PlayerCard memory cardA = gameCards.playerCards({ tokenId: cardOneId }); Game.PlayerCard memory cardB = gameCards.playerCards({ tokenId: cardTwoId }); if (cardA.cardTier != cardB.cardTier) revert CardTierMismatch(); /// Ensure either or both cards are not artifacts. if (cardA.cardType != Game.CardType.UNIT || cardB.cardType != Game.CardType.UNIT) revert InvalidCardType(); uint256[] memory cardIds = new uint256[](2); cardIds[0] = cardOneId; cardIds[1] = cardTwoId; gameCards.incinerate({ tokenIds: cardIds }); /// Get forge chance. uint256 forgeRate = forgeRates[cardA.cardTier]; if (forgeRate == 0) revert InvalidRate(); uint256 ephermalSeed = seeder.getAndUpdateGameSeed(); uint256 roll = (ephermalSeed % _WEIGHT_SUM) + 1; // If the player has rolled an upgrade, allocated the new card tier to be a step above // their provided card tiers. Otherwise, mint them a card of the same tier. Game.CardTier newTier; if (ephermalSeed % _MAX_RATE + 1 <= forgeRate) { newTier = cardA.cardTier == Game.CardTier.SSS ? Game.CardTier.SSS : Game.CardTier(uint256(cardA.cardTier) + 1); } else { newTier = cardA.cardTier; } uint256[] memory baseCardIds = new uint256[](1); uint256 cumulativeWeight = 0; for (uint256 i = 0; i < cardWeights.length; i++) { cumulativeWeight += cardWeights[i]; if (roll <= cumulativeWeight) { baseCardIds[0] = forgeCards[i]; break; } } gameCards.mintCards({ cardIds: baseCardIds, tierWeights: _getTierWeightsArray(newTier), receiver: msg.sender }); } /** * Function used to forge an artifact card. * @param baseCardId Unique base card identifier. * @param signature Signed message digest. */ function forgeArtifact( uint256 baseCardId, uint256 nonce, bytes calldata signature ) external checkForgeState(ForgeState.ACTIVE) { if (baseCardId == 0 || baseCardId > baseCards.baseCardCount()) revert NonExistentCardId(); if (baseCards.baseCards(baseCardId).cardType != Game.CardType.ARTIFACT) revert CardNotArtifact(); bytes32 digest = keccak256(abi.encodePacked(msg.sender, baseCardId, nonce)).toEthSignedMessageHash(); if (digest.recover(signature) != signer) revert SignerMismatch(); if (nonceUsed[nonce]) revert NonceUsed(); nonceUsed[nonce] = true; uint256[] memory ids = new uint256[](1); ids[0] = baseCardId; uint256[6] memory weight; gameCards.mintCards({ cardIds: ids, tierWeights: weight, receiver: msg.sender }); } /** * @inheritdoc ICardForge */ function setForgeData( uint256[] calldata baseCardIds, uint256[] calldata weights ) external onlyRoles(AccessRoles.GAME_MASTER_ROLE) { _validateInputs(baseCardIds, weights); forgeCards = baseCardIds; cardWeights = weights; emit ForgeDataUpdated(baseCardIds, cardWeights); } /** * @inheritdoc ICardForge */ function setForgeRate(Game.CardTier tier, uint256 rate) external onlyRoles(AccessRoles.GAME_MASTER_ROLE) { if (tier == Game.CardTier.UNDEFINED) revert UndefinedCardTier(); if (rate == 0 || rate > _MAX_RATE) revert InvalidRate(); uint256 oldRate = forgeRates[tier]; forgeRates[tier] = rate; emit ForgeRateUpdated({ cardTier: tier, oldTierRate: oldRate, newTierRate: rate }); } /** * @inheritdoc ICardForge */ function toggleForgeState() external onlyRoles(AccessRoles.GAME_MASTER_ROLE) { ForgeState oldState = forgeState; forgeState = oldState == ForgeState.INACTIVE ? ForgeState.ACTIVE : ForgeState.INACTIVE; emit ForgeStateUpdated({ oldState: oldState, newState: forgeState }); } /** * @inheritdoc ICardForge */ function setSigner(address newSigner) external onlyRoles(AccessRoles.GAME_MASTER_ROLE) { if (newSigner == address(0)) revert ZeroAddress(); address oldSigner = signer; signer = newSigner; emit SignerUpdated(oldSigner, newSigner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL LOGIC */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Function used to validate that: * 1. `ids` and `weights` are equal in length. * 2. `ids` only contains valid base card identifiers. * 3. `ids` contains no duplicate entries. * 4. `weights` sum equals `_WEIGHT_SUM` (10_000). */ function _validateInputs(uint256[] memory baseCardIds, uint256[] memory weights) internal view { if (baseCardIds.length != weights.length) revert ArrayLengthMismatch(); if (baseCardIds.length == 0) revert ZeroLengthArray(); uint256 maxCardId = baseCards.baseCardCount(); uint256 weightSum = 0; uint256 dupes = 0; for (uint256 i = 0; i < baseCardIds.length; i++) { uint256 baseCardId = baseCardIds[i]; if (baseCardId == 0 || baseCardId > maxCardId) revert InvalidBaseCardId(); if (dupes >> baseCardId & 1 == 1) revert DuplicateBaseCardId(); dupes |= 1 << baseCardId; weightSum += weights[i]; } if (weightSum != _WEIGHT_SUM) revert InvalidWeightSum(); } /** * Function used to return an array that guarantees a card tier upgrade. * @param cardTier Tier of the newly forged card. */ function _getTierWeightsArray(Game.CardTier cardTier) internal pure returns (uint256[6] memory tierWeights) { uint256 tierIdx = cardTier == Game.CardTier.SSS ? 5 : uint256(cardTier) - 1; tierWeights[tierIdx] = _WEIGHT_SUM; } /** * Function used to check the current `forgeState` value. */ function _checkForgeState(ForgeState desiredState) internal view { if (forgeState != desiredState) revert InvalidForgeState(); } modifier checkForgeState(ForgeState desiredState) { _checkForgeState(desiredState); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {Ownable} from "./Ownable.sol"; /// @notice Simple single owner and multiroles authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173) /// for compatibility, the nomenclature for the 2-step ownership handover and roles /// may be unique to this codebase. abstract contract OwnableRoles is Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The `user`'s roles is updated to `roles`. /// Each bit of `roles` represents whether the role is set. event RolesUpdated(address indexed user, uint256 indexed roles); /// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`. uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE = 0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The role slot of `user` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED)) /// let roleSlot := keccak256(0x00, 0x20) /// ``` /// This automatically ignores the upper bits of the `user` in case /// they are not clean, as well as keep the `keccak256` under 32-bytes. /// /// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`. uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Overwrite the roles directly without authorization guard. function _setRoles(address user, uint256 roles) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Store the new value. sstore(keccak256(0x0c, 0x20), roles) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles) } } /// @dev Updates the roles directly without authorization guard. /// If `on` is true, each set bit of `roles` will be turned on, /// otherwise, each set bit of `roles` will be turned off. function _updateRoles(address user, uint256 roles, bool on) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) let roleSlot := keccak256(0x0c, 0x20) // Load the current value. let current := sload(roleSlot) // Compute the updated roles if `on` is true. let updated := or(current, roles) // Compute the updated roles if `on` is false. // Use `and` to compute the intersection of `current` and `roles`, // `xor` it with `current` to flip the bits in the intersection. if iszero(on) { updated := xor(current, and(current, roles)) } // Then, store the new value. sstore(roleSlot, updated) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated) } } /// @dev Grants the roles directly without authorization guard. /// Each bit of `roles` represents the role to turn on. function _grantRoles(address user, uint256 roles) internal virtual { _updateRoles(user, roles, true); } /// @dev Removes the roles directly without authorization guard. /// Each bit of `roles` represents the role to turn off. function _removeRoles(address user, uint256 roles) internal virtual { _updateRoles(user, roles, false); } /// @dev Throws if the sender does not have any of the `roles`. function _checkRoles(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Throws if the sender is not the owner, /// and does not have any of the `roles`. /// Checks for ownership first, then lazily checks for roles. function _checkOwnerOrRoles(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner. // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`. if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } } /// @dev Throws if the sender does not have any of the `roles`, /// and is not the owner. /// Checks for roles first, then lazily checks for ownership. function _checkRolesOrOwner(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { // If the caller is not the stored owner. // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`. if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } } /// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`. /// This is meant for frontends like Etherscan, and is therefore not fully optimized. /// Not recommended to be called on-chain. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) { /// @solidity memory-safe-assembly assembly { for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } { // We don't need to mask the values of `ordinals`, as Solidity // cleans dirty upper bits when storing variables into memory. roles := or(shl(mload(add(ordinals, i)), 1), roles) } } } /// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap. /// This is meant for frontends like Etherscan, and is therefore not fully optimized. /// Not recommended to be called on-chain. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) { /// @solidity memory-safe-assembly assembly { // Grab the pointer to the free memory. ordinals := mload(0x40) let ptr := add(ordinals, 0x20) let o := 0 // The absence of lookup tables, De Bruijn, etc., here is intentional for // smaller bytecode, as this function is not meant to be called on-chain. for { let t := roles } 1 {} { mstore(ptr, o) // `shr` 5 is equivalent to multiplying by 0x20. // Push back into the ordinals array if the bit is set. ptr := add(ptr, shl(5, and(t, 1))) o := add(o, 1) t := shr(o, roles) if iszero(t) { break } } // Store the length of `ordinals`. mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20)))) // Allocate the memory. mstore(0x40, ptr) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to grant `user` `roles`. /// If the `user` already has a role, then it will be an no-op for the role. function grantRoles(address user, uint256 roles) public payable virtual onlyOwner { _grantRoles(user, roles); } /// @dev Allows the owner to remove `user` `roles`. /// If the `user` does not have a role, then it will be an no-op for the role. function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner { _removeRoles(user, roles); } /// @dev Allow the caller to remove their own roles. /// If the caller does not have a role, then it will be an no-op for the role. function renounceRoles(uint256 roles) public payable virtual { _removeRoles(msg.sender, roles); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the roles of `user`. function rolesOf(address user) public view virtual returns (uint256 roles) { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Load the stored value. roles := sload(keccak256(0x0c, 0x20)) } } /// @dev Returns whether `user` has any of `roles`. function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) { return rolesOf(user) & roles != 0; } /// @dev Returns whether `user` has all of `roles`. function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) { return rolesOf(user) & roles == roles; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by an account with `roles`. modifier onlyRoles(uint256 roles) virtual { _checkRoles(roles); _; } /// @dev Marks a function as only callable by the owner or by an account /// with `roles`. Checks for ownership first, then lazily checks for roles. modifier onlyOwnerOrRoles(uint256 roles) virtual { _checkOwnerOrRoles(roles); _; } /// @dev Marks a function as only callable by an account with `roles` /// or the owner. Checks for roles first, then lazily checks for ownership. modifier onlyRolesOrOwner(uint256 roles) virtual { _checkRolesOrOwner(roles); _; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ROLE CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // IYKYK uint256 internal constant _ROLE_0 = 1 << 0; uint256 internal constant _ROLE_1 = 1 << 1; uint256 internal constant _ROLE_2 = 1 << 2; uint256 internal constant _ROLE_3 = 1 << 3; uint256 internal constant _ROLE_4 = 1 << 4; uint256 internal constant _ROLE_5 = 1 << 5; uint256 internal constant _ROLE_6 = 1 << 6; uint256 internal constant _ROLE_7 = 1 << 7; uint256 internal constant _ROLE_8 = 1 << 8; uint256 internal constant _ROLE_9 = 1 << 9; uint256 internal constant _ROLE_10 = 1 << 10; uint256 internal constant _ROLE_11 = 1 << 11; uint256 internal constant _ROLE_12 = 1 << 12; uint256 internal constant _ROLE_13 = 1 << 13; uint256 internal constant _ROLE_14 = 1 << 14; uint256 internal constant _ROLE_15 = 1 << 15; uint256 internal constant _ROLE_16 = 1 << 16; uint256 internal constant _ROLE_17 = 1 << 17; uint256 internal constant _ROLE_18 = 1 << 18; uint256 internal constant _ROLE_19 = 1 << 19; uint256 internal constant _ROLE_20 = 1 << 20; uint256 internal constant _ROLE_21 = 1 << 21; uint256 internal constant _ROLE_22 = 1 << 22; uint256 internal constant _ROLE_23 = 1 << 23; uint256 internal constant _ROLE_24 = 1 << 24; uint256 internal constant _ROLE_25 = 1 << 25; uint256 internal constant _ROLE_26 = 1 << 26; uint256 internal constant _ROLE_27 = 1 << 27; uint256 internal constant _ROLE_28 = 1 << 28; uint256 internal constant _ROLE_29 = 1 << 29; uint256 internal constant _ROLE_30 = 1 << 30; uint256 internal constant _ROLE_31 = 1 << 31; uint256 internal constant _ROLE_32 = 1 << 32; uint256 internal constant _ROLE_33 = 1 << 33; uint256 internal constant _ROLE_34 = 1 << 34; uint256 internal constant _ROLE_35 = 1 << 35; uint256 internal constant _ROLE_36 = 1 << 36; uint256 internal constant _ROLE_37 = 1 << 37; uint256 internal constant _ROLE_38 = 1 << 38; uint256 internal constant _ROLE_39 = 1 << 39; uint256 internal constant _ROLE_40 = 1 << 40; uint256 internal constant _ROLE_41 = 1 << 41; uint256 internal constant _ROLE_42 = 1 << 42; uint256 internal constant _ROLE_43 = 1 << 43; uint256 internal constant _ROLE_44 = 1 << 44; uint256 internal constant _ROLE_45 = 1 << 45; uint256 internal constant _ROLE_46 = 1 << 46; uint256 internal constant _ROLE_47 = 1 << 47; uint256 internal constant _ROLE_48 = 1 << 48; uint256 internal constant _ROLE_49 = 1 << 49; uint256 internal constant _ROLE_50 = 1 << 50; uint256 internal constant _ROLE_51 = 1 << 51; uint256 internal constant _ROLE_52 = 1 << 52; uint256 internal constant _ROLE_53 = 1 << 53; uint256 internal constant _ROLE_54 = 1 << 54; uint256 internal constant _ROLE_55 = 1 << 55; uint256 internal constant _ROLE_56 = 1 << 56; uint256 internal constant _ROLE_57 = 1 << 57; uint256 internal constant _ROLE_58 = 1 << 58; uint256 internal constant _ROLE_59 = 1 << 59; uint256 internal constant _ROLE_60 = 1 << 60; uint256 internal constant _ROLE_61 = 1 << 61; uint256 internal constant _ROLE_62 = 1 << 62; uint256 internal constant _ROLE_63 = 1 << 63; uint256 internal constant _ROLE_64 = 1 << 64; uint256 internal constant _ROLE_65 = 1 << 65; uint256 internal constant _ROLE_66 = 1 << 66; uint256 internal constant _ROLE_67 = 1 << 67; uint256 internal constant _ROLE_68 = 1 << 68; uint256 internal constant _ROLE_69 = 1 << 69; uint256 internal constant _ROLE_70 = 1 << 70; uint256 internal constant _ROLE_71 = 1 << 71; uint256 internal constant _ROLE_72 = 1 << 72; uint256 internal constant _ROLE_73 = 1 << 73; uint256 internal constant _ROLE_74 = 1 << 74; uint256 internal constant _ROLE_75 = 1 << 75; uint256 internal constant _ROLE_76 = 1 << 76; uint256 internal constant _ROLE_77 = 1 << 77; uint256 internal constant _ROLE_78 = 1 << 78; uint256 internal constant _ROLE_79 = 1 << 79; uint256 internal constant _ROLE_80 = 1 << 80; uint256 internal constant _ROLE_81 = 1 << 81; uint256 internal constant _ROLE_82 = 1 << 82; uint256 internal constant _ROLE_83 = 1 << 83; uint256 internal constant _ROLE_84 = 1 << 84; uint256 internal constant _ROLE_85 = 1 << 85; uint256 internal constant _ROLE_86 = 1 << 86; uint256 internal constant _ROLE_87 = 1 << 87; uint256 internal constant _ROLE_88 = 1 << 88; uint256 internal constant _ROLE_89 = 1 << 89; uint256 internal constant _ROLE_90 = 1 << 90; uint256 internal constant _ROLE_91 = 1 << 91; uint256 internal constant _ROLE_92 = 1 << 92; uint256 internal constant _ROLE_93 = 1 << 93; uint256 internal constant _ROLE_94 = 1 << 94; uint256 internal constant _ROLE_95 = 1 << 95; uint256 internal constant _ROLE_96 = 1 << 96; uint256 internal constant _ROLE_97 = 1 << 97; uint256 internal constant _ROLE_98 = 1 << 98; uint256 internal constant _ROLE_99 = 1 << 99; uint256 internal constant _ROLE_100 = 1 << 100; uint256 internal constant _ROLE_101 = 1 << 101; uint256 internal constant _ROLE_102 = 1 << 102; uint256 internal constant _ROLE_103 = 1 << 103; uint256 internal constant _ROLE_104 = 1 << 104; uint256 internal constant _ROLE_105 = 1 << 105; uint256 internal constant _ROLE_106 = 1 << 106; uint256 internal constant _ROLE_107 = 1 << 107; uint256 internal constant _ROLE_108 = 1 << 108; uint256 internal constant _ROLE_109 = 1 << 109; uint256 internal constant _ROLE_110 = 1 << 110; uint256 internal constant _ROLE_111 = 1 << 111; uint256 internal constant _ROLE_112 = 1 << 112; uint256 internal constant _ROLE_113 = 1 << 113; uint256 internal constant _ROLE_114 = 1 << 114; uint256 internal constant _ROLE_115 = 1 << 115; uint256 internal constant _ROLE_116 = 1 << 116; uint256 internal constant _ROLE_117 = 1 << 117; uint256 internal constant _ROLE_118 = 1 << 118; uint256 internal constant _ROLE_119 = 1 << 119; uint256 internal constant _ROLE_120 = 1 << 120; uint256 internal constant _ROLE_121 = 1 << 121; uint256 internal constant _ROLE_122 = 1 << 122; uint256 internal constant _ROLE_123 = 1 << 123; uint256 internal constant _ROLE_124 = 1 << 124; uint256 internal constant _ROLE_125 = 1 << 125; uint256 internal constant _ROLE_126 = 1 << 126; uint256 internal constant _ROLE_127 = 1 << 127; uint256 internal constant _ROLE_128 = 1 << 128; uint256 internal constant _ROLE_129 = 1 << 129; uint256 internal constant _ROLE_130 = 1 << 130; uint256 internal constant _ROLE_131 = 1 << 131; uint256 internal constant _ROLE_132 = 1 << 132; uint256 internal constant _ROLE_133 = 1 << 133; uint256 internal constant _ROLE_134 = 1 << 134; uint256 internal constant _ROLE_135 = 1 << 135; uint256 internal constant _ROLE_136 = 1 << 136; uint256 internal constant _ROLE_137 = 1 << 137; uint256 internal constant _ROLE_138 = 1 << 138; uint256 internal constant _ROLE_139 = 1 << 139; uint256 internal constant _ROLE_140 = 1 << 140; uint256 internal constant _ROLE_141 = 1 << 141; uint256 internal constant _ROLE_142 = 1 << 142; uint256 internal constant _ROLE_143 = 1 << 143; uint256 internal constant _ROLE_144 = 1 << 144; uint256 internal constant _ROLE_145 = 1 << 145; uint256 internal constant _ROLE_146 = 1 << 146; uint256 internal constant _ROLE_147 = 1 << 147; uint256 internal constant _ROLE_148 = 1 << 148; uint256 internal constant _ROLE_149 = 1 << 149; uint256 internal constant _ROLE_150 = 1 << 150; uint256 internal constant _ROLE_151 = 1 << 151; uint256 internal constant _ROLE_152 = 1 << 152; uint256 internal constant _ROLE_153 = 1 << 153; uint256 internal constant _ROLE_154 = 1 << 154; uint256 internal constant _ROLE_155 = 1 << 155; uint256 internal constant _ROLE_156 = 1 << 156; uint256 internal constant _ROLE_157 = 1 << 157; uint256 internal constant _ROLE_158 = 1 << 158; uint256 internal constant _ROLE_159 = 1 << 159; uint256 internal constant _ROLE_160 = 1 << 160; uint256 internal constant _ROLE_161 = 1 << 161; uint256 internal constant _ROLE_162 = 1 << 162; uint256 internal constant _ROLE_163 = 1 << 163; uint256 internal constant _ROLE_164 = 1 << 164; uint256 internal constant _ROLE_165 = 1 << 165; uint256 internal constant _ROLE_166 = 1 << 166; uint256 internal constant _ROLE_167 = 1 << 167; uint256 internal constant _ROLE_168 = 1 << 168; uint256 internal constant _ROLE_169 = 1 << 169; uint256 internal constant _ROLE_170 = 1 << 170; uint256 internal constant _ROLE_171 = 1 << 171; uint256 internal constant _ROLE_172 = 1 << 172; uint256 internal constant _ROLE_173 = 1 << 173; uint256 internal constant _ROLE_174 = 1 << 174; uint256 internal constant _ROLE_175 = 1 << 175; uint256 internal constant _ROLE_176 = 1 << 176; uint256 internal constant _ROLE_177 = 1 << 177; uint256 internal constant _ROLE_178 = 1 << 178; uint256 internal constant _ROLE_179 = 1 << 179; uint256 internal constant _ROLE_180 = 1 << 180; uint256 internal constant _ROLE_181 = 1 << 181; uint256 internal constant _ROLE_182 = 1 << 182; uint256 internal constant _ROLE_183 = 1 << 183; uint256 internal constant _ROLE_184 = 1 << 184; uint256 internal constant _ROLE_185 = 1 << 185; uint256 internal constant _ROLE_186 = 1 << 186; uint256 internal constant _ROLE_187 = 1 << 187; uint256 internal constant _ROLE_188 = 1 << 188; uint256 internal constant _ROLE_189 = 1 << 189; uint256 internal constant _ROLE_190 = 1 << 190; uint256 internal constant _ROLE_191 = 1 << 191; uint256 internal constant _ROLE_192 = 1 << 192; uint256 internal constant _ROLE_193 = 1 << 193; uint256 internal constant _ROLE_194 = 1 << 194; uint256 internal constant _ROLE_195 = 1 << 195; uint256 internal constant _ROLE_196 = 1 << 196; uint256 internal constant _ROLE_197 = 1 << 197; uint256 internal constant _ROLE_198 = 1 << 198; uint256 internal constant _ROLE_199 = 1 << 199; uint256 internal constant _ROLE_200 = 1 << 200; uint256 internal constant _ROLE_201 = 1 << 201; uint256 internal constant _ROLE_202 = 1 << 202; uint256 internal constant _ROLE_203 = 1 << 203; uint256 internal constant _ROLE_204 = 1 << 204; uint256 internal constant _ROLE_205 = 1 << 205; uint256 internal constant _ROLE_206 = 1 << 206; uint256 internal constant _ROLE_207 = 1 << 207; uint256 internal constant _ROLE_208 = 1 << 208; uint256 internal constant _ROLE_209 = 1 << 209; uint256 internal constant _ROLE_210 = 1 << 210; uint256 internal constant _ROLE_211 = 1 << 211; uint256 internal constant _ROLE_212 = 1 << 212; uint256 internal constant _ROLE_213 = 1 << 213; uint256 internal constant _ROLE_214 = 1 << 214; uint256 internal constant _ROLE_215 = 1 << 215; uint256 internal constant _ROLE_216 = 1 << 216; uint256 internal constant _ROLE_217 = 1 << 217; uint256 internal constant _ROLE_218 = 1 << 218; uint256 internal constant _ROLE_219 = 1 << 219; uint256 internal constant _ROLE_220 = 1 << 220; uint256 internal constant _ROLE_221 = 1 << 221; uint256 internal constant _ROLE_222 = 1 << 222; uint256 internal constant _ROLE_223 = 1 << 223; uint256 internal constant _ROLE_224 = 1 << 224; uint256 internal constant _ROLE_225 = 1 << 225; uint256 internal constant _ROLE_226 = 1 << 226; uint256 internal constant _ROLE_227 = 1 << 227; uint256 internal constant _ROLE_228 = 1 << 228; uint256 internal constant _ROLE_229 = 1 << 229; uint256 internal constant _ROLE_230 = 1 << 230; uint256 internal constant _ROLE_231 = 1 << 231; uint256 internal constant _ROLE_232 = 1 << 232; uint256 internal constant _ROLE_233 = 1 << 233; uint256 internal constant _ROLE_234 = 1 << 234; uint256 internal constant _ROLE_235 = 1 << 235; uint256 internal constant _ROLE_236 = 1 << 236; uint256 internal constant _ROLE_237 = 1 << 237; uint256 internal constant _ROLE_238 = 1 << 238; uint256 internal constant _ROLE_239 = 1 << 239; uint256 internal constant _ROLE_240 = 1 << 240; uint256 internal constant _ROLE_241 = 1 << 241; uint256 internal constant _ROLE_242 = 1 << 242; uint256 internal constant _ROLE_243 = 1 << 243; uint256 internal constant _ROLE_244 = 1 << 244; uint256 internal constant _ROLE_245 = 1 << 245; uint256 internal constant _ROLE_246 = 1 << 246; uint256 internal constant _ROLE_247 = 1 << 247; uint256 internal constant _ROLE_248 = 1 << 248; uint256 internal constant _ROLE_249 = 1 << 249; uint256 internal constant _ROLE_250 = 1 << 250; uint256 internal constant _ROLE_251 = 1 << 251; uint256 internal constant _ROLE_252 = 1 << 252; uint256 internal constant _ROLE_253 = 1 << 253; uint256 internal constant _ROLE_254 = 1 << 254; uint256 internal constant _ROLE_255 = 1 << 255; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized ECDSA wrapper. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol) /// /// @dev Note: /// - The recovery functions use the ecrecover precompile (0x1). /// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure. /// This is for more safety by default. /// Use the `tryRecover` variants if you need to get the zero address back /// upon recovery failure instead. /// - As of Solady version 0.0.134, all `bytes signature` variants accept both /// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// This is for calldata efficiency on smart accounts prevalent on L2s. /// /// WARNING! Do NOT use signatures as unique identifiers: /// - Use a nonce in the digest to prevent replay attacks on the same contract. /// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts. /// EIP-712 also enables readable signing of typed data for better user safety. /// This implementation does NOT check if a signature is non-malleable. library ECDSA { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The signature is invalid. error InvalidSignature(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RECOVERY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function recover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. for {} 1 {} { mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. if eq(mload(signature), 64) { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(mload(signature), 65) { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. break } result := 0 break } result := mload( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function recoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) for {} 1 {} { if eq(signature.length, 64) { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(signature.length, 65) { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. break } result := 0 break } result := mload( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. result := mload( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) result := mload( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* TRY-RECOVER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // WARNING! // These functions will NOT revert upon recovery failure. // Instead, they will return the zero address upon recovery failure. // It is critical that the returned address is NEVER compared against // a zero address (e.g. an uninitialized address variable). /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function tryRecover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. for {} 1 {} { mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. if eq(mload(signature), 64) { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(mload(signature), 65) { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. break } result := 0 break } pop( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function tryRecoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := 1 let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) for {} 1 {} { if eq(signature.length, 64) { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. break } if eq(signature.length, 65) { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. break } result := 0 break } pop( staticcall( gas(), // Amount of gas left for the transaction. result, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. pop( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) pop( staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x40, // Start of output. 0x20 // Size of output. ) ) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, hash) // Store into scratch space for keccak256. mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes. result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`. } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. /// Note: Supports lengths of `s` up to 999999 bytes. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let sLength := mload(s) let o := 0x20 mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded. mstore(0x00, 0x00) // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`. for { let temp := sLength } 1 {} { o := sub(o, 1) mstore8(o, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } let n := sub(0x3a, o) // Header length: `26 + 32 - o`. // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes. returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20)) mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header. result := keccak256(add(s, sub(0x20, n)), add(n, sLength)) mstore(s, sLength) // Restore the length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; /** * @title AccessRoles * @notice This library contains all the valid roles within the protocol. Roles have been defined to mimic * {Solady.OwnableRoles} roles. */ library AccessRoles { /// `OwnableRoles._ROLE_0` uint256 public constant GAME_MASTER_ROLE = 1 << 0; /// `OwnableRoles._ROLE_1` uint256 public constant SEEDER_ROLE = 1 << 1; /// `OwnableRoles._ROLE_2` uint256 public constant MINTER_ROLE = 1 << 2; /// `OwnableRoles._ROLE_3` uint256 public constant RESOLVER_ROLE = 1 << 3; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import { Game } from "../types/Game.sol"; /** * @title ICardForge * @notice Interface for CardForge. */ interface ICardForge { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Thrown when the zero address is provided. */ error ZeroAddress(); /** * Thrown when an input array of zero length is provided. */ error ZeroLengthArray(); /** * Thrown when two input arrays differ in length. */ error ArrayLengthMismatch(); /** * Thrown when a provided base card ID is not valid. */ error InvalidBaseCardId(); /** * Thrown when the two provided player cards differ in tier. */ error CardTierMismatch(); /** * Thrown when the caller does not own the provided player card identifiers. */ error CallerNotOwner(); /** * Thrown when a base card identifier is provided twice. */ error DuplicateBaseCardId(); /** * Thrown when the same tokenised player card is provided twice. */ error DuplicateCardId(); /** * Thrown when the sum of the `weights` array does not equal 10_000. */ error InvalidWeightSum(); /** * Thrown when the provided base cards are not unit types. */ error InvalidCardType(); /** * Thrown when an undefined card tier is provided. */ error UndefinedCardTier(); /** * Thrown when an invalid rate is provided. */ error InvalidRate(); /** * Thrown when the artifact ID being forged does not exist. */ error NonExistentCardId(); /** * Thrown when the card attempting to be forged is not an artifact. */ error CardNotArtifact(); /** * Thrown when attempting to re-use an already used nonce. */ error NonceUsed(); /** * Thrown when the recovered signer doesn't match the expected signer. */ error SignerMismatch(); /** * Thrown when the caller is not the origin. */ error CallerNotOrigin(); /** * Thrown when an invalid forge state is found. */ error InvalidForgeState(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ENUMS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Enum encapsulating the possible stats of the card forge. */ enum ForgeState { INACTIVE, ACTIVE } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Emitted when the forge state is updated. * @param oldState Old forge state. * @param newState New forge state. */ event ForgeStateUpdated(ForgeState oldState, ForgeState newState); /** * Emitted when the forge rate of a card tier is updated. * @param cardTier Tier of card whoms rate is being updated. * @param oldTierRate Old forge rate. * @param newTierRate New forge rate. */ event ForgeRateUpdated(Game.CardTier cardTier, uint256 oldTierRate, uint256 newTierRate); /** * Emitted when the `signer` address is updated. * @param oldSigner Old `signer` address. * @param newSigner New `signer` address. */ event SignerUpdated(address indexed oldSigner, address indexed newSigner); /** * Emitted when forge data is updated. * @param baseCardIds The base card IDs that can be forged. * @param weights Weightings associated with each `baseCardId` of `baseCardIds`. */ event ForgeDataUpdated(uint256[] baseCardIds, uint256[] weights); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Function used to forge a new unit card. Forging requires that the provided card IDs are of the same tier. * Upon forging, both cards are destroyed. * @param cardOneId First tokenized card ID. * @param cardTwoId Second tokenized card ID. */ function forgeUnit(uint256 cardOneId, uint256 cardTwoId) external; /** * Function used to set forge data relating to forgable cards and their respective weight. * @param baseCardIds Array of base card identifiers that can be forged. * @param weights Array of weightings associated with each base card. */ function setForgeData(uint256[] calldata baseCardIds, uint256[] calldata weights) external; /** * Function used to set a new forge rate for a specified card tier. * @param tier Card Tier to update forge rate for. * @param rate New rate of for the specified `tier`. */ function setForgeRate(Game.CardTier tier, uint256 rate) external; /** * Function used to toggle the forge state. */ function toggleForgeState() external; /** * Function used to set a new `signer` address. * @param newSigner New `signer` address value. */ function setSigner(address newSigner) external; /** * Function used to view the rate of a given card tier. * @param cardTier Game.CardTier value. */ function forgeRates(Game.CardTier cardTier) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; /** * @title ISeeder * @notice Interface for Seeder. */ interface ISeeder { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Thrown when the zero address is provided as input. */ error ZeroAddress(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Emitted when the game seed is updated. * @param oldSeed Old game seed. * @param newSeed New game seed. */ event GameSeedUpdated(uint256 oldSeed, uint256 newSeed); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Function used to get the current game seed and update it. The value returned * is the game seed prior to the update. */ function getAndUpdateGameSeed() external returns (uint256); /** * Function used to view the current game seed. */ function currentGameSeed() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import { ICardAbilities } from "./ICardAbilities.sol"; import { IERC721AUpgradeable } from "@erc721a-upgradeable/interfaces/IERC721AUpgradeable.sol"; import { Game } from "../types/Game.sol"; /** * @title IGameCards * @notice Interface for GameCards. */ interface IGameCards is IERC721AUpgradeable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Thrown when the zero address is provided. */ error ZeroAddress(); /** * Thrown when an input array of zero length is provided. */ error ZeroLengthArray(); /** * Thrown when trying to access data for a non-existent token ID. */ error NonExistentTokenId(); /** * Thrown when the caller is not the owner of the card. */ error CallerNotOwner(); /** * Thrown when the specified level does not match the expected level. */ error CardLevelMismatch(); /** * Thrown when the recovered signer does not match the expected signer. */ error SignerMismatch(); /** * Thrown when an invalid card level is provided. */ error InvalidCardLevel(); /** * Thrown when an invalid maximum card level is provided. */ error InvalidMaxLevel(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Emitted when a new player card is defined. * @param tokenId Unique token identifier. * @param newPlayerCard Information relating to the newly defined player card. */ event PlayerCardDefined(uint256 indexed tokenId, Game.PlayerCard newPlayerCard); /** * Emitted when the `Seeder` contract is updated. * @param oldSeeder Old `Seeder` contract address. * @param newSeeder New `Seeder` contract address. */ event SeederUpdated(address oldSeeder, address newSeeder); /** * Emitted when the `Abilities` contract is updated. * @param oldAbilities Old `Abilities` contract address. * @param newAbilities New `Abilities` contract address. */ event AbilitiesUpdated(address oldAbilities, address newAbilities); /** * Emitted when the `MetadataRenderer` contract is updated. * @param oldMetadataRenderer Old `MetadataRenderer` contract address. * @param newMetadataRenderer New `MetadataRenderer` contract address. */ event MetadataRendererUpdated(address oldMetadataRenderer, address newMetadataRenderer); /** * Emitted when the `signer` address is updated. * @param oldSigner Old `signer` address. * @param newSigner New `signer` address. */ event SignerUpdated(address indexed oldSigner, address indexed newSigner); /** * Emitted when the `baseCards` address is updated. * @param oldBaseCards Old `baseCards` address. * @param newBaseCards New `baseCards` address. */ event BaseCardsUpdated(address oldBaseCards, address newBaseCards); /** * Emitted when a player card is leveled. * @param tokenId Unique card identifier. * @param oldLevel Old card level. * @param newLevel New card level. */ event LevelUp(uint256 indexed tokenId, uint256 oldLevel, uint256 newLevel); /** * Emitted when the maximum card level is updated. * @param oldMaxLevel Old maximum card level. * @param newMaxLevel New maximum card level. */ event MaxCardLevelUpdated(uint256 oldMaxLevel, uint256 newMaxLevel); /** * Emitted when level stat modifiers are updated. * @param level Stat level being modified. * @param oldStatModifiers Old stat modifiers for `level`. * @param newStatModifiers New stat modifiers for `level`. */ event StatModifiersUpdated(uint256 indexed level, Game.Stats oldStatModifiers, Game.Stats newStatModifiers); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Function used to view the total number of derivative base cards that have been minted. * @param baseCardId Unique base card identifier. */ function serialNumbers(uint256 baseCardId) external view returns (uint256); /** * Function used to initialize the Cards contract. * @param _owner Contract owner. * @param _gameMaster Designed Game Master. * @param _signer Signer address. * @param _seeder Seeder contract. * @param _baseCards BaseCards contract. * @param _abilities Abilities contract. * @param _metadataRenderer Metadata renderer contract. * @param _blastGovernor Blast Governor contract. */ function initialize( address _owner, address _gameMaster, address _signer, address _seeder, address _baseCards, address _abilities, address _metadataRenderer, address _blastGovernor ) external; /** * Function used to mint new cards to the receiver. * @param cardIds Unique card identifiers to mint. * @param tierWeights Weightings associated with rolling a specific tier of card. * @param receiver Address to mint the new cards to. */ function mintCards(uint256[] calldata cardIds, uint256[6] calldata tierWeights, address receiver) external; /** * Function used to incinerate a list of cards. * @param tokenIds Array of card identifiers. */ function incinerate(uint256[] calldata tokenIds) external; /** * Function used to level up a card. * @param tokenId Unique card identifier. * @param newLevel Expected new level of the card. * @param signature Signed message digest. */ function levelUpCard(uint256 tokenId, uint256 newLevel, bytes calldata signature) external; /** * Function used to set a new `Seeder` value. * @param newSeeder New `Seeder` contract address. */ function setSeeder(address newSeeder) external; /** * Function used to set a new `BaseCards` value. * @param newBaseCards New `BaseCards` contract address. */ function setBaseCards(address newBaseCards) external; /** * Function used to set a new `Abilities` value. * @param newAbilities New `Abilities` contract address. */ function setAbilities(address newAbilities) external; /** * Function used to set a new `MetadataRenderer` value. * @param newMetadataRenderer New `MetadataRenderer` contract address. */ function setMetadataRenderer(address newMetadataRenderer) external; /** * Function used to set a new `signer` address. * @param newSigner New `signer` address value. */ function setSigner(address newSigner) external; /** * Function used to set stat modifiers for a specified card level. * @param level Card level to set stat modifiers for. * @param modifiers New stat modifiers for `level`. */ function setCardLevelModifiers(uint256 level, Game.Stats calldata modifiers) external; /** * Function used to set a new maximum card level. * @param newMaxLevel New maximum card level value. */ function setMaxCardLevel(uint256 newMaxLevel) external; /** * Function used to view the `Game.PlayerCard` struct for a given token idenitifer. * @param tokenId Unique token identifier. */ function playerCards(uint256 tokenId) external view returns (Game.PlayerCard memory); /** * Function used to view the current stat modifiers of a given card level. * @param cardLevel Card level to check modifiers for. */ function statModifiers(uint256 cardLevel) external view returns (Game.Stats memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import { Game } from "../types/Game.sol"; /** * @title IBaseCards * @notice Interface for BaseCards. */ interface IBaseCards { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Thrown when the zero address is provided as input. */ error ZeroAddress(); /** * Thrown when an input array of zero length is provided. */ error ZeroLengthArray(); /** * Thrown when invalid card attributes have been provided. */ error InvalidCardStats(); /** * Thrown when an undefined Game.Unit type is provided. */ error UndefinedUnitType(); /** * Thrown when an undefined archetype type is provided. */ error UndefinedArchetype(); /** * Thrown when an invalid card ID is provided. */ error InvalidCardId(); /** * Thrown when a duplicate archetype value is provided when adding base cards. */ error DuplicateArchetype(); /** * Thrown when an undefined card type is provided when editing a base card. */ error UndefinedCardType(); /** * Thrown when an invalid card tier is provided when editing a base card. */ error InvalidCardTier(); /** * Thrown when a zero length name is provided when editing a base card. */ error EmptyName(); /** * Thrown when a zero length image URI is provided when editing a base card. */ error EmptyImageURI(); /** * Thrown when a unit card has invalid stats. */ error InvalidUnitStats(); /** * Thrown when an undefined card tier is provided. */ error UndefinedCardTier(); /** * Thrown when no name or image URI are provided when editing a card. */ error EmptyParameters(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Emitted when a new base card is added to the game. * @param baseCardId Unique base card identifier. * @param newBaseCard Information relating to the newly added base card. */ event BaseCardAdded(uint256 indexed baseCardId, Game.BaseCard newBaseCard); /** * Emitted when a base card is modified. * @param baseCardId Unique base card identifier. * @param oldBaseCard Old `Game.BaseCard` struct. * @param newBaseCard New `Game.BaseCard` struct. */ event BaseCardUpdated(uint256 indexed baseCardId, Game.BaseCard oldBaseCard, Game.BaseCard newBaseCard); /** * Emitted when the image URI of a base card is modified. * @param baseCardId Unique base card identifier. * @param oldImageURI Old `imageURI` value. * @param newImageURI New `imageURI` value. */ event BaseCardImageURIUpdated(uint256 indexed baseCardId, string oldImageURI, string newImageURI); /** * Emitted when the `Game.BaseCard.name` value is modified. * @param baseCardId Unique base card identifier. * @param oldName Old `Game.BaseCard.name` value. * @param newName New `Game.BaseCard.name` value. */ event BaseCardNameUpdated(uint256 indexed baseCardId, string oldName, string newName); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Function used to view the total number of base cards. */ function baseCardCount() external view returns (uint256); /** * Function used to add new base cards to the game. * @param units Array of unit base cards to add. * @param artifacts Array of artifact base cards to add. */ function addBaseCards(Game.Unit[] calldata units, Game.Artifact[] calldata artifacts) external; /** * Function used to edit a base card. * @param baseCardId Unique base card identifier. * @param newBaseCard Newly desired `Game.BaseCard` struct. * @dev This function may only be called if tokenized versions of this card have never been minted. */ function editBaseCard(uint256 baseCardId, Game.BaseCard calldata newBaseCard) external; /** * Function used to modify the image URI of a base card. * @param baseCardId Unique base card identifier. * @param newName Newly desired `name` value. * @param newImageURI Newly desired `imageURI` value. */ function setNameAndImageURI(uint256 baseCardId, string calldata newName, string calldata newImageURI) external; /** * Function used to view the `Game.BaseCard` struct for a given card identifier. * @param baseCardId Unique base card idenitifer. */ function baseCards(uint256 baseCardId) external view returns (Game.BaseCard memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; /** * @title IBlast * @notice Interface for Blast. */ interface IBlast { enum YieldMode { AUTOMATIC, VOID, CLAIMABLE } enum GasMode { VOID, CLAIMABLE } // configure function configureContract(address contractAddress, YieldMode _yield, GasMode gasMode, address governor) external; function configure(YieldMode _yield, GasMode gasMode, address governor) external; // base configuration options function configureClaimableYield() external; function configureClaimableYieldOnBehalf(address contractAddress) external; function configureAutomaticYield() external; function configureAutomaticYieldOnBehalf(address contractAddress) external; function configureVoidYield() external; function configureVoidYieldOnBehalf(address contractAddress) external; function configureClaimableGas() external; function configureClaimableGasOnBehalf(address contractAddress) external; function configureVoidGas() external; function configureVoidGasOnBehalf(address contractAddress) external; function configureGovernor(address _governor) external; function configureGovernorOnBehalf(address _newGovernor, address contractAddress) external; // claim yield function claimYield(address contractAddress, address recipientOfYield, uint256 amount) external returns (uint256); function claimAllYield(address contractAddress, address recipientOfYield) external returns (uint256); // claim gas function claimAllGas(address contractAddress, address recipientOfGas) external returns (uint256); function claimGasAtMinClaimRate(address contractAddress, address recipientOfGas, uint256 minClaimRateBips) external returns (uint256); function claimMaxGas(address contractAddress, address recipientOfGas) external returns (uint256); function claimGas(address contractAddress, address recipientOfGas, uint256 gasToClaim, uint256 gasSecondsToConsume) external returns (uint256); // read functions function readClaimableYield(address contractAddress) external view returns (uint256); function readYieldConfiguration(address contractAddress) external view returns (uint8); function readGasParams(address contractAddress) external view returns (uint256 etherSeconds, uint256 etherBalance, uint256 lastUpdated, GasMode); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; /** * @title Game * @notice This library contains shared data types and structures that are used within the game. */ /** * Namespace used to encapsulate shared game data types and structures. */ library Game { /** * Enum encapsulating the various tiers that can be associated with a card. */ enum CardTier { UNDEFINED, C, B, A, S, SS, SSS } /** * Enum encapsulating the possible card types. */ enum CardType { UNDEFINED, UNIT, ARTIFACT } /** * Struct encapsulating general card stats. * @param HP Health Points. * @param PWR Base Power. * @param DEF Base Defense. * @param SPD Base Attack Speed. */ struct Stats { uint256 HP; uint256 PWR; uint256 DEF; uint256 SPD; } /** * Struct encapsulating information related to a unit base card. * @param name Name of the unit. * @param imageURI Unique resource identifier for the unit image. * @param unitType Type of unit the base card is. * @param stats Base stats of the unit. * @param archetypes Archetypes related to the unit. */ struct Unit { string name; string imageURI; uint16 unitType; Stats stats; uint16[] archetypes; } /** * Struct encapsulating information related to an artifact base card. * @param name Name of the artifact. * @param imageURI Unique resource idenitifier for the artifact image. * @param cardTier Base card tier of the artifact. * @param archetypes Archetypes related to the artifact. */ struct Artifact { string name; string imageURI; CardTier cardTier; uint16[] archetypes; } /** * Struct encapsulating information related to a base card. * @param name Name of the base card, this will either be the name of the unit or the artifact. * @param imageURI Unique resource identifier for the image, this will either be an image of a unit or an artifact. * @param cardType Either an artifact or a unit. * @param cardTier For artifacts this will be constant. For units, a tier will be determined upon mint. * @param stats For artifacts all stats will be 0. For units, stats will be determined upon mint. * @param archetypes Archetypes related to the underlying base card. */ struct BaseCard { string name; string imageURI; CardType cardType; CardTier cardTier; uint16 unitType; Stats stats; uint16[] archetypes; } /** * Struct encapsulating information related to a tokenized player card. * @param baseCardId Base card identifier associated with the player card. * @param serialNumber The number which indicates how many of this card existed at mint. * @param level Level of the card. * @param cardType Indicates if this card is an artifact or unit. * @param cardTier For artifacts this will be constant. For units, a tier will be determined upon mint. * @param unitType Type of unit associated with this card, an artifact will yield a `0` value. * @param stats For artifacts all stats will be 0. For units, stats will be determined upon mint. * @param archetypes Archetypes associated with the player card. * @param abilityIds Abilities associated with the player card. */ struct PlayerCard { uint256 baseCardId; uint256 serialNumber; uint256 level; CardType cardType; CardTier cardTier; uint16 unitType; Stats stats; uint16[] archetypes; uint256[3] abilityIds; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// While the ownable portion follows /// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, /// the nomenclature for the 2-step ownership handover may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev Cannot double-initialize. error AlreadyInitialized(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } } /// @dev Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`. revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(0)); } /// @dev Request a two-step ownership handover to the caller. /// The request will automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public payable virtual { unchecked { uint256 expires = block.timestamp + _ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`. revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly assembly { result := sload(_OWNER_SLOT) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 0x20)) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.20; import { Game } from "../types/Game.sol"; /** * @title ICardAbilities * @notice Interface for CardAbilities. */ interface ICardAbilities { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Thrown when a Ability input array of zero length is provided. */ error ZeroLengthArray(); /** * Thrown when an undefined archetype is provided. */ error UndefinedArchetype(); /** * Thrown when an empty ability name is provided. */ error EmptyName(); /** * Thrown when an undefined AbilityStars value is provided. */ error UndefinedAbilityStars(); /** * Thrown when the zero address is provided as input. */ error ZeroAddress(); /** * Thrown when the sum of weights doesn't equal 10_000. */ error InvalidWeightSum(); /** * Thrown when a non-existent ability ID is provided. */ error NonExistentAbilityId(); /** * Thrown when `Game.CardTier.UNDEFINED` is provided when updating weights. */ error UndefinedCardTier(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ENUMS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Enum encapsulating the number of stars that can be associated with an ability. */ enum AbilityStars { UNDEFINED, ONE, TWO, THREE } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Struct encapsulating an Ability. * @param name Name of the ability. * @param stars Star tier. * @param archetype Related archetype. */ struct Ability { string name; AbilityStars stars; uint16 archetype; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Emitted when an ability is added. * @param abilityId Unique ability identifier. * @param newAbility The new ability that was added. */ event AbilityAdded(uint256 indexed abilityId, Ability newAbility); /** * Emitted when an ability is removed. * @param abilityId Unique ability idenitfier. * @param ability Ability that has been removed. */ event AbilityRemoved(uint256 indexed abilityId, Ability ability); /** * Emitted when the name of an ability is updated. * @param abilityId Unique ability identifier. * @param oldName Old ability name. * @param newName New ability name. */ event AbilityNameUpdated(uint256 indexed abilityId, string oldName, string newName); /** * Emitted when card tier ability weights are updated. * @param cardTier Game.CardTier value. * @param oldWeights Old weight values. * @param newWeights New weight values. */ event WeightsUpdated(Game.CardTier cardTier, uint256[3] oldWeights, uint256[3] newWeights); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /** * Function used to view the total number of abilities. */ function abilityCount() external view returns (uint256); /** * Function used to add abilities. * @param newAbilities Array of abilities to add. */ function addAbilities(Ability[] calldata newAbilities) external; /** * Function used to edit an already existing ability name. * @param abilityId Unique ability identifier. * @param newName Newly desired name value. */ function editAbilityName(uint256 abilityId, string calldata newName) external; /** * Function used to remove an ability. * @param abilityId Unique ability idenitifer. * @custom:note This function should be called with extreme caution as removing an ability already associated with a * tokenized card break the game. */ function removeAbility(uint256 abilityId) external; /** * Function used to get abilities for a card. * @param cardTier Tier of the card. * @param archetypes Archetypes associated with the card. * @param ephemeralSeed Seed used to "randomise" ability choices. */ function getCardAbilities( Game.CardTier cardTier, uint16[] calldata archetypes, uint256 ephemeralSeed ) external view returns (uint256[3] memory abilities); /** * Function used to update card tier ability weights. * @param cardTier Card tier to update weights for. * @param updatedWeights Updated card tier weights. */ function updateWeights(Game.CardTier cardTier, uint256[3] calldata updatedWeights) external; /** * Function used to view the ability associated with an ID. * @param abilityId Unique ability identifier. */ function idToAbility(uint256 abilityId) external view returns (Ability memory); /** * Function used to view the sorted abilities for a given archetype at a specified star tier. * @param archetype Archetype of the unit. * @param stars Star tier rating to lookup. */ function sortedAbilities(uint16 archetype, AbilityStars stars) external view returns (uint256[] memory); /** * Function used to view the star tier weights of a given card tier. * @param cardTier Tier of card to check weights for. */ function weights(Game.CardTier cardTier) external view returns (uint256[3] memory); }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721AUpgradeable.sol';
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721AUpgradeable { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external payable; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
{ "remappings": [ "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@erc721a-upgradeable/=lib/ERC721A-Upgradeable/contracts/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "@openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "@openzeppelin-contracts/=lib/openzeppelin-contracts/", "@solady/=lib/solady/", "@v2-core/=lib/v2-core/contracts/", "@v2-periphery/=lib/v2-periphery/contracts/", "ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solady/=lib/solady/", "v2-core/=lib/v2-core/contracts/", "v2-periphery/=lib/v2-periphery/contracts/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_gameMaster","type":"address"},{"internalType":"address","name":"_signer","type":"address"},{"internalType":"address","name":"_seeder","type":"address"},{"internalType":"address","name":"_gameCards","type":"address"},{"internalType":"address","name":"_baseCards","type":"address"},{"internalType":"address","name":"_blastGovernor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[],"name":"CallerNotOrigin","type":"error"},{"inputs":[],"name":"CallerNotOwner","type":"error"},{"inputs":[],"name":"CardNotArtifact","type":"error"},{"inputs":[],"name":"CardTierMismatch","type":"error"},{"inputs":[],"name":"DuplicateBaseCardId","type":"error"},{"inputs":[],"name":"DuplicateCardId","type":"error"},{"inputs":[],"name":"InvalidBaseCardId","type":"error"},{"inputs":[],"name":"InvalidCardType","type":"error"},{"inputs":[],"name":"InvalidForgeState","type":"error"},{"inputs":[],"name":"InvalidRate","type":"error"},{"inputs":[],"name":"InvalidWeightSum","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NonExistentCardId","type":"error"},{"inputs":[],"name":"NonceUsed","type":"error"},{"inputs":[],"name":"SignerMismatch","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UndefinedCardTier","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroLengthArray","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"baseCardIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"ForgeDataUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum Game.CardTier","name":"cardTier","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"oldTierRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTierRate","type":"uint256"}],"name":"ForgeRateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum ICardForge.ForgeState","name":"oldState","type":"uint8"},{"indexed":false,"internalType":"enum ICardForge.ForgeState","name":"newState","type":"uint8"}],"name":"ForgeStateUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":true,"internalType":"address","name":"newSigner","type":"address"}],"name":"SignerUpdated","type":"event"},{"inputs":[],"name":"BLAST","outputs":[{"internalType":"contract IBlast","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseCards","outputs":[{"internalType":"contract IBaseCards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"cardWeights","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"baseCardId","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"forgeArtifact","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"forgeCards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum Game.CardTier","name":"cardTier","type":"uint8"}],"name":"forgeRates","outputs":[{"internalType":"uint256","name":"rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"forgeState","outputs":[{"internalType":"enum ICardForge.ForgeState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"cardOneId","type":"uint256"},{"internalType":"uint256","name":"cardTwoId","type":"uint256"}],"name":"forgeUnit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gameCards","outputs":[{"internalType":"contract IGameCards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"nonceUsed","outputs":[{"internalType":"bool","name":"used","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"seeder","outputs":[{"internalType":"contract ISeeder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"baseCardIds","type":"uint256[]"},{"internalType":"uint256[]","name":"weights","type":"uint256[]"}],"name":"setForgeData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Game.CardTier","name":"tier","type":"uint8"},{"internalType":"uint256","name":"rate","type":"uint256"}],"name":"setForgeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigner","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleForgeState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a06040527343000000000000000000000000000000000000026080523480156200002957600080fd5b5060405162002b9838038062002b988339810160408190526200004c91620002c6565b6001600160a01b03861615806200006a57506001600160a01b038516155b806200007d57506001600160a01b038416155b806200009057506001600160a01b038316155b80620000a357506001600160a01b038216155b80620000b657506001600160a01b038116155b15620000d55760405163d92e233d60e01b815260040160405180910390fd5b6080516001600160a01b0316634e606c476040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156200011357600080fd5b505af115801562000128573d6000803e3d6000fd5b5050608051604051631d70c8d360e31b81526001600160a01b038581166004830152909116925063eb8646989150602401600060405180830381600087803b1580156200017457600080fd5b505af115801562000189573d6000803e3d6000fd5b505050506200019e336200020160201b60201c565b620001ab8660016200023d565b50600280546001600160a01b039586166001600160a01b03199182161790915560038054948616948216949094179093556004805492851692841692909217909155600580549190931691161790555062000347565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6200024b828260016200024f565b5050565b638b78c6d8600c52826000526020600c2080548381178362000272575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b80516001600160a01b0381168114620002c157600080fd5b919050565b60008060008060008060c08789031215620002e057600080fd5b620002eb87620002a9565b9550620002fb60208801620002a9565b94506200030b60408801620002a9565b93506200031b60608801620002a9565b92506200032b60808801620002a9565b91506200033b60a08801620002a9565b90509295509295509295565b6080516128356200036360003960006104e801526128356000f3fe6080604052600436106101c25760003560e01c80636c19e783116100f757806397d7577611610095578063e3a62bd511610064578063e3a62bd51461056c578063f04e283e14610599578063f2fde38b146105ac578063fee81cf4146105bf57600080fd5b806397d75776146104d6578063982463de1461050a578063b852ddbd1461051f578063bad956a01461053f57600080fd5b80637afb9b1d116100d15780637afb9b1d146104255780637e941a0d146104525780638da5cb5b1461047257806394d0d3a6146104a657600080fd5b80636c19e783146103dd578063715018a6146103fd578063788986741461040557600080fd5b80632de94807116101645780634a4ee7b11161013e5780634a4ee7b11461035e578063514e62fc1461037157806354d1f13d146103a8578063684931ed146103b057600080fd5b80632de94807146102be57806338c73fd4146102ff5780633dd05e741461031f57600080fd5b80631cd64df4116101a05780631cd64df41461020f57806320b4eb0214610244578063238ac9331461026457806325692962146102b657600080fd5b80630729faec146101c7578063183a4f6e146101e95780631c10893f146101fc575b600080fd5b3480156101d357600080fd5b506101e76101e2366004611dee565b6105f2565b005b6101e76101f7366004611e1a565b610742565b6101e761020a366004611e55565b61074f565b34801561021b57600080fd5b5061022f61022a366004611e55565b610765565b60405190151581526020015b60405180910390f35b34801561025057600080fd5b506101e761025f366004611e73565b610784565b34801561027057600080fd5b506002546102919073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023b565b6101e7610bf6565b3480156102ca57600080fd5b506102f16102d9366004611ef3565b638b78c6d8600c908152600091909152602090205490565b60405190815260200161023b565b34801561030b57600080fd5b506102f161031a366004611e1a565b610c46565b34801561032b57600080fd5b506005546103519074010000000000000000000000000000000000000000900460ff1681565b60405161023b9190611f5a565b6101e761036c366004611e55565b610c67565b34801561037d57600080fd5b5061022f61038c366004611e55565b638b78c6d8600c90815260009290925260209091205416151590565b6101e7610c79565b3480156103bc57600080fd5b506003546102919073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103e957600080fd5b506101e76103f8366004611ef3565b610cb5565b6101e7610d85565b34801561041157600080fd5b506102f1610420366004611e1a565b610d99565b34801561043157600080fd5b506005546102919073ffffffffffffffffffffffffffffffffffffffff1681565b34801561045e57600080fd5b506101e761046d366004611fb4565b610da9565b34801561047e57600080fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754610291565b3480156104b257600080fd5b5061022f6104c1366004611e1a565b60076020526000908152604090205460ff1681565b3480156104e257600080fd5b506102917f000000000000000000000000000000000000000000000000000000000000000081565b34801561051657600080fd5b506101e7610e7e565b34801561052b57600080fd5b506101e761053a366004612020565b610f78565b34801561054b57600080fd5b506004546102919073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057857600080fd5b506102f1610587366004612042565b60066020526000908152604090205481565b6101e76105a7366004611ef3565b6117fa565b6101e76105ba366004611ef3565b611837565b3480156105cb57600080fd5b506102f16105da366004611ef3565b63389a75e1600c908152600091909152602090205490565b60016105fd8161185e565b600083600681111561061157610611611f17565b03610648576040517feb6f0afc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b811580610656575061271082115b1561068d576040517f6a43f8d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600660008560068111156106a5576106a5611f17565b60068111156106b6576106b6611f17565b815260200190815260200160002054905082600660008660068111156106de576106de611f17565b60068111156106ef576106ef611f17565b8152602001908152602001600020819055507f700ee87de9c5bf5a2b0958958edcf5f0c99fa188324cba9fb9c183570cb2f18a8482856040516107349392919061205f565b60405180910390a150505050565b61074c3382611884565b50565b610757611890565b61076182826118c6565b5050565b638b78c6d8600c90815260008390526020902054811681145b92915050565b600161078f816118d2565b84158061082b5750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c3702fa76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108289190612087565b85115b15610862576040517f0d4a929c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546040517fabb051740000000000000000000000000000000000000000000000000000000081526004810187905260029173ffffffffffffffffffffffffffffffffffffffff169063abb0517490602401600060405180830381865afa1580156108d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610918919081019061232c565b60400151600281111561092d5761092d611f17565b14610964576040517fdbbad12800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101869052605481018590526000906109eb90607401604051602081830303815290604052805190602001206020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c60042090565b600254604080516020601f880181900481028201810190925286815292935073ffffffffffffffffffffffffffffffffffffffff90911691610a4a918790879081908401838280828437600092019190915250869392505061194a9050565b73ffffffffffffffffffffffffffffffffffffffff1614610a97576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008581526007602052604090205460ff1615610ae0576040517f1f6d5aef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260076020526040808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116811790915581518181528083019092528160200160208202803683370190505090508681600081518110610b4d57610b4d612428565b602002602001018181525050610b61611d63565b600480546040517f03728ca300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116916303728ca391610bba9186918691339101612492565b600060405180830381600087803b158015610bd457600080fd5b505af1158015610be8573d6000803e3d6000fd5b505050505050505050505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60008181548110610c5657600080fd5b600091825260209091200154905081565b610c6f611890565b6107618282611884565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6001610cc08161185e565b73ffffffffffffffffffffffffffffffffffffffff8216610d0d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f2d025324f0a785e8c12d0a0d91a9caa49df4ef20ff87e0df7213a1d4f3157beb90600090a3505050565b610d8d611890565b610d9760006119f4565b565b60018181548110610c5657600080fd5b6001610db48161185e565b610e2185858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250611a5a92505050565b610e2d60008686611d81565b50610e3a60018484611d81565b507f21336086afa28f44951f6287ed7224dfa13b3403e2897cbad149b2f9742593cd85856001604051610e6f939291906124f7565b60405180910390a15050505050565b6001610e898161185e565b60055474010000000000000000000000000000000000000000900460ff166000816001811115610ebb57610ebb611f17565b14610ec7576000610eca565b60015b600580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000836001811115610f1857610f18611f17565b02179055506005546040517f0442bef59385629203a86ca0e64ce802bea1a6ca4799b54c80e56b33a1de5da391610f6c91849174010000000000000000000000000000000000000000900460ff1690612598565b60405180910390a15050565b6001610f83816118d2565b333214610fbc576040517fe02c6ccf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818303610ff5576040517fdbbf2f4800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546040517f6352211e00000000000000000000000000000000000000000000000000000000815291820185905273ffffffffffffffffffffffffffffffffffffffff1690636352211e90602401602060405180830381865afa158015611062573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108691906125b3565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110ea576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546040517f6352211e00000000000000000000000000000000000000000000000000000000815291820184905273ffffffffffffffffffffffffffffffffffffffff1690636352211e90602401602060405180830381865afa158015611157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117b91906125b3565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111df576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546040517f4dc0884f00000000000000000000000000000000000000000000000000000000815291820185905260009173ffffffffffffffffffffffffffffffffffffffff90911690634dc0884f90602401600060405180830381865afa158015611251573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611297919081019061263e565b600480546040517f4dc0884f00000000000000000000000000000000000000000000000000000000815291820186905291925060009173ffffffffffffffffffffffffffffffffffffffff1690634dc0884f90602401600060405180830381865afa15801561130a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611350919081019061263e565b90508060800151600681111561136857611368611f17565b8260800151600681111561137e5761137e611f17565b146113b5576040517f41dc2d2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001826060015160028111156113cd576113cd611f17565b1415806113f057506001816060015160028111156113ed576113ed611f17565b14155b15611427576040517f7dbbb63500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516002808252606082018352600092602083019080368337019050509050858160008151811061145c5761145c612428565b602002602001018181525050848160018151811061147c5761147c612428565b6020908102919091010152600480546040517fcf46fd0100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169163cf46fd01916114dc91859101612724565b600060405180830381600087803b1580156114f657600080fd5b505af115801561150a573d6000803e3d6000fd5b505050506000600660008560800151600681111561152a5761152a611f17565b600681111561153b5761153b611f17565b815260200190815260200160002054905080600003611586576040517f6a43f8d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600354604080517f05587775000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916305587775916004808301926020929190829003018187875af11580156115f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161b9190612087565b9050600061162b61271083612737565b6116369060016127a1565b905060008361164761271085612737565b6116529060016127a1565b116116b55760068760800151600681111561166f5761166f611f17565b146116ab578660800151600681111561168a5761168a611f17565b6116959060016127a1565b60068111156116a6576116a6611f17565b6116ae565b60065b90506116bc565b5060808601515b604080516001808252818301909252600091602080830190803683370190505090506000805b60015481101561177257600181815481106116ff576116ff612428565b90600052602060002001548261171591906127a1565b9150818511611760576000818154811061173157611731612428565b90600052602060002001548360008151811061174f5761174f612428565b602002602001018181525050611772565b8061176a816127b4565b9150506116e2565b5060045473ffffffffffffffffffffffffffffffffffffffff166303728ca38361179b86611c9f565b336040518463ffffffff1660e01b81526004016117ba93929190612492565b600060405180830381600087803b1580156117d457600080fd5b505af11580156117e8573d6000803e3d6000fd5b50505050505050505050505050505050565b611802611890565b63389a75e1600c52806000526020600c20805442111561182a57636f5e88186000526004601cfd5b6000905561074c816119f4565b61183f611890565b8060601b61185557637448fbae6000526004601cfd5b61074c816119f4565b638b78c6d8600c5233600052806020600c20541661074c576382b429006000526004601cfd5b61076182826000611d0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610d97576382b429006000526004601cfd5b61076182826001611d0a565b8060018111156118e4576118e4611f17565b60055474010000000000000000000000000000000000000000900460ff16600181111561191357611913611f17565b1461074c576040517f3e36381900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051600190836000526020830151604052604083510361199f57604083015160ff81901c601b016020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff166060526119c5565b60418351036119c057606083015160001a60205260408301516060526119c5565b600091505b6020600160806000855afa5191503d6119e657638baa579f6000526004601cfd5b600060605260405292915050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927805473ffffffffffffffffffffffffffffffffffffffff9092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b8051825114611a95576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151600003611ad0576040517f0f59b9ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554604080517fc3702fa7000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163c3702fa79160048083019260209291908290030181865afa158015611b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b649190612087565b905060008060005b8551811015611c5c576000868281518110611b8957611b89612428565b602002602001015190508060001480611ba157508481115b15611bd8576040517fadb070da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8083901c600116600103611c18576040517f2ba6e3e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001901b83179250858281518110611c3357611c33612428565b602002602001015184611c4691906127a1565b9350508080611c54906127b4565b915050611b6c565b506127108214611c98576040517f940addc700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b611ca7611d63565b60006006836006811115611cbd57611cbd611f17565b14611ce5576001836006811115611cd657611cd6611f17565b611ce091906127ec565b611ce8565b60055b9050612710828260068110611cff57611cff612428565b602002015250919050565b638b78c6d8600c52826000526020600c20805483811783611d2c575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b6040518060c001604052806006906020820280368337509192915050565b828054828255906000526020600020908101928215611dbc579160200282015b82811115611dbc578235825591602001919060010190611da1565b50611dc8929150611dcc565b5090565b5b80821115611dc85760008155600101611dcd565b6007811061074c57600080fd5b60008060408385031215611e0157600080fd5b8235611e0c81611de1565b946020939093013593505050565b600060208284031215611e2c57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461074c57600080fd5b60008060408385031215611e6857600080fd5b8235611e0c81611e33565b60008060008060608587031215611e8957600080fd5b8435935060208501359250604085013567ffffffffffffffff80821115611eaf57600080fd5b818701915087601f830112611ec357600080fd5b813581811115611ed257600080fd5b886020828501011115611ee457600080fd5b95989497505060200194505050565b600060208284031215611f0557600080fd5b8135611f1081611e33565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110611f5657611f56611f17565b9052565b6020810161077e8284611f46565b60008083601f840112611f7a57600080fd5b50813567ffffffffffffffff811115611f9257600080fd5b6020830191508360208260051b8501011115611fad57600080fd5b9250929050565b60008060008060408587031215611fca57600080fd5b843567ffffffffffffffff80821115611fe257600080fd5b611fee88838901611f68565b9096509450602087013591508082111561200757600080fd5b5061201487828801611f68565b95989497509550505050565b6000806040838503121561203357600080fd5b50508035926020909101359150565b60006020828403121561205457600080fd5b8135611f1081611de1565b606081016007851061207357612073611f17565b938152602081019290925260409091015290565b60006020828403121561209957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff811182821017156120f2576120f26120a0565b60405290565b604051610120810167ffffffffffffffff811182821017156120f2576120f26120a0565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612163576121636120a0565b604052919050565b600082601f83011261217c57600080fd5b815167ffffffffffffffff811115612196576121966120a0565b60206121c8817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160161211c565b82815285828487010111156121dc57600080fd5b60005b838110156121fa5785810183015182820184015282016121df565b506000928101909101919091529392505050565b80516003811061221d57600080fd5b919050565b805161221d81611de1565b805161ffff8116811461221d57600080fd5b60006080828403121561225157600080fd5b6040516080810181811067ffffffffffffffff82111715612274576122746120a0565b8060405250809150825181526020830151602082015260408301516040820152606083015160608201525092915050565b600082601f8301126122b657600080fd5b8151602067ffffffffffffffff8211156122d2576122d26120a0565b8160051b6122e182820161211c565b92835284810182019282810190878511156122fb57600080fd5b83870192505b84831015612321576123128361222d565b82529183019190830190612301565b979650505050505050565b60006020828403121561233e57600080fd5b815167ffffffffffffffff8082111561235657600080fd5b90830190610140828603121561236b57600080fd5b6123736120cf565b82518281111561238257600080fd5b61238e8782860161216b565b8252506020830151828111156123a357600080fd5b6123af8782860161216b565b6020830152506123c16040840161220e565b60408201526123d260608401612222565b60608201526123e36080840161222d565b60808201526123f58660a0850161223f565b60a08201526101208301518281111561240d57600080fd5b612419878286016122a5565b60c08301525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081518084526020808501945080840160005b838110156124875781518752958201959082019060010161246b565b509495945050505050565b60006101008083526124a681840187612457565b91505060208083018560005b60068110156124cf578151835291830191908301906001016124b2565b5050505073ffffffffffffffffffffffffffffffffffffffff831660e0830152949350505050565b6040815282604082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84111561253057600080fd5b8360051b8086606085013780830190506060810160206060858403018186015281865480845260808501915087600052826000209450600093505b8084101561258b578454825260019485019493909301929082019061256b565b5098975050505050505050565b604081016125a68285611f46565b611f106020830184611f46565b6000602082840312156125c557600080fd5b8151611f1081611e33565b600082601f8301126125e157600080fd5b6040516060810181811067ffffffffffffffff82111715612604576126046120a0565b60405280606084018581111561261957600080fd5b845b8181101561263357805183526020928301920161261b565b509195945050505050565b60006020828403121561265057600080fd5b815167ffffffffffffffff8082111561266857600080fd5b908301906101c0828603121561267d57600080fd5b6126856120f8565b8251815260208301516020820152604083015160408201526126a96060840161220e565b60608201526126ba60808401612222565b60808201526126cb60a0840161222d565b60a08201526126dd8660c0850161223f565b60c0820152610140830151828111156126f557600080fd5b612701878286016122a5565b60e0830152506127158661016085016125d0565b61010082015295945050505050565b602081526000611f106020830184612457565b60008261276d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561077e5761077e612772565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036127e5576127e5612772565b5060010190565b8181038181111561077e5761077e61277256fea2646970667358221220c30ffd88d33a7d906724603089fda7e42e4a35e5c3f49001288e38605de6257c64736f6c6343000814003300000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de50000000000000000000000001facd50481d827d7d342d79278b9c5a1f9eb6cd70000000000000000000000004131ae1e157c91fe083bdcf857a230fb79ac903a00000000000000000000000010fe37bac405b209f83ff523fb8d00c0c3f508a8000000000000000000000000c8607c5befa7a7567ca78040ba5c36d181243ac1000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
Deployed Bytecode
0x6080604052600436106101c25760003560e01c80636c19e783116100f757806397d7577611610095578063e3a62bd511610064578063e3a62bd51461056c578063f04e283e14610599578063f2fde38b146105ac578063fee81cf4146105bf57600080fd5b806397d75776146104d6578063982463de1461050a578063b852ddbd1461051f578063bad956a01461053f57600080fd5b80637afb9b1d116100d15780637afb9b1d146104255780637e941a0d146104525780638da5cb5b1461047257806394d0d3a6146104a657600080fd5b80636c19e783146103dd578063715018a6146103fd578063788986741461040557600080fd5b80632de94807116101645780634a4ee7b11161013e5780634a4ee7b11461035e578063514e62fc1461037157806354d1f13d146103a8578063684931ed146103b057600080fd5b80632de94807146102be57806338c73fd4146102ff5780633dd05e741461031f57600080fd5b80631cd64df4116101a05780631cd64df41461020f57806320b4eb0214610244578063238ac9331461026457806325692962146102b657600080fd5b80630729faec146101c7578063183a4f6e146101e95780631c10893f146101fc575b600080fd5b3480156101d357600080fd5b506101e76101e2366004611dee565b6105f2565b005b6101e76101f7366004611e1a565b610742565b6101e761020a366004611e55565b61074f565b34801561021b57600080fd5b5061022f61022a366004611e55565b610765565b60405190151581526020015b60405180910390f35b34801561025057600080fd5b506101e761025f366004611e73565b610784565b34801561027057600080fd5b506002546102919073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161023b565b6101e7610bf6565b3480156102ca57600080fd5b506102f16102d9366004611ef3565b638b78c6d8600c908152600091909152602090205490565b60405190815260200161023b565b34801561030b57600080fd5b506102f161031a366004611e1a565b610c46565b34801561032b57600080fd5b506005546103519074010000000000000000000000000000000000000000900460ff1681565b60405161023b9190611f5a565b6101e761036c366004611e55565b610c67565b34801561037d57600080fd5b5061022f61038c366004611e55565b638b78c6d8600c90815260009290925260209091205416151590565b6101e7610c79565b3480156103bc57600080fd5b506003546102919073ffffffffffffffffffffffffffffffffffffffff1681565b3480156103e957600080fd5b506101e76103f8366004611ef3565b610cb5565b6101e7610d85565b34801561041157600080fd5b506102f1610420366004611e1a565b610d99565b34801561043157600080fd5b506005546102919073ffffffffffffffffffffffffffffffffffffffff1681565b34801561045e57600080fd5b506101e761046d366004611fb4565b610da9565b34801561047e57600080fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754610291565b3480156104b257600080fd5b5061022f6104c1366004611e1a565b60076020526000908152604090205460ff1681565b3480156104e257600080fd5b506102917f000000000000000000000000430000000000000000000000000000000000000281565b34801561051657600080fd5b506101e7610e7e565b34801561052b57600080fd5b506101e761053a366004612020565b610f78565b34801561054b57600080fd5b506004546102919073ffffffffffffffffffffffffffffffffffffffff1681565b34801561057857600080fd5b506102f1610587366004612042565b60066020526000908152604090205481565b6101e76105a7366004611ef3565b6117fa565b6101e76105ba366004611ef3565b611837565b3480156105cb57600080fd5b506102f16105da366004611ef3565b63389a75e1600c908152600091909152602090205490565b60016105fd8161185e565b600083600681111561061157610611611f17565b03610648576040517feb6f0afc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b811580610656575061271082115b1561068d576040517f6a43f8d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600660008560068111156106a5576106a5611f17565b60068111156106b6576106b6611f17565b815260200190815260200160002054905082600660008660068111156106de576106de611f17565b60068111156106ef576106ef611f17565b8152602001908152602001600020819055507f700ee87de9c5bf5a2b0958958edcf5f0c99fa188324cba9fb9c183570cb2f18a8482856040516107349392919061205f565b60405180910390a150505050565b61074c3382611884565b50565b610757611890565b61076182826118c6565b5050565b638b78c6d8600c90815260008390526020902054811681145b92915050565b600161078f816118d2565b84158061082b5750600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c3702fa76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108289190612087565b85115b15610862576040517f0d4a929c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6005546040517fabb051740000000000000000000000000000000000000000000000000000000081526004810187905260029173ffffffffffffffffffffffffffffffffffffffff169063abb0517490602401600060405180830381865afa1580156108d2573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610918919081019061232c565b60400151600281111561092d5761092d611f17565b14610964576040517fdbbad12800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101869052605481018590526000906109eb90607401604051602081830303815290604052805190602001206020527b19457468657265756d205369676e6564204d6573736167653a0a3332600052603c60042090565b600254604080516020601f880181900481028201810190925286815292935073ffffffffffffffffffffffffffffffffffffffff90911691610a4a918790879081908401838280828437600092019190915250869392505061194a9050565b73ffffffffffffffffffffffffffffffffffffffff1614610a97576040517f10c74b0300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008581526007602052604090205460ff1615610ae0576040517f1f6d5aef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260076020526040808220805460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909116811790915581518181528083019092528160200160208202803683370190505090508681600081518110610b4d57610b4d612428565b602002602001018181525050610b61611d63565b600480546040517f03728ca300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116916303728ca391610bba9186918691339101612492565b600060405180830381600087803b158015610bd457600080fd5b505af1158015610be8573d6000803e3d6000fd5b505050505050505050505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60008181548110610c5657600080fd5b600091825260209091200154905081565b610c6f611890565b6107618282611884565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6001610cc08161185e565b73ffffffffffffffffffffffffffffffffffffffff8216610d0d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002805473ffffffffffffffffffffffffffffffffffffffff8481167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f2d025324f0a785e8c12d0a0d91a9caa49df4ef20ff87e0df7213a1d4f3157beb90600090a3505050565b610d8d611890565b610d9760006119f4565b565b60018181548110610c5657600080fd5b6001610db48161185e565b610e2185858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808902828101820190935288825290935088925087918291850190849080828437600092019190915250611a5a92505050565b610e2d60008686611d81565b50610e3a60018484611d81565b507f21336086afa28f44951f6287ed7224dfa13b3403e2897cbad149b2f9742593cd85856001604051610e6f939291906124f7565b60405180910390a15050505050565b6001610e898161185e565b60055474010000000000000000000000000000000000000000900460ff166000816001811115610ebb57610ebb611f17565b14610ec7576000610eca565b60015b600580547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000836001811115610f1857610f18611f17565b02179055506005546040517f0442bef59385629203a86ca0e64ce802bea1a6ca4799b54c80e56b33a1de5da391610f6c91849174010000000000000000000000000000000000000000900460ff1690612598565b60405180910390a15050565b6001610f83816118d2565b333214610fbc576040517fe02c6ccf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818303610ff5576040517fdbbf2f4800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546040517f6352211e00000000000000000000000000000000000000000000000000000000815291820185905273ffffffffffffffffffffffffffffffffffffffff1690636352211e90602401602060405180830381865afa158015611062573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108691906125b3565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110ea576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546040517f6352211e00000000000000000000000000000000000000000000000000000000815291820184905273ffffffffffffffffffffffffffffffffffffffff1690636352211e90602401602060405180830381865afa158015611157573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117b91906125b3565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146111df576040517f5cd8319200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480546040517f4dc0884f00000000000000000000000000000000000000000000000000000000815291820185905260009173ffffffffffffffffffffffffffffffffffffffff90911690634dc0884f90602401600060405180830381865afa158015611251573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611297919081019061263e565b600480546040517f4dc0884f00000000000000000000000000000000000000000000000000000000815291820186905291925060009173ffffffffffffffffffffffffffffffffffffffff1690634dc0884f90602401600060405180830381865afa15801561130a573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611350919081019061263e565b90508060800151600681111561136857611368611f17565b8260800151600681111561137e5761137e611f17565b146113b5576040517f41dc2d2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001826060015160028111156113cd576113cd611f17565b1415806113f057506001816060015160028111156113ed576113ed611f17565b14155b15611427576040517f7dbbb63500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516002808252606082018352600092602083019080368337019050509050858160008151811061145c5761145c612428565b602002602001018181525050848160018151811061147c5761147c612428565b6020908102919091010152600480546040517fcf46fd0100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169163cf46fd01916114dc91859101612724565b600060405180830381600087803b1580156114f657600080fd5b505af115801561150a573d6000803e3d6000fd5b505050506000600660008560800151600681111561152a5761152a611f17565b600681111561153b5761153b611f17565b815260200190815260200160002054905080600003611586576040517f6a43f8d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600354604080517f05587775000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff16916305587775916004808301926020929190829003018187875af11580156115f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161b9190612087565b9050600061162b61271083612737565b6116369060016127a1565b905060008361164761271085612737565b6116529060016127a1565b116116b55760068760800151600681111561166f5761166f611f17565b146116ab578660800151600681111561168a5761168a611f17565b6116959060016127a1565b60068111156116a6576116a6611f17565b6116ae565b60065b90506116bc565b5060808601515b604080516001808252818301909252600091602080830190803683370190505090506000805b60015481101561177257600181815481106116ff576116ff612428565b90600052602060002001548261171591906127a1565b9150818511611760576000818154811061173157611731612428565b90600052602060002001548360008151811061174f5761174f612428565b602002602001018181525050611772565b8061176a816127b4565b9150506116e2565b5060045473ffffffffffffffffffffffffffffffffffffffff166303728ca38361179b86611c9f565b336040518463ffffffff1660e01b81526004016117ba93929190612492565b600060405180830381600087803b1580156117d457600080fd5b505af11580156117e8573d6000803e3d6000fd5b50505050505050505050505050505050565b611802611890565b63389a75e1600c52806000526020600c20805442111561182a57636f5e88186000526004601cfd5b6000905561074c816119f4565b61183f611890565b8060601b61185557637448fbae6000526004601cfd5b61074c816119f4565b638b78c6d8600c5233600052806020600c20541661074c576382b429006000526004601cfd5b61076182826000611d0a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927543314610d97576382b429006000526004601cfd5b61076182826001611d0a565b8060018111156118e4576118e4611f17565b60055474010000000000000000000000000000000000000000900460ff16600181111561191357611913611f17565b1461074c576040517f3e36381900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604051600190836000526020830151604052604083510361199f57604083015160ff81901c601b016020527f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff166060526119c5565b60418351036119c057606083015160001a60205260408301516060526119c5565b600091505b6020600160806000855afa5191503d6119e657638baa579f6000526004601cfd5b600060605260405292915050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927805473ffffffffffffffffffffffffffffffffffffffff9092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b8051825114611a95576040517fa24a13a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151600003611ad0576040517f0f59b9ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600554604080517fc3702fa7000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163c3702fa79160048083019260209291908290030181865afa158015611b40573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b649190612087565b905060008060005b8551811015611c5c576000868281518110611b8957611b89612428565b602002602001015190508060001480611ba157508481115b15611bd8576040517fadb070da00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8083901c600116600103611c18576040517f2ba6e3e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806001901b83179250858281518110611c3357611c33612428565b602002602001015184611c4691906127a1565b9350508080611c54906127b4565b915050611b6c565b506127108214611c98576040517f940addc700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b611ca7611d63565b60006006836006811115611cbd57611cbd611f17565b14611ce5576001836006811115611cd657611cd6611f17565b611ce091906127ec565b611ce8565b60055b9050612710828260068110611cff57611cff612428565b602002015250919050565b638b78c6d8600c52826000526020600c20805483811783611d2c575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b6040518060c001604052806006906020820280368337509192915050565b828054828255906000526020600020908101928215611dbc579160200282015b82811115611dbc578235825591602001919060010190611da1565b50611dc8929150611dcc565b5090565b5b80821115611dc85760008155600101611dcd565b6007811061074c57600080fd5b60008060408385031215611e0157600080fd5b8235611e0c81611de1565b946020939093013593505050565b600060208284031215611e2c57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461074c57600080fd5b60008060408385031215611e6857600080fd5b8235611e0c81611e33565b60008060008060608587031215611e8957600080fd5b8435935060208501359250604085013567ffffffffffffffff80821115611eaf57600080fd5b818701915087601f830112611ec357600080fd5b813581811115611ed257600080fd5b886020828501011115611ee457600080fd5b95989497505060200194505050565b600060208284031215611f0557600080fd5b8135611f1081611e33565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110611f5657611f56611f17565b9052565b6020810161077e8284611f46565b60008083601f840112611f7a57600080fd5b50813567ffffffffffffffff811115611f9257600080fd5b6020830191508360208260051b8501011115611fad57600080fd5b9250929050565b60008060008060408587031215611fca57600080fd5b843567ffffffffffffffff80821115611fe257600080fd5b611fee88838901611f68565b9096509450602087013591508082111561200757600080fd5b5061201487828801611f68565b95989497509550505050565b6000806040838503121561203357600080fd5b50508035926020909101359150565b60006020828403121561205457600080fd5b8135611f1081611de1565b606081016007851061207357612073611f17565b938152602081019290925260409091015290565b60006020828403121561209957600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff811182821017156120f2576120f26120a0565b60405290565b604051610120810167ffffffffffffffff811182821017156120f2576120f26120a0565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612163576121636120a0565b604052919050565b600082601f83011261217c57600080fd5b815167ffffffffffffffff811115612196576121966120a0565b60206121c8817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8501160161211c565b82815285828487010111156121dc57600080fd5b60005b838110156121fa5785810183015182820184015282016121df565b506000928101909101919091529392505050565b80516003811061221d57600080fd5b919050565b805161221d81611de1565b805161ffff8116811461221d57600080fd5b60006080828403121561225157600080fd5b6040516080810181811067ffffffffffffffff82111715612274576122746120a0565b8060405250809150825181526020830151602082015260408301516040820152606083015160608201525092915050565b600082601f8301126122b657600080fd5b8151602067ffffffffffffffff8211156122d2576122d26120a0565b8160051b6122e182820161211c565b92835284810182019282810190878511156122fb57600080fd5b83870192505b84831015612321576123128361222d565b82529183019190830190612301565b979650505050505050565b60006020828403121561233e57600080fd5b815167ffffffffffffffff8082111561235657600080fd5b90830190610140828603121561236b57600080fd5b6123736120cf565b82518281111561238257600080fd5b61238e8782860161216b565b8252506020830151828111156123a357600080fd5b6123af8782860161216b565b6020830152506123c16040840161220e565b60408201526123d260608401612222565b60608201526123e36080840161222d565b60808201526123f58660a0850161223f565b60a08201526101208301518281111561240d57600080fd5b612419878286016122a5565b60c08301525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081518084526020808501945080840160005b838110156124875781518752958201959082019060010161246b565b509495945050505050565b60006101008083526124a681840187612457565b91505060208083018560005b60068110156124cf578151835291830191908301906001016124b2565b5050505073ffffffffffffffffffffffffffffffffffffffff831660e0830152949350505050565b6040815282604082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84111561253057600080fd5b8360051b8086606085013780830190506060810160206060858403018186015281865480845260808501915087600052826000209450600093505b8084101561258b578454825260019485019493909301929082019061256b565b5098975050505050505050565b604081016125a68285611f46565b611f106020830184611f46565b6000602082840312156125c557600080fd5b8151611f1081611e33565b600082601f8301126125e157600080fd5b6040516060810181811067ffffffffffffffff82111715612604576126046120a0565b60405280606084018581111561261957600080fd5b845b8181101561263357805183526020928301920161261b565b509195945050505050565b60006020828403121561265057600080fd5b815167ffffffffffffffff8082111561266857600080fd5b908301906101c0828603121561267d57600080fd5b6126856120f8565b8251815260208301516020820152604083015160408201526126a96060840161220e565b60608201526126ba60808401612222565b60808201526126cb60a0840161222d565b60a08201526126dd8660c0850161223f565b60c0820152610140830151828111156126f557600080fd5b612701878286016122a5565b60e0830152506127158661016085016125d0565b61010082015295945050505050565b602081526000611f106020830184612457565b60008261276d577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561077e5761077e612772565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036127e5576127e5612772565b5060010190565b8181038181111561077e5761077e61277256fea2646970667358221220c30ffd88d33a7d906724603089fda7e42e4a35e5c3f49001288e38605de6257c64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de50000000000000000000000001facd50481d827d7d342d79278b9c5a1f9eb6cd70000000000000000000000004131ae1e157c91fe083bdcf857a230fb79ac903a00000000000000000000000010fe37bac405b209f83ff523fb8d00c0c3f508a8000000000000000000000000c8607c5befa7a7567ca78040ba5c36d181243ac1000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
-----Decoded View---------------
Arg [0] : _gameMaster (address): 0x51a16E6AEc2924e8886fc323618876e3ED0e4dE5
Arg [1] : _signer (address): 0x1facD50481D827D7d342D79278B9C5A1F9eB6CD7
Arg [2] : _seeder (address): 0x4131aE1e157c91fe083BdCf857A230fb79Ac903a
Arg [3] : _gameCards (address): 0x10FE37BAC405B209f83FF523Fb8D00C0c3F508a8
Arg [4] : _baseCards (address): 0xc8607C5BefA7A7567ca78040bA5C36d181243ac1
Arg [5] : _blastGovernor (address): 0xAbb8621b2F4FB61f083b9f2a033A40086DB9030d
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 00000000000000000000000051a16e6aec2924e8886fc323618876e3ed0e4de5
Arg [1] : 0000000000000000000000001facd50481d827d7d342d79278b9c5a1f9eb6cd7
Arg [2] : 0000000000000000000000004131ae1e157c91fe083bdcf857a230fb79ac903a
Arg [3] : 00000000000000000000000010fe37bac405b209f83ff523fb8d00c0c3f508a8
Arg [4] : 000000000000000000000000c8607c5befa7a7567ca78040ba5c36d181243ac1
Arg [5] : 000000000000000000000000abb8621b2f4fb61f083b9f2a033a40086db9030d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.