ETH Price: $3,306.10 (-0.03%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Assign Members217027222025-01-25 16:29:5921 hrs ago1737822599IN
0x09529ea3...ff435bA98
0 ETH0.0008929810.89984617
Assign Members217024062025-01-25 15:26:3522 hrs ago1737818795IN
0x09529ea3...ff435bA98
0 ETH0.001151728.98980269
Assign Members216957382025-01-24 17:04:3544 hrs ago1737738275IN
0x09529ea3...ff435bA98
0 ETH0.0014128617.2456024
Assign Members216941572025-01-24 11:47:112 days ago1737719231IN
0x09529ea3...ff435bA98
0 ETH0.0023319518.20201097
Assign Members216890802025-01-23 18:47:232 days ago1737658043IN
0x09529ea3...ff435bA98
0 ETH0.000817839.98256463
Assign Members216875412025-01-23 13:38:593 days ago1737639539IN
0x09529ea3...ff435bA98
0 ETH0.0016924220.66098369
Assign Members216874662025-01-23 13:23:473 days ago1737638627IN
0x09529ea3...ff435bA98
0 ETH0.0014747518.00110097
Assign Members216870502025-01-23 12:00:113 days ago1737633611IN
0x09529ea3...ff435bA98
0 ETH0.000867196.76888611
Assign Members216867452025-01-23 10:58:473 days ago1737629927IN
0x09529ea3...ff435bA98
0 ETH0.000601077.33684601
Assign Members216867392025-01-23 10:57:353 days ago1737629855IN
0x09529ea3...ff435bA98
0 ETH0.000658818.04156905
Assign Members216862872025-01-23 9:26:473 days ago1737624407IN
0x09529ea3...ff435bA98
0 ETH0.000888346.93399426
Assign Members216827302025-01-22 21:31:353 days ago1737581495IN
0x09529ea3...ff435bA98
0 ETH0.00079249.6722368
Assign Members216807442025-01-22 14:51:473 days ago1737557507IN
0x09529ea3...ff435bA98
0 ETH0.0013884816.94802455
Assign Members216806272025-01-22 14:28:113 days ago1737556091IN
0x09529ea3...ff435bA98
0 ETH0.0013755216.78981963
Assign Members216805762025-01-22 14:17:593 days ago1737555479IN
0x09529ea3...ff435bA98
0 ETH0.0015010418.32467063
Assign Members216802312025-01-22 13:08:474 days ago1737551327IN
0x09529ea3...ff435bA98
0 ETH0.0013584710.60355861
Assign Members216802182025-01-22 13:06:114 days ago1737551171IN
0x09529ea3...ff435bA98
0 ETH0.0013088510.21626133
Assign Members216754362025-01-21 21:05:114 days ago1737493511IN
0x09529ea3...ff435bA98
0 ETH0.0012599815.37951366
Assign Members216740152025-01-21 16:19:354 days ago1737476375IN
0x09529ea3...ff435bA98
0 ETH0.0015630519.07881667
Assign Members216739942025-01-21 16:15:234 days ago1737476123IN
0x09529ea3...ff435bA98
0 ETH0.0016633520.30319514
Assign Members216722592025-01-21 10:26:475 days ago1737455207IN
0x09529ea3...ff435bA98
0 ETH0.0020508316.00777566
Assign Members216652222025-01-20 10:51:236 days ago1737370283IN
0x09529ea3...ff435bA98
0 ETH0.0019844824.22646189
Assign Members216610682025-01-19 20:57:476 days ago1737320267IN
0x09529ea3...ff435bA98
0 ETH0.004335452.91859695
Assign Members216599152025-01-19 17:05:476 days ago1737306347IN
0x09529ea3...ff435bA98
0 ETH0.0028374334.63412246
Assign Members216581432025-01-19 11:09:477 days ago1737284987IN
0x09529ea3...ff435bA98
0 ETH0.0027025832.98816697
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
SykyGroups

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 300 runs

Other Settings:
paris EvmVersion
File 1 of 6 : SykyGroups.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/// @author Syky - Nathan Rempel

/*
           @@@   @@@@@   @@@@@@@         @@@@    @@@@@@@      @@@@@     @@@@@@@        @@@@
         @@@@      @@@     @@@@@@        @@       @@@@@@       @@        @@@@@@        @@
         @@@@@      @@      @@@@@       @@        @@@@@       @            @@@@@      @@
         @@@@@@      @@      @@@@@     @@         @@@@@     @               @@@@     @@
          @@@@@@      @       @@@@@   @@          @@@@@    @                @@@@@    @
           @@@@@@@             @@@@@ @@           @@@@@  @@@                 @@@@@  @
             @@@@@@             @@@@@@            @@@@@@@@@@@                 @@@@@@
               @@@@@@           @@@@@             @@@@@  @@@@@                 @@@@@
                @@@@@@@         @@@@@             @@@@@   @@@@@                @@@@@
         @        @@@@@@        @@@@@             @@@@@    @@@@@               @@@@@
         @@        @@@@@        @@@@@             @@@@@     @@@@@              @@@@@
         @@@@      @@@@@        @@@@@             @@@@@@     @@@@@@           @@@@@@
         @@@@@@   @@@@         @@@@@@@           @@@@@@@     @@@@@@@          @@@@@@@
*/

import "../base/GroupRegistry.sol";

contract SykyGroups is GroupRegistry {
    /*//////////////////////////////////////////////////////////////
                            Version Info
    //////////////////////////////////////////////////////////////*/

    string public constant ENV = "GOERLI";
    string public constant VER = "1.0.0";

    /*//////////////////////////////////////////////////////////////
                            Constructor
    //////////////////////////////////////////////////////////////*/

    constructor(address defaultAdmin_) GroupRegistry(defaultAdmin_) {}
}

File 2 of 6 : IPermissions.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IPermissions {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

File 3 of 6 : Permissions.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "./interface/IPermissions.sol";
import "../lib/TWStrings.sol";

/**
 *  @title   Permissions
 *  @dev     This contracts provides extending-contracts with role-based access control mechanisms
 */
contract Permissions is IPermissions {
    /// @dev Map from keccak256 hash of a role => a map from address => whether address has role.
    mapping(bytes32 => mapping(address => bool)) private _hasRole;

    /// @dev Map from keccak256 hash of a role to role admin. See {getRoleAdmin}.
    mapping(bytes32 => bytes32) private _getRoleAdmin;

    /// @dev Default admin role for all roles. Only accounts with this role can grant/revoke other roles.
    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /// @dev Modifier that checks if an account has the specified role; reverts otherwise.
    modifier onlyRole(bytes32 role) {
        _checkRole(role, msg.sender);
        _;
    }

    /**
     *  @notice         Checks whether an account has a particular role.
     *  @dev            Returns `true` if `account` has been granted `role`.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account for which the role is being checked.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _hasRole[role][account];
    }

    /**
     *  @notice         Checks whether an account has a particular role;
     *                  role restrictions can be swtiched on and off.
     *
     *  @dev            Returns `true` if `account` has been granted `role`.
     *                  Role restrictions can be swtiched on and off:
     *                      - If address(0) has ROLE, then the ROLE restrictions
     *                        don't apply.
     *                      - If address(0) does not have ROLE, then the ROLE
     *                        restrictions will apply.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account for which the role is being checked.
     */
    function hasRoleWithSwitch(bytes32 role, address account) public view returns (bool) {
        if (!_hasRole[role][address(0)]) {
            return _hasRole[role][account];
        }

        return true;
    }

    /**
     *  @notice         Returns the admin role that controls the specified role.
     *  @dev            See {grantRole} and {revokeRole}.
     *                  To change a role's admin, use {_setRoleAdmin}.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     */
    function getRoleAdmin(bytes32 role) external view override returns (bytes32) {
        return _getRoleAdmin[role];
    }

    /**
     *  @notice         Grants a role to an account, if not previously granted.
     *  @dev            Caller must have admin role for the `role`.
     *                  Emits {RoleGranted Event}.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account to which the role is being granted.
     */
    function grantRole(bytes32 role, address account) public virtual override {
        _checkRole(_getRoleAdmin[role], msg.sender);
        if (_hasRole[role][account]) {
            revert("Can only grant to non holders");
        }
        _setupRole(role, account);
    }

    /**
     *  @notice         Revokes role from an account.
     *  @dev            Caller must have admin role for the `role`.
     *                  Emits {RoleRevoked Event}.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account from which the role is being revoked.
     */
    function revokeRole(bytes32 role, address account) public virtual override {
        _checkRole(_getRoleAdmin[role], msg.sender);
        _revokeRole(role, account);
    }

    /**
     *  @notice         Revokes role from the account.
     *  @dev            Caller must have the `role`, with caller being the same as `account`.
     *                  Emits {RoleRevoked Event}.
     *
     *  @param role     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     *  @param account  Address of the account from which the role is being revoked.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        if (msg.sender != account) {
            revert("Can only renounce for self");
        }
        _revokeRole(role, account);
    }

    /// @dev Sets `adminRole` as `role`'s admin role.
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = _getRoleAdmin[role];
        _getRoleAdmin[role] = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /// @dev Sets up `role` for `account`
    function _setupRole(bytes32 role, address account) internal virtual {
        _hasRole[role][account] = true;
        emit RoleGranted(role, account, msg.sender);
    }

    /// @dev Revokes `role` from `account`
    function _revokeRole(bytes32 role, address account) internal virtual {
        _checkRole(role, account);
        delete _hasRole[role][account];
        emit RoleRevoked(role, account, msg.sender);
    }

    /// @dev Checks `role` for `account`. Reverts with a message including the required role.
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!_hasRole[role][account]) {
            revert(
                string(
                    abi.encodePacked(
                        "Permissions: account ",
                        TWStrings.toHexString(uint160(account), 20),
                        " is missing role ",
                        TWStrings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /// @dev Checks `role` for `account`. Reverts with a message including the required role.
    function _checkRoleWithSwitch(bytes32 role, address account) internal view virtual {
        if (!hasRoleWithSwitch(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "Permissions: account ",
                        TWStrings.toHexString(uint160(account), 20),
                        " is missing role ",
                        TWStrings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }
}

File 4 of 6 : TWStrings.sol
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 * @dev String operations.
 */
library TWStrings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 5 of 6 : GroupRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/// @author Syky - Nathan Rempel

import "./interface/IGroupRegistry.sol";

import "@thirdweb-dev/contracts/extension/Permissions.sol";

contract GroupRegistry is IGroupRegistry, Permissions {
    /*//////////////////////////////////////////////////////////////
                            Constants
    //////////////////////////////////////////////////////////////*/

    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");

    /*//////////////////////////////////////////////////////////////
                            Mappings
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => ItemSet) private _groups;
    mapping(uint256 => ItemSet) private _subgroups;

    /*//////////////////////////////////////////////////////////////
                            Constructor
    //////////////////////////////////////////////////////////////*/

    constructor(address defaultAdmin_) {
        _setupRole(DEFAULT_ADMIN_ROLE, defaultAdmin_);
        _setRoleAdmin(MANAGER_ROLE, DEFAULT_ADMIN_ROLE);
    }

    /*//////////////////////////////////////////////////////////////
                        Admin functions
    //////////////////////////////////////////////////////////////*/

    function assignMembers(
        uint256 _subgroupId,
        address[] calldata _members
    ) external onlyValidId(_subgroupId) onlyManager {
        ItemSet storage _itemSet = _subgroups[_subgroupId];
        uint256 memberLength = _members.length;
        uint256[] memory members = new uint256[](memberLength);
        for (uint256 i; i < memberLength; ) {
            members[i] = uint160(_members[i]);
            unchecked {
                ++i;
            }
        }
        _insertItems(_itemSet, members);
        emit MembersAssigned(_subgroupId, _members);
    }

    function removeMembers(
        uint256 _subgroupId,
        address[] calldata _members
    ) external onlyValidId(_subgroupId) onlyManager {
        ItemSet storage _itemSet = _subgroups[_subgroupId];
        uint256 memberLength = _members.length;
        uint256[] memory members = new uint256[](memberLength);
        for (uint256 i; i < memberLength; ) {
            members[i] = uint160(_members[i]);
            unchecked {
                ++i;
            }
        }
        _removeItems(_itemSet, members);
        emit MembersAssigned(_subgroupId, _members);
    }

    function assignSubgroups(
        uint256 _groupId,
        uint256[] calldata _subgroupIds
    ) external onlyValidId(_groupId) onlyManager {
        ItemSet storage _itemSet = _groups[_groupId];
        _insertItems(_itemSet, _subgroupIds);
        emit SubgroupsAssigned(_groupId, _subgroupIds);
    }

    function removeSubgroups(
        uint256 _groupId,
        uint256[] calldata _subgroupIds
    ) external onlyValidId(_groupId) onlyManager {
        ItemSet storage _itemSet = _groups[_groupId];
        _removeItems(_itemSet, _subgroupIds);
        emit SubgroupsRemoved(_groupId, _subgroupIds);
    }

    /*//////////////////////////////////////////////////////////////
                        Public getters
    //////////////////////////////////////////////////////////////*/

    function isGroupMember(
        uint256 _groupId,
        address _member
    ) external view returns (bool) {
        return _isGroupMember(_groupId, _member);
    }

    function isSubgroupMember(
        uint256 _subgroupId,
        address _member
    ) external view returns (bool) {
        return _isSubgroupMember(_subgroupId, _member);
    }

    function groupMembers(
        uint256 _groupId
    ) external view returns (GroupMembersQuery memory) {
        return
            GroupMembersQuery({groupId: _groupId, subgroups: _getGroupMembers(_groupId)});
    }

    function groupSubgroups(uint256 _groupId) external view returns (uint256[] memory) {
        return _getSubgroups(_groupId);
    }

    function subgroupMembers(
        uint256 _subgroupId
    ) external view returns (SubgroupMembersQuery memory) {
        return
            SubgroupMembersQuery({
                subgroupId: _subgroupId,
                members: _getSubgroupMembers(_subgroupId)
            });
    }

    /*//////////////////////////////////////////////////////////////
                            Modifiers
    //////////////////////////////////////////////////////////////*/

    /// @dev Modifier that checks if an account has admin or manager role; reverts otherwise.
    modifier onlyManager() {
        _checkManagerAdmin();
        _;
    }

    modifier onlyValidId(uint256 _id) {
        if (_id == 0) revert NonZeroIdRequired();
        _;
    }

    /*//////////////////////////////////////////////////////////////
                        Internal functions
    //////////////////////////////////////////////////////////////*/

    /// @dev Function that checks if an account has admin or manager role; reverts otherwise.
    function _checkManagerAdmin() internal view {
        if (
            !hasRole(DEFAULT_ADMIN_ROLE, msg.sender) && !hasRole(MANAGER_ROLE, msg.sender)
        ) {
            revert ManagerRoleRequired();
        }
    }

    function _insertItems(
        ItemSet storage _itemSet,
        uint256[] memory _items
    ) internal virtual {
        uint256 assignCount = _items.length;
        if (assignCount == 0) revert NonEmptyArrayRequired();

        uint256 currentIdx = _itemSet.index;
        for (uint256 i; i < assignCount; ) {
            //don't add zero group
            if (_items[i] == 0) continue;

            //don't add existing subgroup
            uint256 existingIdx = _itemSet.indexOf[_items[i]];
            if (_itemSet.items[existingIdx] == _items[i]) continue;

            //add subgroup to current index
            _itemSet.items[currentIdx] = _items[i];

            unchecked {
                //add the index reference, increment the current index
                _itemSet.indexOf[_items[i]] = currentIdx++;
                ++i;
            }
        }
        //revert if no changes to save gas
        if (_itemSet.index == currentIdx) revert AlreadyAssigned();

        //save the new index
        _itemSet.index = currentIdx;
    }

    function _removeItems(
        ItemSet storage _itemSet,
        uint256[] memory _items
    ) internal virtual {
        uint256 removeCount = _items.length;
        if (removeCount == 0) revert NonEmptyArrayRequired();

        bool unchanged = true;

        for (uint256 i; i < removeCount; ) {
            //don't add zero addresses
            if (_items[i] == 0) continue;

            //confirm the member exists
            uint256 existingIdx = _itemSet.indexOf[_items[i]];
            if (_itemSet.items[existingIdx] == _items[i]) {
                delete _itemSet.items[existingIdx];
                delete _itemSet.indexOf[_items[i]];
                unchanged = false;
            }

            unchecked {
                ++i;
            }
        }

        //revert if no changes to save gas
        if (unchanged) revert AlreadyRemoved();
    }

    function _selectItems(
        ItemSet storage _itemSet
    ) internal view returns (uint256[] memory) {
        uint256 itemLength = _itemSet.index;

        uint256[] memory allItems = new uint256[](itemLength);
        uint256 actualLength = 0;

        unchecked {
            for (uint256 i; i < itemLength; ) {
                allItems[i] = _itemSet.items[i];
                if (allItems[i] != 0) {
                    ++actualLength;
                }
                ++i;
            }
        }

        uint256[] memory actualItems = new uint256[](actualLength);

        uint256 idx;

        unchecked {
            for (uint256 i; i < itemLength; ) {
                if (allItems[i] != 0) {
                    actualItems[idx] = allItems[i];
                    ++idx;
                }
                ++i;
            }
        }

        return actualItems;
    }

    function _isGroupMember(
        uint256 _groupId,
        address _member
    ) internal view returns (bool) {
        uint256 subgroupCount = _groups[_groupId].index;
        for (uint256 i; i < subgroupCount; ) {
            uint256 subgroupId = _groups[_groupId].items[i];
            if (subgroupId == 0) continue;
            if (_isSubgroupMember(subgroupId, _member)) return true;
            unchecked {
                ++i;
            }
        }
        return false;
    }

    function _isSubgroupMember(
        uint256 _subgroupId,
        address _member
    ) internal view returns (bool) {
        uint256 memberIdx = _subgroups[_subgroupId].indexOf[uint160(_member)];
        return _subgroups[_subgroupId].items[memberIdx] == uint160(_member);
    }

    function _getSubgroups(uint256 _groupId) internal view returns (uint256[] memory) {
        ItemSet storage group = _groups[_groupId];
        return _selectItems(group);
    }

    function _getSubgroupMembers(
        uint256 _subgroupId
    ) internal view returns (address[] memory) {
        ItemSet storage subgroup = _subgroups[_subgroupId];
        uint256[] memory items = _selectItems(subgroup);
        uint256 itemsLength = items.length;

        address[] memory members = new address[](itemsLength);
        for (uint256 i; i < itemsLength; ) {
            members[i] = address(uint160(items[i]));
            unchecked {
                ++i;
            }
        }
        return members;
    }

    function _getGroupMembers(
        uint256 _groupId
    ) internal view returns (SubgroupMembersQuery[] memory) {
        uint256[] memory subgroupIds = _getSubgroups(_groupId);

        uint256 subgroupsLength = subgroupIds.length;
        SubgroupMembersQuery[] memory subgroups = new SubgroupMembersQuery[](
            subgroupsLength
        );

        for (uint256 i; i < subgroupsLength; ) {
            subgroups[i] = SubgroupMembersQuery({
                subgroupId: subgroupIds[i],
                members: _getSubgroupMembers(subgroupIds[i])
            });
            unchecked {
                ++i;
            }
        }

        return subgroups;
    }
}

File 6 of 6 : IGroupRegistry.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/// @author Syky - Nathan Rempel

interface IGroupRegistry {
    struct ItemSet {
        uint256 index;
        mapping(uint256 => uint256) items;
        mapping(uint256 => uint256) indexOf;
    }

    struct GroupMembersQuery {
        uint256 groupId;
        SubgroupMembersQuery[] subgroups;
    }

    struct SubgroupMembersQuery {
        uint256 subgroupId;
        address[] members;
    }

    function isGroupMember(
        uint256 _groupId,
        address _member
    ) external view returns (bool);

    function isSubgroupMember(
        uint256 _subgroupId,
        address _member
    ) external view returns (bool);

    function groupMembers(
        uint256 _groupId
    ) external view returns (GroupMembersQuery memory);

    function groupSubgroups(uint256 _groupId) external view returns (uint256[] memory);

    function subgroupMembers(
        uint256 _subgroupId
    ) external view returns (SubgroupMembersQuery memory);

    function assignMembers(uint256 _subgroupId, address[] calldata _members) external;

    function removeMembers(uint256 _subgroupId, address[] calldata _members) external;

    function assignSubgroups(uint256 _groupId, uint256[] calldata _subgroupIds) external;

    function removeSubgroups(uint256 _groupId, uint256[] calldata _subgroupIds) external;

    event MembersAssigned(uint256 indexed subgroupId, address[] members);
    event MembersRemoved(uint256 indexed subgroupId, address[] members);
    event SubgroupsAssigned(uint256 indexed groupId, uint256[] subgroupIds);
    event SubgroupsRemoved(uint256 indexed groupId, uint256[] subgroupIds);

    error ManagerRoleRequired();
    error NonZeroIdRequired();
    error NonEmptyArrayRequired();
    error AlreadyAssigned();
    error AlreadyRemoved();
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 300
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"defaultAdmin_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyAssigned","type":"error"},{"inputs":[],"name":"AlreadyRemoved","type":"error"},{"inputs":[],"name":"ManagerRoleRequired","type":"error"},{"inputs":[],"name":"NonEmptyArrayRequired","type":"error"},{"inputs":[],"name":"NonZeroIdRequired","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"subgroupId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"members","type":"address[]"}],"name":"MembersAssigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"subgroupId","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"members","type":"address[]"}],"name":"MembersRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"subgroupIds","type":"uint256[]"}],"name":"SubgroupsAssigned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"groupId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"subgroupIds","type":"uint256[]"}],"name":"SubgroupsRemoved","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ENV","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VER","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_subgroupId","type":"uint256"},{"internalType":"address[]","name":"_members","type":"address[]"}],"name":"assignMembers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_groupId","type":"uint256"},{"internalType":"uint256[]","name":"_subgroupIds","type":"uint256[]"}],"name":"assignSubgroups","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_groupId","type":"uint256"}],"name":"groupMembers","outputs":[{"components":[{"internalType":"uint256","name":"groupId","type":"uint256"},{"components":[{"internalType":"uint256","name":"subgroupId","type":"uint256"},{"internalType":"address[]","name":"members","type":"address[]"}],"internalType":"struct IGroupRegistry.SubgroupMembersQuery[]","name":"subgroups","type":"tuple[]"}],"internalType":"struct IGroupRegistry.GroupMembersQuery","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_groupId","type":"uint256"}],"name":"groupSubgroups","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRoleWithSwitch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_groupId","type":"uint256"},{"internalType":"address","name":"_member","type":"address"}],"name":"isGroupMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_subgroupId","type":"uint256"},{"internalType":"address","name":"_member","type":"address"}],"name":"isSubgroupMember","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_subgroupId","type":"uint256"},{"internalType":"address[]","name":"_members","type":"address[]"}],"name":"removeMembers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_groupId","type":"uint256"},{"internalType":"uint256[]","name":"_subgroupIds","type":"uint256[]"}],"name":"removeSubgroups","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_subgroupId","type":"uint256"}],"name":"subgroupMembers","outputs":[{"components":[{"internalType":"uint256","name":"subgroupId","type":"uint256"},{"internalType":"address[]","name":"members","type":"address[]"}],"internalType":"struct IGroupRegistry.SubgroupMembersQuery","name":"","type":"tuple"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50604051620018773803806200187783398101604081905261003191610110565b8061003d60008261006f565b6100687f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0860006100c8565b5050610140565b6000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b600082815260016020526040808220805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b60006020828403121561012257600080fd5b81516001600160a01b038116811461013957600080fd5b9392505050565b61172780620001506000396000f3fe608060405234801561001057600080fd5b50600436106101215760003560e01c8063627cf4b0116100ad578063bbba649611610071578063bbba6496146102c5578063bfeb5607146102d8578063d547741f146102eb578063ec87621c146102fe578063fd907a731461032557600080fd5b8063627cf4b01461023b5780637c6285a11461024e57806391d1485414610273578063a217fddf146102aa578063a32fa5b3146102b257600080fd5b80632f2ff15d116100f45780632f2ff15d146101b157806336568abe146101c45780633c4de40f146101d75780634daf13fc1461020857806358c97f3d1461021b57600080fd5b80631afe20f514610126578063200091651461013b5780632469413814610163578063248a9ca314610183575b600080fd5b610139610134366004611340565b610345565b005b61014e6101493660046113a8565b610404565b60405190151581526020015b60405180910390f35b6101766101713660046113d4565b610444565b60405161015a919061144d565b6101a36101913660046113d4565b60009081526001602052604090205490565b60405190815260200161015a565b6101396101bf3660046113a8565b61047b565b6101396101d23660046113a8565b610518565b6101fb604051806040016040528060058152602001640312e302e360dc1b81525081565b60405161015a91906114e6565b610139610216366004611340565b61057a565b61022e6102293660046113d4565b61062a565b60405161015a9190611519565b610139610249366004611340565b610635565b6101fb60405180604001604052806006815260200165474f45524c4960d01b81525081565b61014e6102813660046113a8565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6101a3600081565b61014e6102c03660046113a8565b610763565b6101396102d3366004611340565b6107b5565b61014e6102e63660046113a8565b6108a0565b6101396102f93660046113a8565b6108ac565b6101a37f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b6103386103333660046113d4565b6108c5565b60405161015a9190611551565b82806000036103675760405163cfd138ad60e01b815260040160405180910390fd5b61036f6108f4565b60006002600086815260200190815260200160002090506103c38185858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061098292505050565b847f16315b549fe1fb96d012112f40ea2fef86ed35bb00f94a66c829639b1b095cd885856040516103f5929190611564565b60405180910390a25050505050565b60008281526003602090815260408083206001600160a01b0385168085526002820184528285205485526001909101909252822054145b90505b92915050565b604080518082019091526000815260606020820152604051806040016040528083815260200161047384610ab8565b905292915050565b6000828152600160205260409020546104949033610bb6565b6000828152602081815260408083206001600160a01b038516845290915290205460ff161561050a5760405162461bcd60e51b815260206004820152601d60248201527f43616e206f6e6c79206772616e7420746f206e6f6e20686f6c6465727300000060448201526064015b60405180910390fd5b6105148282610c34565b5050565b336001600160a01b038216146105705760405162461bcd60e51b815260206004820152601a60248201527f43616e206f6e6c792072656e6f756e636520666f722073656c660000000000006044820152606401610501565b6105148282610c8d565b828060000361059c5760405163cfd138ad60e01b815260040160405180910390fd5b6105a46108f4565b60006002600086815260200190815260200160002090506105f881858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610ced92505050565b847f1d597d0d7ee74920d789ab9bd4d7472395aade87f464faa43374ea48a7409b8e85856040516103f5929190611564565b606061043e82610e50565b82806000036106575760405163cfd138ad60e01b815260040160405180910390fd5b61065f6108f4565b60008481526003602052604081209083908167ffffffffffffffff8111156106895761068961159d565b6040519080825280602002602001820160405280156106b2578160200160208202803683370190505b50905060005b82811015610715578686828181106106d2576106d26115b3565b90506020020160208101906106e791906115c9565b6001600160a01b0316828281518110610702576107026115b3565b60209081029190910101526001016106b8565b506107208382610982565b867f7f58d4449a0f6788522f6a362f8562cbdeb20a9ee3df4958eff97f1e6c5a670f87876040516107529291906115e4565b60405180910390a250505050505050565b60008281526020818152604080832083805290915281205460ff166107ac57506000828152602081815260408083206001600160a01b038516845290915290205460ff1661043e565b50600192915050565b82806000036107d75760405163cfd138ad60e01b815260040160405180910390fd5b6107df6108f4565b60008481526003602052604081209083908167ffffffffffffffff8111156108095761080961159d565b604051908082528060200260200182016040528015610832578160200160208202803683370190505b50905060005b8281101561089557868682818110610852576108526115b3565b905060200201602081019061086791906115c9565b6001600160a01b0316828281518110610882576108826115b3565b6020908102919091010152600101610838565b506107208382610ced565b600061043b8383610e71565b6000828152600160205260409020546105709033610bb6565b604080518082019091526000815260606020820152604051806040016040528083815260200161047384610f10565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1615801561096257503360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b15610980576040516349349c6360e11b815260040160405180910390fd5b565b805160008190036109a657604051637422fb4760e01b815260040160405180910390fd5b600160005b82811015610a92578381815181106109c5576109c56115b3565b6020026020010151600003156109ab5760008560020160008684815181106109ef576109ef6115b3565b60200260200101518152602001908152602001600020549050848281518110610a1a57610a1a6115b3565b60200260200101518660010160008381526020019081526020016000205403610a8957600081815260018701602052604081208190558551600288019190879085908110610a6a57610a6a6115b3565b6020026020010151815260200190815260200160002060009055600092505b506001016109ab565b508015610ab2576040516355adf54760e11b815260040160405180910390fd5b50505050565b60606000610ac583610e50565b805190915060008167ffffffffffffffff811115610ae557610ae561159d565b604051908082528060200260200182016040528015610b2b57816020015b604080518082019091526000815260606020820152815260200190600190039081610b035790505b50905060005b82811015610bad576040518060400160405280858381518110610b5657610b566115b3565b60200260200101518152602001610b85868481518110610b7857610b786115b3565b6020026020010151610f10565b815250828281518110610b9a57610b9a6115b3565b6020908102919091010152600101610b31565b50949350505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1661051457610bf2816001600160a01b03166014610fd7565b610bfd836020610fd7565b604051602001610c0e929190611625565b60408051601f198184030181529082905262461bcd60e51b8252610501916004016114e6565b6000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b610c978282610bb6565b6000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b80516000819003610d1157604051637422fb4760e01b815260040160405180910390fd5b825460005b82811015610e2657838181518110610d3057610d306115b3565b602002602001015160000315610d16576000856002016000868481518110610d5a57610d5a6115b3565b60200260200101518152602001908152602001600020549050848281518110610d8557610d856115b3565b60200260200101518660010160008381526020019081526020016000205403610dae5750610d16565b848281518110610dc057610dc06115b3565b60200260200101518660010160008581526020019081526020016000208190555082806001019350866002016000878581518110610e0057610e006115b3565b602002602001015181526020019081526020016000208190555081600101915050610d16565b508354819003610e4957604051639688dc5160e01b815260040160405180910390fd5b9092555050565b6000818152600260205260409020606090610e6a81611173565b9392505050565b600082815260026020526040812054815b81811015610f0557600085815260026020908152604080832084845260010190915281205490819003610eb55750610e82565b60008181526003602090815260408083206001600160a01b03891680855260028201845282852054855260019091019092529091205403610efc576001935050505061043e565b50600101610e82565b506000949350505050565b6000818152600360205260408120606091610f2a82611173565b805190915060008167ffffffffffffffff811115610f4a57610f4a61159d565b604051908082528060200260200182016040528015610f73578160200160208202803683370190505b50905060005b82811015610fcd57838181518110610f9357610f936115b3565b6020026020010151828281518110610fad57610fad6115b3565b6001600160a01b0390921660209283029190910190910152600101610f79565b5095945050505050565b60606000610fe68360026116b0565b610ff19060026116c7565b67ffffffffffffffff8111156110095761100961159d565b6040519080825280601f01601f191660200182016040528015611033576020820181803683370190505b509050600360fc1b8160008151811061104e5761104e6115b3565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061107d5761107d6115b3565b60200101906001600160f81b031916908160001a90535060006110a18460026116b0565b6110ac9060016116c7565b90505b6001811115611124576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106110e0576110e06115b3565b1a60f81b8282815181106110f6576110f66115b3565b60200101906001600160f81b031916908160001a90535060049490941c9361111d816116da565b90506110af565b50831561043b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610501565b805460609060008167ffffffffffffffff8111156111935761119361159d565b6040519080825280602002602001820160405280156111bc578160200160208202803683370190505b5090506000805b8381101561122c57600081815260018701602052604090205483518490839081106111f0576111f06115b3565b60200260200101818152505082818151811061120e5761120e6115b3565b6020026020010151600014611224578160010191505b6001016111c3565b5060008167ffffffffffffffff8111156112485761124861159d565b604051908082528060200260200182016040528015611271578160200160208202803683370190505b5090506000805b858110156112e857848181518110611292576112926115b3565b60200260200101516000146112e0578481815181106112b3576112b36115b3565b60200260200101518383815181106112cd576112cd6115b3565b6020026020010181815250508160010191505b600101611278565b50909695505050505050565b60008083601f84011261130657600080fd5b50813567ffffffffffffffff81111561131e57600080fd5b6020830191508360208260051b850101111561133957600080fd5b9250929050565b60008060006040848603121561135557600080fd5b83359250602084013567ffffffffffffffff81111561137357600080fd5b61137f868287016112f4565b9497909650939450505050565b80356001600160a01b03811681146113a357600080fd5b919050565b600080604083850312156113bb57600080fd5b823591506113cb6020840161138c565b90509250929050565b6000602082840312156113e657600080fd5b5035919050565b600060408301825184526020808401516040828701528281518085526060880191508383019450600092505b808310156114425784516001600160a01b03168252938301936001929092019190830190611419565b509695505050505050565b60006020808352606083018451828501528185015160408086015281815180845260808701915060808160051b8801019350848301925060005b818110156114b557607f198886030183526114a38585516113ed565b94509285019291850191600101611487565b5092979650505050505050565b60005b838110156114dd5781810151838201526020016114c5565b50506000910152565b60208152600082518060208401526115058160408501602087016114c2565b601f01601f19169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b818110156112e857835183529284019291840191600101611535565b60208152600061043b60208301846113ed565b6020808252810182905260006001600160fb1b0383111561158457600080fd5b8260051b80856040850137919091016040019392505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000602082840312156115db57600080fd5b61043b8261138c565b60208082528181018390526000908460408401835b86811015611442576001600160a01b036116128461138c565b16825291830191908301906001016115f9565b7f5065726d697373696f6e733a206163636f756e7420000000000000000000000081526000835161165d8160158501602088016114c2565b7001034b99036b4b9b9b4b733903937b6329607d1b601591840191820152835161168e8160268401602088016114c2565b01602601949350505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761043e5761043e61169a565b8082018082111561043e5761043e61169a565b6000816116e9576116e961169a565b50600019019056fea2646970667358221220126d6310a65dba868ae14845cff1984d4d0d94ccca5babf9bf960029946972da64736f6c63430008140033000000000000000000000000f9e30ba8df802eef5a0fb239d59dee05f18b2e49

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101215760003560e01c8063627cf4b0116100ad578063bbba649611610071578063bbba6496146102c5578063bfeb5607146102d8578063d547741f146102eb578063ec87621c146102fe578063fd907a731461032557600080fd5b8063627cf4b01461023b5780637c6285a11461024e57806391d1485414610273578063a217fddf146102aa578063a32fa5b3146102b257600080fd5b80632f2ff15d116100f45780632f2ff15d146101b157806336568abe146101c45780633c4de40f146101d75780634daf13fc1461020857806358c97f3d1461021b57600080fd5b80631afe20f514610126578063200091651461013b5780632469413814610163578063248a9ca314610183575b600080fd5b610139610134366004611340565b610345565b005b61014e6101493660046113a8565b610404565b60405190151581526020015b60405180910390f35b6101766101713660046113d4565b610444565b60405161015a919061144d565b6101a36101913660046113d4565b60009081526001602052604090205490565b60405190815260200161015a565b6101396101bf3660046113a8565b61047b565b6101396101d23660046113a8565b610518565b6101fb604051806040016040528060058152602001640312e302e360dc1b81525081565b60405161015a91906114e6565b610139610216366004611340565b61057a565b61022e6102293660046113d4565b61062a565b60405161015a9190611519565b610139610249366004611340565b610635565b6101fb60405180604001604052806006815260200165474f45524c4960d01b81525081565b61014e6102813660046113a8565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b6101a3600081565b61014e6102c03660046113a8565b610763565b6101396102d3366004611340565b6107b5565b61014e6102e63660046113a8565b6108a0565b6101396102f93660046113a8565b6108ac565b6101a37f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b6103386103333660046113d4565b6108c5565b60405161015a9190611551565b82806000036103675760405163cfd138ad60e01b815260040160405180910390fd5b61036f6108f4565b60006002600086815260200190815260200160002090506103c38185858080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061098292505050565b847f16315b549fe1fb96d012112f40ea2fef86ed35bb00f94a66c829639b1b095cd885856040516103f5929190611564565b60405180910390a25050505050565b60008281526003602090815260408083206001600160a01b0385168085526002820184528285205485526001909101909252822054145b90505b92915050565b604080518082019091526000815260606020820152604051806040016040528083815260200161047384610ab8565b905292915050565b6000828152600160205260409020546104949033610bb6565b6000828152602081815260408083206001600160a01b038516845290915290205460ff161561050a5760405162461bcd60e51b815260206004820152601d60248201527f43616e206f6e6c79206772616e7420746f206e6f6e20686f6c6465727300000060448201526064015b60405180910390fd5b6105148282610c34565b5050565b336001600160a01b038216146105705760405162461bcd60e51b815260206004820152601a60248201527f43616e206f6e6c792072656e6f756e636520666f722073656c660000000000006044820152606401610501565b6105148282610c8d565b828060000361059c5760405163cfd138ad60e01b815260040160405180910390fd5b6105a46108f4565b60006002600086815260200190815260200160002090506105f881858580806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250610ced92505050565b847f1d597d0d7ee74920d789ab9bd4d7472395aade87f464faa43374ea48a7409b8e85856040516103f5929190611564565b606061043e82610e50565b82806000036106575760405163cfd138ad60e01b815260040160405180910390fd5b61065f6108f4565b60008481526003602052604081209083908167ffffffffffffffff8111156106895761068961159d565b6040519080825280602002602001820160405280156106b2578160200160208202803683370190505b50905060005b82811015610715578686828181106106d2576106d26115b3565b90506020020160208101906106e791906115c9565b6001600160a01b0316828281518110610702576107026115b3565b60209081029190910101526001016106b8565b506107208382610982565b867f7f58d4449a0f6788522f6a362f8562cbdeb20a9ee3df4958eff97f1e6c5a670f87876040516107529291906115e4565b60405180910390a250505050505050565b60008281526020818152604080832083805290915281205460ff166107ac57506000828152602081815260408083206001600160a01b038516845290915290205460ff1661043e565b50600192915050565b82806000036107d75760405163cfd138ad60e01b815260040160405180910390fd5b6107df6108f4565b60008481526003602052604081209083908167ffffffffffffffff8111156108095761080961159d565b604051908082528060200260200182016040528015610832578160200160208202803683370190505b50905060005b8281101561089557868682818110610852576108526115b3565b905060200201602081019061086791906115c9565b6001600160a01b0316828281518110610882576108826115b3565b6020908102919091010152600101610838565b506107208382610ced565b600061043b8383610e71565b6000828152600160205260409020546105709033610bb6565b604080518082019091526000815260606020820152604051806040016040528083815260200161047384610f10565b3360009081527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5602052604090205460ff1615801561096257503360009081527fe84508f2c7fa9c351146748b3025cb78b45df37d868e48c6a75102fecdeee645602052604090205460ff16155b15610980576040516349349c6360e11b815260040160405180910390fd5b565b805160008190036109a657604051637422fb4760e01b815260040160405180910390fd5b600160005b82811015610a92578381815181106109c5576109c56115b3565b6020026020010151600003156109ab5760008560020160008684815181106109ef576109ef6115b3565b60200260200101518152602001908152602001600020549050848281518110610a1a57610a1a6115b3565b60200260200101518660010160008381526020019081526020016000205403610a8957600081815260018701602052604081208190558551600288019190879085908110610a6a57610a6a6115b3565b6020026020010151815260200190815260200160002060009055600092505b506001016109ab565b508015610ab2576040516355adf54760e11b815260040160405180910390fd5b50505050565b60606000610ac583610e50565b805190915060008167ffffffffffffffff811115610ae557610ae561159d565b604051908082528060200260200182016040528015610b2b57816020015b604080518082019091526000815260606020820152815260200190600190039081610b035790505b50905060005b82811015610bad576040518060400160405280858381518110610b5657610b566115b3565b60200260200101518152602001610b85868481518110610b7857610b786115b3565b6020026020010151610f10565b815250828281518110610b9a57610b9a6115b3565b6020908102919091010152600101610b31565b50949350505050565b6000828152602081815260408083206001600160a01b038516845290915290205460ff1661051457610bf2816001600160a01b03166014610fd7565b610bfd836020610fd7565b604051602001610c0e929190611625565b60408051601f198184030181529082905262461bcd60e51b8252610501916004016114e6565b6000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b610c978282610bb6565b6000828152602081815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b80516000819003610d1157604051637422fb4760e01b815260040160405180910390fd5b825460005b82811015610e2657838181518110610d3057610d306115b3565b602002602001015160000315610d16576000856002016000868481518110610d5a57610d5a6115b3565b60200260200101518152602001908152602001600020549050848281518110610d8557610d856115b3565b60200260200101518660010160008381526020019081526020016000205403610dae5750610d16565b848281518110610dc057610dc06115b3565b60200260200101518660010160008581526020019081526020016000208190555082806001019350866002016000878581518110610e0057610e006115b3565b602002602001015181526020019081526020016000208190555081600101915050610d16565b508354819003610e4957604051639688dc5160e01b815260040160405180910390fd5b9092555050565b6000818152600260205260409020606090610e6a81611173565b9392505050565b600082815260026020526040812054815b81811015610f0557600085815260026020908152604080832084845260010190915281205490819003610eb55750610e82565b60008181526003602090815260408083206001600160a01b03891680855260028201845282852054855260019091019092529091205403610efc576001935050505061043e565b50600101610e82565b506000949350505050565b6000818152600360205260408120606091610f2a82611173565b805190915060008167ffffffffffffffff811115610f4a57610f4a61159d565b604051908082528060200260200182016040528015610f73578160200160208202803683370190505b50905060005b82811015610fcd57838181518110610f9357610f936115b3565b6020026020010151828281518110610fad57610fad6115b3565b6001600160a01b0390921660209283029190910190910152600101610f79565b5095945050505050565b60606000610fe68360026116b0565b610ff19060026116c7565b67ffffffffffffffff8111156110095761100961159d565b6040519080825280601f01601f191660200182016040528015611033576020820181803683370190505b509050600360fc1b8160008151811061104e5761104e6115b3565b60200101906001600160f81b031916908160001a905350600f60fb1b8160018151811061107d5761107d6115b3565b60200101906001600160f81b031916908160001a90535060006110a18460026116b0565b6110ac9060016116c7565b90505b6001811115611124576f181899199a1a9b1b9c1cb0b131b232b360811b85600f16601081106110e0576110e06115b3565b1a60f81b8282815181106110f6576110f66115b3565b60200101906001600160f81b031916908160001a90535060049490941c9361111d816116da565b90506110af565b50831561043b5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610501565b805460609060008167ffffffffffffffff8111156111935761119361159d565b6040519080825280602002602001820160405280156111bc578160200160208202803683370190505b5090506000805b8381101561122c57600081815260018701602052604090205483518490839081106111f0576111f06115b3565b60200260200101818152505082818151811061120e5761120e6115b3565b6020026020010151600014611224578160010191505b6001016111c3565b5060008167ffffffffffffffff8111156112485761124861159d565b604051908082528060200260200182016040528015611271578160200160208202803683370190505b5090506000805b858110156112e857848181518110611292576112926115b3565b60200260200101516000146112e0578481815181106112b3576112b36115b3565b60200260200101518383815181106112cd576112cd6115b3565b6020026020010181815250508160010191505b600101611278565b50909695505050505050565b60008083601f84011261130657600080fd5b50813567ffffffffffffffff81111561131e57600080fd5b6020830191508360208260051b850101111561133957600080fd5b9250929050565b60008060006040848603121561135557600080fd5b83359250602084013567ffffffffffffffff81111561137357600080fd5b61137f868287016112f4565b9497909650939450505050565b80356001600160a01b03811681146113a357600080fd5b919050565b600080604083850312156113bb57600080fd5b823591506113cb6020840161138c565b90509250929050565b6000602082840312156113e657600080fd5b5035919050565b600060408301825184526020808401516040828701528281518085526060880191508383019450600092505b808310156114425784516001600160a01b03168252938301936001929092019190830190611419565b509695505050505050565b60006020808352606083018451828501528185015160408086015281815180845260808701915060808160051b8801019350848301925060005b818110156114b557607f198886030183526114a38585516113ed565b94509285019291850191600101611487565b5092979650505050505050565b60005b838110156114dd5781810151838201526020016114c5565b50506000910152565b60208152600082518060208401526115058160408501602087016114c2565b601f01601f19169190910160400192915050565b6020808252825182820181905260009190848201906040850190845b818110156112e857835183529284019291840191600101611535565b60208152600061043b60208301846113ed565b6020808252810182905260006001600160fb1b0383111561158457600080fd5b8260051b80856040850137919091016040019392505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b6000602082840312156115db57600080fd5b61043b8261138c565b60208082528181018390526000908460408401835b86811015611442576001600160a01b036116128461138c565b16825291830191908301906001016115f9565b7f5065726d697373696f6e733a206163636f756e7420000000000000000000000081526000835161165d8160158501602088016114c2565b7001034b99036b4b9b9b4b733903937b6329607d1b601591840191820152835161168e8160268401602088016114c2565b01602601949350505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761043e5761043e61169a565b8082018082111561043e5761043e61169a565b6000816116e9576116e961169a565b50600019019056fea2646970667358221220126d6310a65dba868ae14845cff1984d4d0d94ccca5babf9bf960029946972da64736f6c63430008140033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000f9e30ba8df802eef5a0fb239d59dee05f18b2e49

-----Decoded View---------------
Arg [0] : defaultAdmin_ (address): 0xf9E30Ba8Df802EeF5A0fb239d59dee05f18B2e49

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f9e30ba8df802eef5a0fb239d59dee05f18b2e49


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.