Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xEEb00E283259d5E1930f27c62552A6a6BE510348
Balance 0 ETH
Nonce 1
Code Size 9584 bytes
Proxy EIP-1967 Proxy Implementation: 0x36EaE2bD...3b1f
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

9584 bytes
0x60806040523661000b57005b600061001561014a565b9050600081600101600080357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161011b906119be565b60405180910390fd5b3660008037600080366000845af43d6000803e8060008114610145573d6000f35b3d6000fd5b6000807ff72346055b4d7224c7ec19860d22963ca622fbb313761bfba507c1a3aeedf37290508091505090565b600061018161014a565b9050600073ffffffffffffffffffffffffffffffffffffffff168160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610216576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020d90611a2a565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b61026681610498565b50565b60005b835181101561044d57600084828151811061028a57610289611a4a565b5b6020026020010151602001519050600060028111156102ac576102ab611a79565b5b8160028111156102bf576102be611a79565b5b0361030f5761030a8583815181106102da576102d9611a4a565b5b6020026020010151600001518684815181106102f9576102f8611a4a565b5b602002602001015160400151610755565b610439565b6001600281111561032357610322611a79565b5b81600281111561033657610335611a79565b5b036103865761038185838151811061035157610350611a4a565b5b6020026020010151600001518684815181106103705761036f611a4a565b5b6020026020010151604001516109cc565b610438565b60028081111561039957610398611a79565b5b8160028111156103ac576103ab611a79565b5b036103fc576103f78583815181106103c7576103c6611a4a565b5b6020026020010151600001518684815181106103e6576103e5611a4a565b5b602002602001015160400151610c4d565b610437565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90611b1a565b60405180910390fd5b5b5b50808061044590611b73565b91505061026c565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161048193929190611edf565b60405180910390a16104938282610dd8565b505050565b60006104a261057c565b905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061051d6000801b846105a9565b8273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b6000807f746c6723185dc95a8925081faed89cbd4670299390e2ebfb0b9c3e755e204ef490508091505090565b60006105b361057c565b90506105bf8383610efa565b6106f05761064e828260010160008460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008681526020019081526020016000206001016106f590919063ffffffff16565b503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc1ddb807f72f9e732ef6f32805c68a3b77ca377c0e141fe3bcaf19fe667f3534866040516106e79190611f3d565b60405180910390a45b505050565b600061071d836000018373ffffffffffffffffffffffffffffffffffffffff1660001b610f9b565b905092915050565b600061074d836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611002565b905092915050565b6000815111610799576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079090611fca565b60405180910390fd5b60006107a361014a565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610814576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080b9061205c565b60405180910390fd5b60008160020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff1603610881576108808285611025565b5b60005b83518110156109c55760008482815181106108a2576108a1611a4a565b5b602002602001015190506000846001016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610996576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098d906120ee565b60405180910390fd5b6109a28583868a611100565b83806109ad90612126565b945050505080806109bd90611b73565b915050610884565b5050505050565b6000815111610a10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0790611fca565b60405180910390fd5b6000610a1a61014a565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a829061205c565b60405180910390fd5b60008160020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018054905090506000816bffffffffffffffffffffffff1603610af857610af78285611025565b5b60005b8351811015610c46576000848281518110610b1957610b18611a4a565b5b602002602001015190506000846001016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508673ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610c0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c03906121cc565b60405180910390fd5b610c178582846112ad565b610c238583868a611100565b8380610c2e90612126565b94505050508080610c3e90611b73565b915050610afb565b5050505050565b6000815111610c91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c8890611fca565b60405180910390fd5b6000610c9b61014a565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614610d0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d039061225e565b60405180910390fd5b60005b8251811015610dd2576000838281518110610d2d57610d2c611a4a565b5b602002602001015190506000836001016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050610dbd8482846112ad565b50508080610dca90611b73565b915050610d0f565b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160315610ef657610e2f826040518060600160405280602881526020016124ef6028913961190f565b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051610e5791906122ba565b600060405180830381855af49150503d8060008114610e92576040519150601f19603f3d011682016040523d82523d6000602084013e610e97565b606091505b509150915081610ef357600081511115610eb45780518082602001fd5b83836040517f192105d7000000000000000000000000000000000000000000000000000000008152600401610eea9291906122d1565b60405180910390fd5b50505b5050565b600080610f0561057c565b9050610f92838260010160008460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600087815260200190815260200160002060010161072590919063ffffffff16565b91505092915050565b6000610fa78383611002565b610ffc5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190505b92915050565b600080836001016000848152602001908152602001600020541415905092915050565b611047816040518060600160405280602481526020016125176024913961190f565b81600301805490508260020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018190555081600301819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b81846001016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508360020160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000018390806001815401808255809150506001900390600052602060002090600891828204019190066004029091909190916101000a81548163ffffffff021916908360e01c021790555080846001016000857bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361131c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161131390612373565b60405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361138a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161138190612405565b60405180910390fd5b6000836001016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160149054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff169050600060018560020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001805490506114619190612425565b90508082146115f55760008560020160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000182815481106114c2576114c1611a4a565b5b90600052602060002090600891828204019190066004029054906101000a900460e01b9050808660020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001848154811061153e5761153d611a4a565b5b90600052602060002090600891828204019190066004026101000a81548163ffffffff021916908360e01c021790555082866001016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060000160146101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550505b8460020160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000180548061164957611648612459565b5b60019003818190600052602060002090600891828204019190066004026101000a81549063ffffffff02191690559055846001016000847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001908152602001600020600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a8154906bffffffffffffffffffffffff0219169055505060008103611908576000600186600301805490506117339190612425565b905060008660020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010154905081811461187457600087600301838154811061179d5761179c611a4a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050808860030183815481106117e1576117e0611a4a565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818860020160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010181905550505b8660030180548061188857611887612459565b5b6001900381819060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905590558660020160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001016000905550505b5050505050565b6000823b905060008111829061195b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195291906124cc565b60405180910390fd5b50505050565b600082825260208201905092915050565b7f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f74206578697374600082015250565b60006119a8602083611961565b91506119b382611972565b602082019050919050565b600060208201905081810360008301526119d78161199b565b9050919050565b7f416c726561647920696e697469616c697a656421000000000000000000000000600082015250565b6000611a14601483611961565b9150611a1f826119de565b602082019050919050565b60006020820190508181036000830152611a4381611a07565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4c69624469616d6f6e644375743a20496e636f7272656374204661636574437560008201527f74416374696f6e00000000000000000000000000000000000000000000000000602082015250565b6000611b04602783611961565b9150611b0f82611aa8565b604082019050919050565b60006020820190508181036000830152611b3381611af7565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000819050919050565b6000611b7e82611b69565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611bb057611baf611b3a565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611c1282611be7565b9050919050565b611c2281611c07565b82525050565b60038110611c3957611c38611a79565b5b50565b6000819050611c4a82611c28565b919050565b6000611c5a82611c3c565b9050919050565b611c6a81611c4f565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b611cd181611c9c565b82525050565b6000611ce38383611cc8565b60208301905092915050565b6000602082019050919050565b6000611d0782611c70565b611d118185611c7b565b9350611d1c83611c8c565b8060005b83811015611d4d578151611d348882611cd7565b9750611d3f83611cef565b925050600181019050611d20565b5085935050505092915050565b6000606083016000830151611d726000860182611c19565b506020830151611d856020860182611c61565b5060408301518482036040860152611d9d8282611cfc565b9150508091505092915050565b6000611db68383611d5a565b905092915050565b6000602082019050919050565b6000611dd682611bbb565b611de08185611bc6565b935083602082028501611df285611bd7565b8060005b85811015611e2e5784840389528151611e0f8582611daa565b9450611e1a83611dbe565b925060208a01995050600181019050611df6565b50829750879550505050505092915050565b611e4981611c07565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b83811015611e89578082015181840152602081019050611e6e565b60008484015250505050565b6000601f19601f8301169050919050565b6000611eb182611e4f565b611ebb8185611e5a565b9350611ecb818560208601611e6b565b611ed481611e95565b840191505092915050565b60006060820190508181036000830152611ef98186611dcb565b9050611f086020830185611e40565b8181036040830152611f1a8184611ea6565b9050949350505050565b6000819050919050565b611f3781611f24565b82525050565b6000602082019050611f526000830184611f2e565b92915050565b7f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660008201527f6163657420746f20637574000000000000000000000000000000000000000000602082015250565b6000611fb4602b83611961565b9150611fbf82611f58565b604082019050919050565b60006020820190508181036000830152611fe381611fa7565b9050919050565b7f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260008201527f6520616464726573732830290000000000000000000000000000000000000000602082015250565b6000612046602c83611961565b915061205182611fea565b604082019050919050565b6000602082019050818103600083015261207581612039565b9050919050565b7f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60008201527f6e207468617420616c7265616479206578697374730000000000000000000000602082015250565b60006120d8603583611961565b91506120e38261207c565b604082019050919050565b60006020820190508181036000830152612107816120cb565b9050919050565b60006bffffffffffffffffffffffff82169050919050565b60006121318261210e565b91506bffffffffffffffffffffffff820361214f5761214e611b3a565b5b600182019050919050565b7f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60008201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000602082015250565b60006121b6603883611961565b91506121c18261215a565b604082019050919050565b600060208201905081810360008301526121e5816121a9565b9050919050565b7f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260008201527f657373206d757374206265206164647265737328302900000000000000000000602082015250565b6000612248603683611961565b9150612253826121ec565b604082019050919050565b600060208201905081810360008301526122778161223b565b9050919050565b600081905092915050565b600061229482611e4f565b61229e818561227e565b93506122ae818560208601611e6b565b80840191505092915050565b60006122c68284612289565b915081905092915050565b60006040820190506122e66000830185611e40565b81810360208301526122f88184611ea6565b90509392505050565b7f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360008201527f74696f6e207468617420646f65736e2774206578697374000000000000000000602082015250565b600061235d603783611961565b915061236882612301565b604082019050919050565b6000602082019050818103600083015261238c81612350565b9050919050565b7f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560008201527f7461626c652066756e6374696f6e000000000000000000000000000000000000602082015250565b60006123ef602e83611961565b91506123fa82612393565b604082019050919050565b6000602082019050818103600083015261241e816123e2565b9050919050565b600061243082611b69565b915061243b83611b69565b925082820390508181111561245357612452611b3a565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600081519050919050565b600061249e82612488565b6124a88185611961565b93506124b8818560208601611e6b565b6124c181611e95565b840191505092915050565b600060208201905081810360008301526124e68184612493565b90509291505056fe4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a264697066735822122070fbd06feff1b7a70998a1d6e378d8024f260233de4e3d33541526982e33ada164736f6c63430008110033

Verified Source Code Full Match

Compiler: v0.8.17+commit.8df45f5f EVM: london Optimization: No
Diamond.sol 59 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

/******************************************************************************\
* Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
*
* Implementation of a diamond.
/******************************************************************************/

import "./base/Diamond/LibDiamondStorage.sol";
import { LibDiamond } from "./base/Diamond/LibDiamond.sol";
import { IDiamondCut } from "./interfaces/IDiamondCut.sol";

contract Diamond {
	constructor(address _contractOwner, address _diamondCutFacet) payable {
		LibDiamond.setDiamondAddress(address(this));
		LibDiamond.setContractOwner(_contractOwner);

		// Add the diamondCut external function from the diamondCutFacet
		IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1);
		bytes4[] memory functionSelectors = new bytes4[](1);
		functionSelectors[0] = IDiamondCut.diamondCut.selector;
		cut[0] = IDiamondCut.FacetCut({
			facetAddress: _diamondCutFacet,
			action: IDiamondCut.FacetCutAction.Add,
			functionSelectors: functionSelectors
		});
		LibDiamond.diamondCut(cut, address(0), "");
	}

	// Find facet for function that is called and execute the
	// function if a facet is found and return any value.
	fallback() external payable {
		DiamondStorage storage ds = LibDiamondStorage.layout();
		// get facet from function selector
		address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress;
		require(facet != address(0), "Diamond: Function does not exist");
		// Execute external function from facet using delegatecall and return any value.
		assembly {
			// copy function selector and any arguments
			calldatacopy(0, 0, calldatasize())
			// execute function call using the facet
			let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
			// get any return value
			returndatacopy(0, 0, returndatasize())
			// return any return value or error back to the caller
			switch result
			case 0 {
				revert(0, returndatasize())
			}
			default {
				return(0, returndatasize())
			}
		}
	}

	receive() external payable {}
}
UintUtils.sol 80 lines
// SPDX-License-Identifier: MIT
/**
 * Copyright (C) 2024 uSmart
 */
pragma solidity ^0.8.9;

/**
 * @title utility functions for uint256 operations
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)
 */
library UintUtils {
	error UintUtils__InsufficientHexLength();

	bytes16 private constant HEX_SYMBOLS = "0123456789abcdef";

	function add(uint256 a, int256 b) internal pure returns (uint256) {
		return b < 0 ? sub(a, -b) : a + uint256(b);
	}

	function sub(uint256 a, int256 b) internal pure returns (uint256) {
		return b < 0 ? add(a, -b) : a - uint256(b);
	}

	function toString(uint256 value) internal pure returns (string memory) {
		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);
	}

	function toHexString(uint256 value) internal pure returns (string memory) {
		if (value == 0) {
			return "0x00";
		}

		uint256 length = 0;

		for (uint256 temp = value; temp != 0; temp >>= 8) {
			unchecked {
				length++;
			}
		}

		return toHexString(value, 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";

		unchecked {
			for (uint256 i = 2 * length + 1; i > 1; --i) {
				buffer[i] = HEX_SYMBOLS[value & 0xf];
				value >>= 4;
			}
		}

		if (value != 0) revert UintUtils__InsufficientHexLength();

		return string(buffer);
	}
}
IERC173.sol 21 lines
// SPDX-License-Identifier: MIT
/**
 * Copyright (C) 2024 uSmart
 */
pragma solidity ^0.8.9;

/// @title ERC-173 Contract Ownership Standard
///  Note: the ERC-165 identifier for this interface is 0x7f5828d0
interface IERC173 {
	/// @dev This emits when ownership of a contract changes.
	event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

	/// @notice Get the address of the owner
	/// @return owner_ The address of the owner.
	function owner() external view returns (address owner_);

	/// @notice Set the address of the new owner of the contract
	/// @dev Set _newOwner to address(0) to renounce any ownership.
	/// @param _newOwner The address of the new owner of the contract
	function transferOwnership(address _newOwner) external;
}
AddressUtils.sol 105 lines
// SPDX-License-Identifier: MIT
/**
 * Copyright (C) 2024 uSmart
 */
pragma solidity ^0.8.9;

import { UintUtils } from "./UintUtils.sol";

library AddressUtils {
	using UintUtils for uint256;

	error AddressUtils__InsufficientBalance();
	error AddressUtils__NotContract();
	error AddressUtils__SendValueFailed();

	function toString(address account) internal pure returns (string memory) {
		return uint256(uint160(account)).toHexString(20);
	}

	function isContract(address account) internal view returns (bool) {
		uint256 size;
		assembly {
			size := extcodesize(account)
		}
		return size > 0;
	}

	function sendValue(address payable account, uint256 amount) internal {
		(bool success, ) = account.call{ value: amount }("");
		if (!success) revert AddressUtils__SendValueFailed();
	}

	function functionCall(address target, bytes memory data) internal returns (bytes memory) {
		return functionCall(target, data, "AddressUtils: failed low-level call");
	}

	function functionCall(address target, bytes memory data, string memory error) internal returns (bytes memory) {
		return _functionCallWithValue(target, data, 0, error);
	}

	function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
		return functionCallWithValue(target, data, value, "AddressUtils: failed low-level call with value");
	}

	function functionCallWithValue(address target, bytes memory data, uint256 value, string memory error) internal returns (bytes memory) {
		if (value > address(this).balance) revert AddressUtils__InsufficientBalance();
		return _functionCallWithValue(target, data, value, error);
	}

	/**
	 * @notice execute arbitrary external call with limited gas usage and amount of copied return data
	 * @dev derived from https://github.com/nomad-xyz/ExcessivelySafeCall (MIT License)
	 * @param target recipient of call
	 * @param gasAmount gas allowance for call
	 * @param value native token value to include in call
	 * @param maxCopy maximum number of bytes to copy from return data
	 * @param data encoded call data
	 * @return success whether call is successful
	 * @return returnData copied return data
	 */
	function excessivelySafeCall(
		address target,
		uint256 gasAmount,
		uint256 value,
		uint16 maxCopy,
		bytes memory data
	) internal returns (bool success, bytes memory returnData) {
		returnData = new bytes(maxCopy);

		assembly {
			// execute external call via assembly to avoid automatic copying of return data
			success := call(gasAmount, target, value, add(data, 0x20), mload(data), 0, 0)

			// determine whether to limit amount of data to copy
			let toCopy := returndatasize()

			if gt(toCopy, maxCopy) {
				toCopy := maxCopy
			}

			// store the length of the copied bytes
			mstore(returnData, toCopy)

			// copy the bytes from returndata[0:toCopy]
			returndatacopy(add(returnData, 0x20), 0, toCopy)
		}
	}

	function _functionCallWithValue(address target, bytes memory data, uint256 value, string memory error) private returns (bytes memory) {
		if (!isContract(target)) revert AddressUtils__NotContract();

		(bool success, bytes memory returnData) = target.call{ value: value }(data);

		if (success) {
			return returnData;
		} else if (returnData.length > 0) {
			assembly {
				let returnData_size := mload(returnData)
				revert(add(32, returnData), returnData_size)
			}
		} else {
			revert(error);
		}
	}
}
EnumerableSet.sol 177 lines
// SPDX-License-Identifier: MIT
/**
 * Copyright (C) 2024 uSmart
 */
pragma solidity ^0.8.9;

/**
 * @title Set implementation with enumeration functions
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)
 */
library EnumerableSet {
	error EnumerableSet__IndexOutOfBounds();

	struct Set {
		bytes32[] _values;
		// 1-indexed to allow 0 to signify nonexistence
		mapping(bytes32 => uint256) _indexes;
	}

	struct Bytes32Set {
		Set _inner;
	}

	struct AddressSet {
		Set _inner;
	}

	struct UintSet {
		Set _inner;
	}

	function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
		return _at(set._inner, index);
	}

	function at(AddressSet storage set, uint256 index) internal view returns (address) {
		return address(uint160(uint256(_at(set._inner, index))));
	}

	function at(UintSet storage set, uint256 index) internal view returns (uint256) {
		return uint256(_at(set._inner, index));
	}

	function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
		return _contains(set._inner, value);
	}

	function contains(AddressSet storage set, address value) internal view returns (bool) {
		return _contains(set._inner, bytes32(uint256(uint160(value))));
	}

	function contains(UintSet storage set, uint256 value) internal view returns (bool) {
		return _contains(set._inner, bytes32(value));
	}

	function indexOf(Bytes32Set storage set, bytes32 value) internal view returns (uint256) {
		return _indexOf(set._inner, value);
	}

	function indexOf(AddressSet storage set, address value) internal view returns (uint256) {
		return _indexOf(set._inner, bytes32(uint256(uint160(value))));
	}

	function indexOf(UintSet storage set, uint256 value) internal view returns (uint256) {
		return _indexOf(set._inner, bytes32(value));
	}

	function length(Bytes32Set storage set) internal view returns (uint256) {
		return _length(set._inner);
	}

	function length(AddressSet storage set) internal view returns (uint256) {
		return _length(set._inner);
	}

	function length(UintSet storage set) internal view returns (uint256) {
		return _length(set._inner);
	}

	function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
		return _add(set._inner, value);
	}

	function add(AddressSet storage set, address value) internal returns (bool) {
		return _add(set._inner, bytes32(uint256(uint160(value))));
	}

	function add(UintSet storage set, uint256 value) internal returns (bool) {
		return _add(set._inner, bytes32(value));
	}

	function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
		return _remove(set._inner, value);
	}

	function remove(AddressSet storage set, address value) internal returns (bool) {
		return _remove(set._inner, bytes32(uint256(uint160(value))));
	}

	function remove(UintSet storage set, uint256 value) internal returns (bool) {
		return _remove(set._inner, bytes32(value));
	}

	function toArray(Bytes32Set storage set) internal view returns (bytes32[] memory) {
		return set._inner._values;
	}

	function toArray(AddressSet storage set) internal view returns (address[] memory) {
		bytes32[] storage values = set._inner._values;
		address[] storage array;

		assembly {
			array.slot := values.slot
		}

		return array;
	}

	function toArray(UintSet storage set) internal view returns (uint256[] memory) {
		bytes32[] storage values = set._inner._values;
		uint256[] storage array;

		assembly {
			array.slot := values.slot
		}

		return array;
	}

	function _at(Set storage set, uint256 index) private view returns (bytes32) {
		if (index >= set._values.length) revert EnumerableSet__IndexOutOfBounds();
		return set._values[index];
	}

	function _contains(Set storage set, bytes32 value) private view returns (bool) {
		return set._indexes[value] != 0;
	}

	function _indexOf(Set storage set, bytes32 value) private view returns (uint256) {
		unchecked {
			return set._indexes[value] - 1;
		}
	}

	function _length(Set storage set) private view returns (uint256) {
		return set._values.length;
	}

	function _add(Set storage set, bytes32 value) private returns (bool status) {
		if (!_contains(set, value)) {
			set._values.push(value);
			set._indexes[value] = set._values.length;
			status = true;
		}
	}

	function _remove(Set storage set, bytes32 value) private returns (bool status) {
		uint256 valueIndex = set._indexes[value];

		if (valueIndex != 0) {
			unchecked {
				bytes32 last = set._values[set._values.length - 1];

				// move last value to now-vacant index

				set._values[valueIndex - 1] = last;
				set._indexes[last] = valueIndex;
			}
			// clear last index

			set._values.pop();
			delete set._indexes[value];

			status = true;
		}
	}
}
IDiamondCut.sol 32 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

/******************************************************************************\
* Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/

interface IDiamondCut {
	enum FacetCutAction {
		Add,
		Replace,
		Remove
	}
	// Add=0, Replace=1, Remove=2

	struct FacetCut {
		address facetAddress;
		FacetCutAction action;
		bytes4[] functionSelectors;
	}

	/// @notice Add/replace/remove any number of functions and optionally execute
	///         a function with delegatecall
	/// @param _diamondCut Contains the facet addresses and function selectors
	/// @param _init The address of the contract or facet to execute _calldata
	/// @param _calldata A function call, including function selector and arguments
	///                  _calldata is executed with delegatecall on _init
	function diamondCut(FacetCut[] calldata _diamondCut, address _init, bytes calldata _calldata) external;

	event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
LibDiamond.sol 178 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

/******************************************************************************\
* Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/
import "./LibDiamondStorage.sol";
import { IDiamondCut } from "../../interfaces/IDiamondCut.sol";

import { LibAccessControl } from "../AccessControl/LibAccessControl.sol";

// Remember to add the loupe functions from DiamondLoupeFacet to the diamond.
// The loupe functions are required by the EIP2535 Diamonds standard

error InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata);

library LibDiamond {
	event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);

	function setDiamondAddress(address _diamondAddress) internal {
		DiamondStorage storage ds = LibDiamondStorage.layout();
		require(ds.diamondAddress == address(0), "Already initialized!");
		ds.diamondAddress = _diamondAddress;
	}

	function getDiamondAddress() internal view returns (address) {
		DiamondStorage storage ds = LibDiamondStorage.layout();
		return ds.diamondAddress;
	}

	function setContractOwner(address _newOwner) internal {
		LibAccessControl._setOwner(_newOwner);
	}

	function enforceIsContractOwner() internal view {
		LibAccessControl._enforceIsOwner();
	}

	// Internal function version of diamondCut
	function diamondCut(IDiamondCut.FacetCut[] memory _diamondCut, address _init, bytes memory _calldata) internal {
		for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {
			IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;
			if (action == IDiamondCut.FacetCutAction.Add) {
				addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
			} else if (action == IDiamondCut.FacetCutAction.Replace) {
				replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
			} else if (action == IDiamondCut.FacetCutAction.Remove) {
				removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
			} else {
				revert("LibDiamondCut: Incorrect FacetCutAction");
			}
		}
		emit DiamondCut(_diamondCut, _init, _calldata);
		initializeDiamondCut(_init, _calldata);
	}

	function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
		require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
		DiamondStorage storage ds = LibDiamondStorage.layout();
		require(_facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)");
		uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);
		// add new facet address if it does not exist
		if (selectorPosition == 0) {
			addFacet(ds, _facetAddress);
		}
		for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
			bytes4 selector = _functionSelectors[selectorIndex];
			address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
			require(oldFacetAddress == address(0), "LibDiamondCut: Can't add function that already exists");
			addFunction(ds, selector, selectorPosition, _facetAddress);
			selectorPosition++;
		}
	}

	function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
		require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
		DiamondStorage storage ds = LibDiamondStorage.layout();
		require(_facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)");
		uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);
		// add new facet address if it does not exist
		if (selectorPosition == 0) {
			addFacet(ds, _facetAddress);
		}
		for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
			bytes4 selector = _functionSelectors[selectorIndex];
			address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
			require(oldFacetAddress != _facetAddress, "LibDiamondCut: Can't replace function with same function");
			removeFunction(ds, oldFacetAddress, selector);
			addFunction(ds, selector, selectorPosition, _facetAddress);
			selectorPosition++;
		}
	}

	function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
		require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
		DiamondStorage storage ds = LibDiamondStorage.layout();
		// if function does not exist then do nothing and return
		require(_facetAddress == address(0), "LibDiamondCut: Remove facet address must be address(0)");
		for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
			bytes4 selector = _functionSelectors[selectorIndex];
			address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
			removeFunction(ds, oldFacetAddress, selector);
		}
	}

	function addFacet(DiamondStorage storage ds, address _facetAddress) internal {
		enforceHasContractCode(_facetAddress, "LibDiamondCut: New facet has no code");
		ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;
		ds.facetAddresses.push(_facetAddress);
	}

	function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {
		ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;
		ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);
		ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;
	}

	function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal {
		require(_facetAddress != address(0), "LibDiamondCut: Can't remove function that doesn't exist");
		// an immutable function is a function defined directly in a diamond
		require(_facetAddress != address(this), "LibDiamondCut: Can't remove immutable function");
		// replace selector with last selector, then delete last selector
		uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;
		uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;
		// if not the same then replace _selector with lastSelector
		if (selectorPosition != lastSelectorPosition) {
			bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];
			ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;
			ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);
		}
		// delete the last selector
		ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();
		delete ds.selectorToFacetAndPosition[_selector];

		// if no more selectors for facet address then delete the facet address
		if (lastSelectorPosition == 0) {
			// replace facet address with last facet address and delete last facet address
			uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;
			uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;
			if (facetAddressPosition != lastFacetAddressPosition) {
				address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];
				ds.facetAddresses[facetAddressPosition] = lastFacetAddress;
				ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;
			}
			ds.facetAddresses.pop();
			delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;
		}
	}

	function initializeDiamondCut(address _init, bytes memory _calldata) internal {
		if (_init == address(0)) {
			return;
		}
		enforceHasContractCode(_init, "LibDiamondCut: _init address has no code");
		(bool success, bytes memory error) = _init.delegatecall(_calldata);
		if (!success) {
			if (error.length > 0) {
				// bubble up error
				/// @solidity memory-safe-assembly
				assembly {
					let returndata_size := mload(error)
					revert(add(32, error), returndata_size)
				}
			} else {
				revert InitializationFunctionReverted(_init, _calldata);
			}
		}
	}

	function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {
		uint256 contractSize;
		assembly {
			contractSize := extcodesize(_contract)
		}
		require(contractSize > 0, _errorMessage);
	}
}
RoleData.sol 12 lines
// SPDX-License-Identifier: MIT
/**
 * Copyright (C) 2024 uSmart
 */
pragma solidity ^0.8.9;

import { EnumerableSet } from "../../utils/EnumerableSet.sol";

struct RoleData {
	bytes32 adminRole;
	EnumerableSet.AddressSet members;
}
LibDiamondStorage.sol 41 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import { EnumerableSet } from "../../utils/EnumerableSet.sol";

struct FacetAddressAndPosition {
	address facetAddress;
	uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array
}

struct FacetFunctionSelectors {
	bytes4[] functionSelectors;
	uint256 facetAddressPosition; // position of facetAddress in facetAddresses array
}

struct DiamondStorage {
	address diamondAddress;
	// maps function selector to the facet address and
	// the position of the selector in the facetFunctionSelectors.selectors array
	mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;
	// maps facet addresses to function selectors
	mapping(address => FacetFunctionSelectors) facetFunctionSelectors;
	// facet addresses
	address[] facetAddresses;
	// Used to query if a contract implements an interface.
	// Used to implement ERC-165.
	mapping(bytes4 => bool) supportedInterfaces;
	//the whole diamond is paused or not
	bool paused;
}

library LibDiamondStorage {
	bytes32 internal constant STORAGE_SLOT = keccak256("usmart.contracts.diamond.storage.v1");

	function layout() internal pure returns (DiamondStorage storage layout_) {
		bytes32 position = STORAGE_SLOT;
		assembly {
			layout_.slot := position
		}
	}
}
LibAccessControl.sol 180 lines
// SPDX-License-Identifier: MIT
/**
 * Copyright (C) 2024 uSmart
 */
pragma solidity ^0.8.9;

import "./LibAccessControlStorage.sol";

import { IERC173 } from "../../interfaces/IERC173.sol";

import { EnumerableSet } from "../../utils/EnumerableSet.sol";
import { UintUtils } from "../../utils/UintUtils.sol";
import { AddressUtils } from "../../utils/AddressUtils.sol";

library LibAccessControl {
	using EnumerableSet for EnumerableSet.AddressSet;
	using UintUtils for uint256;
	using AddressUtils for address;

	error Ownable__NotOwner();
	error Ownable__NotTransitiveOwner();

	error AccessDenied(bytes32 role, address account);

	event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

	event RoleAdminChanged(address indexed owner, bytes32 role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
	event RoleGranted(address indexed owner, bytes32 role, address indexed account, address indexed sender);
	event RoleRevoked(address indexed owner, bytes32 role, address indexed account, address indexed sender);

	bytes32 internal constant DEFAULT_ADMIN_ROLE = 0x00;

	function _setOwner(address _newOwner) internal {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		address previousOwner = acls.owner;
		acls.owner = _newOwner;

		//Init DEFAULT_ADMIN_ROLE to _newOwner
		LibAccessControl._grantRole(LibAccessControl.DEFAULT_ADMIN_ROLE, _newOwner);

		emit OwnershipTransferred(previousOwner, _newOwner);
	}

	function _owner() internal view returns (address owner_) {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		owner_ = acls.owner;
	}

	function _transitiveOwner() internal view returns (address owner_) {
		owner_ = LibAccessControl._owner();

		while (owner_.isContract()) {
			try IERC173(owner_).owner() returns (address transitiveOwner) {
				owner_ = transitiveOwner;
			} catch {
				break;
			}
		}
	}

	function _enforceIsOwner() internal view {
		//require(msg.sender == _owner(), "Not owner!");
		if (msg.sender != _owner()) {
			revert Ownable__NotOwner();
		}
	}

	function _enforceIsTransitiveOwner() internal view {
		//require(msg.sender == _transitiveOwner(), "Not transitive owner!");
		if (msg.sender != _transitiveOwner()) {
			revert Ownable__NotTransitiveOwner();
		}
	}

	/**
	 * @notice assign role to given account
	 * @param _role role to assign
	 * @param _account recipient of role assignment
	 */
	function _grantRole(bytes32 _role, address _account) internal {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		if (!_hasRole(_role, _account)) {
			acls.roles[acls.owner][_role].members.add(_account);
			emit RoleGranted(acls.owner, _role, _account, msg.sender);
		}
	}

	/**
	 * @notice unassign role from given account
	 * @param _role role to unassign
	 * @param _account account to revokeAccessControlStorage
	 */
	function _revokeRole(bytes32 _role, address _account) internal {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		// require(_role != LibAccessControl.DEFAULT_ADMIN_ROLE && _account != acls.owner);
		acls.roles[acls.owner][_role].members.remove(_account);
		emit RoleRevoked(acls.owner, _role, _account, msg.sender);
	}

	/**
	 * @notice relinquish role
	 * @param _role role to relinquish
	 */
	function _renounceRole(bytes32 _role) internal {
		_revokeRole(_role, msg.sender);
	}

	/**
	 * @notice Query one of the accounts that have role of the project
	 * @dev WARNING: When using _getProjectRoleMember and _getProjectRoleMemberCount, make sure you perform all queries on the same block.
	 * @param _role role to query
	 * @param _index index of role member
	 */
	function _getRoleMember(bytes32 _role, uint256 _index) internal view returns (address) {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		return acls.roles[acls.owner][_role].members.at(_index);
	}

	/**
	 * @notice Query the number of accounts that have role.
	 * @dev WARNING: When using _getRoleMember and _getRoleMemberCount, make sure you perform all queries on the same block.
	 * @param _role role to query
	 */
	function _getRoleMemberCount(address, bytes32 _role) internal view returns (uint256) {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		return acls.roles[acls.owner][_role].members.length();
	}

	/**
	 * @notice query whether role is assigned to account
	 * @param _role role to query
	 * @param _account account to query
	 * @return bool whether role is assigned to account
	 */
	function _hasRole(bytes32 _role, address _account) internal view returns (bool) {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		return acls.roles[acls.owner][_role].members.contains(_account);
	}

	/**
	 * @notice revert if sender does not have given role
	 * @param _role role to query
	 */
	function _checkRole(bytes32 _role) internal view {
		_checkRole(_role, msg.sender);
	}

	/**
	 * @notice revert if given account does not have given role
	 * @param _role role to query
	 * @param _account to query
	 */
	function _checkRole(bytes32 _role, address _account) internal view {
		if (!_hasRole(_role, _account)) {
			revert AccessDenied({ role: _role, account: _account });
		}
	}

	/**
	 * @notice query admin role for given role
	 * @param _role role to query
	 * @return admin role
	 */
	function _getRoleAdmin(bytes32 _role) internal view returns (bytes32) {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		return acls.roles[acls.owner][_role].adminRole;
	}

	/**
	 * @notice set role as admin role
	 * @param _role role to set
	 * @param _adminRole admin role to set
	 */
	function _setRoleAdmin(bytes32 _role, bytes32 _adminRole) internal {
		AccessControllStorage storage acls = LibAccessControlStorage.layout();
		bytes32 previousAdminRole = _getRoleAdmin(_role);
		acls.roles[acls.owner][_role].adminRole = _adminRole;
		emit RoleAdminChanged(acls.owner, _role, previousAdminRole, _adminRole);
	}
}
LibAccessControlStorage.sol 25 lines
// SPDX-License-Identifier: MIT
/**
 * Copyright (C) 2024 uSmart
 */
pragma solidity ^0.8.9;

import { EnumerableSet } from "../../utils/EnumerableSet.sol";
import "./RoleData.sol";

struct AccessControllStorage {
	//owner => role => adminRole, members mapping
	address owner;
	mapping(address => mapping(bytes32 => RoleData)) roles;
}

library LibAccessControlStorage {
	bytes32 internal constant STORAGE_SLOT = keccak256("usmart.common.access-control.storage.v1");

	function layout() internal pure returns (AccessControllStorage storage acls_) {
		bytes32 position = STORAGE_SLOT;
		assembly {
			acls_.slot := position
		}
	}
}

Recent Transactions

No transactions found for this address