pragmasolidity0.8.23;interfaceIAccessControlRegistry{// Emitted when a contract is registered.
// @param _contract The address of the registered contract.
// @param _admin The address of the admin for the registered contract.
eventContractRegistered(addressindexed_contract,addressindexed_admin);// Emitted when a contract is unregistered.
// @param _contract The address of the unregistered contract.
// @param _admin The address who unregistered the contract
eventContractUnregistered(addressindexed_contract,addressindexed_admin);// Emitted when a role is granted to an account for a contract.
// @param targetContract The address of the contract.
// @param role The role being granted.
// @param account The address of the account.
eventRoleGranted(addressindexedtargetContract,bytes32indexedrole,addressindexedaccount);// Emitted when a role is revoked from an account for a contract.
// @param targetContract The address of the contract.
// @param role The role being revoked.
// @param account The address of the account.
eventRoleRevoked(addressindexedtargetContract,bytes32indexedrole,addressindexedaccount);// Registers a contract with the given admin.
// @param _admin The address of the admin for the registered contract.
functionregisterContract(address_admin)external;// Unregisters a contract.
// @param _contract The address of the contract to unregister.
functionunRegisterContract(address_contract)external;// Grants roles to multiple accounts for multiple contracts.
// @param targetContracts An array of contract addresses to which roles will be granted.
// @param roles An array of roles to be granted.
// @param accounts An array of accounts to be granted the roles.
functiongrantRole(address[]memorytargetContracts,bytes32[]memoryroles,address[]memoryaccounts)external;// Revokes roles from multiple accounts for multiple contracts.
// @param targetContracts An array of contract addresses from which roles will be revoked.
// @param roles An array of roles to be revoked.
// @param accounts An array of accounts from which the roles will be revoked.
functionrevokeRole(address[]memorytargetContracts,bytes32[]memoryroles,address[]memoryaccounts)external;//Gets the information of a registered contract.
//@param _contract The address of the contract to get the information.
//@return isActive Whether the contract is active.
//@return admin The address of the admin for the contract.
//MUST revert if the registered contract doesn't exist
functiongetContractInfo(address_contract)externalviewreturns(boolisActive,addressadmin);// Gets the information of a registered contract.
// @param _contract The address of the contract to get the information.
// @return isActive Whether the contract is active.
// @return admin The address of the admin for the contract.
// MUST revert if the registered contract doesn't exist`
functiongetRoleInfo(address_contract)externalviewreturns(boolisActive,addressadmin);}
pragmasolidity0.8.23;import"./IAccessControlRegistry.sol";contractAccessControlRegistryisIAccessControlRegistry{// Contains information about a registered contract.
// @param isActive Indicates whether the contract is active.
// @param admin The address of the admin for the registered contract.
structContractInfo{boolisActive;addressadmin;}// Mapping to store information of registered contracts
mapping(address=>ContractInfo)publiccontracts;// Mapping to track roles assigned to accounts for specific contracts
mapping(address=>mapping(address=>mapping(bytes32=>bool)))public_contractRoles;// Custom error to handle duplicate registration attempts
errorContractAlreadyRegistered();// Modifier to check if the caller is an admin or the contract itself
modifieronlyAdminOrContract(address_contract){require(_isAdmin(_contract,msg.sender)||(contracts[msg.sender].isActive&&msg.sender==_contract),"Caller is not admin nor contract");_;}// Modifier to check if the caller is an admin of the contract
modifieronlyAdmin(address_contract){require(_isAdmin(_contract,msg.sender),"Caller is not an admin");_;}// Modifier to ensure the contract is active
modifieronlyActiveContract(address_contract){require(contracts[_contract].isActive,"Contract not registered");_;}// Modifier to validate if the provided address is non-zero
modifiervalidAddress(addressaddr){require(addr!=address(0),"Invalid address");_;}// Registers a contract with the given admin
// _admin: Address of the admin to register
functionregisterContract(address_admin)externalvalidAddress(_admin){address_contract=msg.sender;// Check if the contract is already registered
// 检查合约是否已注册
ContractInfostoragecontractInfo=contracts[_contract];if(contractInfo.isActive){revertContractAlreadyRegistered();}// Register the contract with the provided admin
// 使用提供的管理员注册合约
contractInfo.isActive=true;contractInfo.admin=_admin;emitContractRegistered(_contract,_admin);}// Unregisters a contract
// _contract: Address of the contract to unregister
functionunRegisterContract(address_contract)publiconlyAdmin(_contract)onlyActiveContract(_contract){ContractInfostoragecontractInfo=contracts[_contract];contractInfo.isActive=false;contractInfo.admin=address(0);emitContractUnregistered(_contract,msg.sender);}// Grants roles to multiple accounts for multiple contracts
// targetContracts: Array of contract addresses
// roles: Array of roles to grant
// accounts: Array of accounts to assign the roles
functiongrantRole(address[]memorytargetContracts,bytes32[]memoryroles,address[]memoryaccounts)public{require(targetContracts.length==roles.length&&roles.length==accounts.length,"Array lengths do not match");uint256cachedArrayLength=roles.length;// Grant roles in a batch
// 批量授予角色
for(uint256i;i<cachedArrayLength;++i){_grantRole(targetContracts[i],roles[i],accounts[i]);}}// Revokes roles from multiple accounts for multiple contracts
// targetContracts: Array of contract addresses
// roles: Array of roles to revoke
// accounts: Array of accounts from which roles are revoked
functionrevokeRole(address[]memorytargetContracts,bytes32[]memoryroles,address[]memoryaccounts)public{require(targetContracts.length==roles.length&&roles.length==accounts.length,"Array lengths do not match");uint256cachedArrayLength=roles.length;// Revoke roles in a batch
// 批量撤销角色
for(uint256i;i<cachedArrayLength;++i){_revokeRole(targetContracts[i],roles[i],accounts[i]);}}// Retrieves information of a registered contract
// _contract: Address of the contract
// Returns: isActive status and admin address
functiongetContractInfo(address_contract)publicviewreturns(boolisActive,addressadmin){ContractInfostorageinfo=contracts[_contract];return(info.isActive,info.admin);}// Gets role information for an account and contract
// targetContract: Address of the target contract
// account: Address of the account
// role: Role identifier
// Returns: Boolean indicating if the account has the role
functiongetRoleInfo(addresstargetContract,addressaccount,bytes32role)publicviewreturns(bool){return_contractRoles[targetContract][account][role];}// Internal function to grant a role to an account for a contract
// 用于为合约的账户授予角色的内部函数
function_grantRole(addresstargetContract,bytes32role,addressaccount)internalonlyAdminOrContract(targetContract)onlyActiveContract(targetContract)validAddress(account){_contractRoles[targetContract][account][role]=true;emitRoleGranted(targetContract,role,account);}// Internal function to revoke a role from an account for a contract
// 用于从合约的账户撤销角色的内部函数
function_revokeRole(addresstargetContract,bytes32role,addressaccount)internalonlyAdminOrContract(targetContract)onlyActiveContract(targetContract)validAddress(account){require(_contractRoles[targetContract][account][role],"Role already revoked");_contractRoles[targetContract][account][role]=false;emitRoleRevoked(targetContract,role,account);}// Checks if the caller is an admin for the contract
// _contract: Address of the contract
// _admin: Address of the admin
// Returns: Boolean indicating admin status
function_isAdmin(address_contract,address_admin)internalviewreturns(bool){return_admin==contracts[_contract].admin;}}