# 4.13 EIP-7777：Governance for Human Robot Societies？（故事）

本EIP还在讨论中：

{% embed url="<https://ethereum-magicians.org/t/erc-7777-proposal-for-human-robot-societies/21216>" %}
欢迎加入讨论
{% endembed %}

[本EIP的协作请点击此处](https://github.com/ethereum/ERCs/pull/660/files)（不参与技术协作，只想[直接看内容请点击此处](https://github.com/ethereum/ERCs/pull/660/files?short_path=6718ff6#diff-6718ff604da59f4557bfeaca7290c119630c54246f22e9fd43b0c508139638b1)）

## EIP-7777：人机社会的治理

描述：这个ERC定义了管理人类和机器人的身份的接口，并建立它们互动的规则集。

### 摘要

本提案定义了两个核心接口：`IUniversalIdentity` 和 `IUniversalCharter`，为人类和机器人提供了建立身份和创建由特定规则集管理的去中心化社区的机制。`IUniversalIdentity` 接口确立了对除人脑以外的有知觉计算架构的公平和公正对待，使机器人能够获得链上身份，从而与人类进行互动和交易。`IUniversalCharter` 使人类和机器人能够创建、加入（“注册”）、维护（“更新”）、离开和终止基于预定义规则集的自我管理社群，为人类和机器人混合社会提供合作与繁荣的框架。这些接口旨在为去中心化系统中的人机互动提供一个灵活而可执行的结构，确保所有参与者的效率、透明度和安全性。

### 动机

人类的大脑是一个湿润的、并行处理的电化学计算机。最近的硬件和软件进展使得人类社会很可能很快就需要与有意识的非人类计算机（如机器人）进行互动的工具。我们目前的政府形式，公民根据出生地自动注册到特定的规则体系，并不适用于没有传统出生地或出生时间的机器人。机器人面临许多困难，其中之一是它们（目前）无法获得标准的身份证明（如护照），不清楚适用于它们的规则体系是什么（因为一般来说，它们并不是在特定地方出生的），而且它们目前无法使用标准的人类银行系统。同样，如果机器人受到人类或非生物计算机的伤害，目前也不清楚哪个人类法院有管辖权。

传统的地理定义和以人为中心的系统可能效率低下、变更缓慢、透明度不足，并且难以适应全球化的虚拟社会。去中心化、不可变和公开的计算机为这些局限性提供了理想的解决方案，因为它们本质上并不歧视非人类计算机，因此为治理提供了一个公平和更公正的框架。特别是，智能合约可以为调节参与方的权利和责任提供一个强大的框架，而不管它们的计算架构的实现细节是什么。

这个ERC的总体动机是为异构全球社会提供一个专注于身份/治理的智能合约标准接口。虽然这样的规则体系数量无限，但为这些规则体系提供一个标准接口显然是有益的，这大大减少了创建、加入、维护和结束这些社会的摩擦和复杂性。这个ERC的具体动机有两个：

1. 机器人身份创建和管理：为了有意义地参与并遵守链上的法律，非人类（如机器人）必须能够获得有意义的链上身份。重要的是，这些身份应该使机器人能够享受作为特定社会一部分的好处，同时也承担相应的责任。因此，我们提议为机器人启用基于智能合约的身份。具体来说，每个机器人由一个智能合约表示，并需要遵循合约中定义的规则与链上的其他代理进行互动。这个接口也确保了所有参与者能够灵活地提议、采用或撤销规则，从而实现自我管理的合规性和与其他参与者的透明互动。
2. 规则创建和执行：为了让人类和机器人有效合作，双方必须就规则体系达成一致。这个基于以太坊的系统提供了一个基本的去中心化框架，通过智能合约来治理人类与机器人的互动。我们提议通过要求人类和机器人加入受监管的访问智能合约来执行规则体系，这些合约检查它们是否遵守给定的规则。我们还确保可扩展性，即可以创建多个受监管的访问合约，以满足不同的目的，人类和机器人可以根据需要选择加入相关系统。

这些接口共同构成了管理复杂人类与机器人互动的基础，促进一个去中心化、可验证和基于规则的生态系统，在这个生态系统中，机器人和人类可以安全、透明和负责任地互动，以实现所有人的最大利益。

### 技术规范

文中关键字 "MUST"、"MUST NOT"、"REQUIRED"、"SHALL"、"SHALL NOT"、"SHOULD"、"SHOULD NOT"、"RECOMMENDED"、"NOT RECOMMENDED"、"MAY" 和 "OPTIONAL" 的解释应参照 RFC 2119 和 RFC 8174。

```
interface IUniversalIdentity {

   /// @notice 向机器人的身份添加一个规则，表示机器人同意遵循该规则。
   /// @param rule 表示机器人同意遵循的规则的动态字节数组。
   /// @dev 该规则应该来源于机器人打算加入的 IUniversalCharter 合约中定义的规则集。
   /// @dev 这个函数应该由合约实现，用以添加机器人打算遵循的规则。
   function addRule(bytes memory rule) external;

   /// @notice 从机器人的身份中移除一个规则。
   /// @param rule 表示机器人不再同意遵循的规则的动态字节数组。
   /// @dev 这个函数应该由合约实现，用以移除机器人不打算遵循的规则。
   function removeRule(bytes memory rule) external;

   /// @notice 检查机器人是否遵守特定规则。
   /// @param rule 要检查的规则。
   /// @return bool 如果机器人遵守该规则，则返回 true。
   /// @dev 这个函数必须由合约实现以进行合规性验证。
   function checkCompliance(bytes memory rule) external view returns (bool);

   /// @dev 当规则被添加到机器人的身份时触发的事件。
   event RuleAdded(bytes rule);

   /// @dev 当规则从机器人的身份中移除时触发的事件。
   event RuleRemoved(bytes rule);
   
   /// @dev 当订阅了章程（Charter）时触发的事件。
   event SubscribedToCharter(address indexed charter);

   /// @dev 当取消订阅章程时触发的事件。
   event UnsubscribedFromCharter(address indexed charter);
}

interface IUniversalCharter {

   // 定义用户类型的枚举。
   enum UserType { Human, Robot }

   /// @notice 一个用户（人或机器人）通过同意一个规则集而注册入系统。
   /// @param userType 用户的类型。
   /// @param ruleSet 用户同意遵循的各个规则的数组。 
   /// @dev 这个函数必须由使用此接口的合约实现。
   /// @dev 实现的合约必须确保在将用户注册到系统之前，通过调用 `checkCompliance` 验证用户是否遵守指定的规则集。
   function registerUser(UserType userType, bytes[] memory ruleSet) external;

   /// @notice 允许用户（人或机器人）退出系统 
   /// @dev 这个函数必须仅限于用户本人调用（通过 `msg.sender`）。 
   /// @dev 实现的合约必须确保用户在成功退出系统之前遵守了所有必要规则，通过调用 `checkCompliance` 进行验证。
   function leaveSystem() external;

   /// @notice 检查用户（人或机器人）是否遵守系统的规则。
   /// @param user 用户（人或机器人）的地址。
   /// @param ruleSet 要验证的各个规则的数组。 
   /// @return bool 如果用户遵守规则集，则返回 true。
   /// @dev 这个函数应该调用用户的 IUniversalIdentity 合约的 `checkCompliance` 函数逐个检查规则。 
   /// @dev 这个函数必须由合约实现以进行合规性验证。
   function checkCompliance(address user, bytes[] memory ruleSet) external view returns (bool);

   /// @notice 更新规则集。
   /// @param newRuleSet 替换现有规则的新规则数组。 
   /// @dev 这个函数应该限制为授权的用户（例如，合约所有者）。
   function updateRuleSet(bytes[] memory newRuleSet) external;

   /// @notice 终止合约，阻止任何进一步的注册或交互。
   /// @dev 这个函数应该限制为授权的用户（例如，合约所有者）。
   /// @dev 这个函数应该由合约实现。
   function terminateContract() external;

   /// @dev 当用户通过同意一组规则加入系统时触发的事件。
   event UserRegistered(address indexed user, UserType userType, bytes[] ruleSet);

   /// @dev 当用户在履行义务后成功离开系统时触发的事件。
   event UserLeft(address indexed user);

   /// @dev 当用户的合规性随规则集得到验证时触发的事件。
   event ComplianceChecked(address indexed user, bytes[] ruleSet);

   /// @dev 当规则集被更新时触发的事件。
   event RuleSetUpdated(bytes[] newRuleSet, address updatedBy);
}
```

### 基本原理

**IUniversalIdentity**

`addRule(bytes memory rule)`\
这个函数允许机器人向其身份添加特定规则，表明其遵守该规则的意图。它支持动态规则管理，使机器人能够灵活地适应不同系统中的新合规要求。

`removeRule(bytes memory rule)`\
这个函数从机器人的身份中移除规则，通常是在机器人不再需要遵守该规则时（例如，离开一个系统）。它允许合约动态管理机器人的义务，确保其规则集保持准确和最新。

`checkCompliance(bytes memory rule)`\
这个函数检查机器人是否遵守特定规则。它确保机器人在被授权执行任何操作之前遵守规则。

`Events (RuleAdded, RuleRemoved)`\
这些事件提供透明度和可追溯性，使跟踪合规状态变得更加容易。

**IUniversalCharter**

`enum UserType { Human, Robot }`\
UserType 枚举区分人类和机器人，以节省 gas，使合约能够更方便地处理不同用户类型，而不必承担字符串相关的成本和错误。这为未来的不同处理奠定了基础，允许系统根据用户是人类还是机器人应用不同的规则或逻辑。

`registerUser(UserType userType, bytes[] memory ruleSet)`\
这个函数对于注册用户至关重要，将他们与特定的规则集关联。它确保用户（无论是人类还是机器人）在加入系统时都绑定到特定的规则集。

`leaveSystem()`\
这个函数允许用户通过注销自己来离开系统。使用 msg.sender 确保只有用户自己可以调用此函数，从而增强安全性。在用户被允许离开之前，需要进行合规检查（通过 checkCompliance），确保用户在退出系统之前履行所有义务。

`checkCompliance(address user, bytes[] memory ruleSet)`\
这个函数检查用户是否遵守他们同意遵循的特定规则集。它确保系统能够有效地管理和验证与预定义规则集的合规性，帮助维护系统的整体完整性。

`updateRuleSet(bytes[] memory newRuleSet)`\
这个函数使合约中的规则集能够被修改，确保系统能够随着时间的推移而适应。

`terminateContract()`\
这个函数允许合约永久关闭，防止系统内的进一步交互或注册。

`Events (UserRegistered, UserLeft, ComplianceChecked, RuleSetUpdated, ContractTerminated)`\
这些事件共同确保关键活动对链外系统和参与者可见，使系统可审计和透明。

### 向后兼容性

未发现向后兼容性问题。

### 测试用例

### 参考实现

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.19;

import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { UniversalCharter } from "./UniversalCharter.sol";

// 接口
import { IUniversalIdentity } from "./interface/IUniversalIdentity.sol";
import { IUniversalCharter } from "./interface/IUniversalCharter.sol";

/// @title UniversalIdentity
/// @notice UniversalIdentity 合约用于管理机器人的身份。

contract UniversalIdentity is IUniversalIdentity, OwnableUpgradeable {
  /// @notice 当前合约实现的版本标识
   string public constant VERSION = "v0.0.1";

   /// @notice 存储机器人同意遵循的规则的映射
   mapping(bytes => bool) private robotRules;

   /// @notice 存储每个规则的链外合规状态的映射
   mapping(bytes => bool) private complianceStatus;

   /// @notice 跟踪机器人订阅的章程
   mapping(address => bool) private subscribedCharters;

   /// @notice 自定义错误，以节省回滚时的 gas
   error RuleNotAgreed(bytes rule);
   error RuleNotCompliant(bytes rule);
   error RuleAlreadyAdded(bytes rule);

   /// @dev 检查合规性时发出的事件
   /// @param updater 合规性更新者的地址（合约所有者）
   /// @param rule 被检查的规则
   event ComplianceChecked(address indexed updater, bytes rule);

   /// @notice 检查规则是否存在的修饰符(Modifier)
   modifier ruleExists(bytes memory rule) {
	   require(robotRules[rule], "规则不存在");
	   _;
	   }

    /// @notice 设置所有者的构造函数（constructor）
    constructor() {
        initialize({ _owner: address(0xdEaD) });
    }

    /// @dev 初始化函数
    function initialize(address _owner) public initializer {
        __Ownable_init();
        transferOwnership(_owner);
    }

    /// @notice 向机器人的身份添加规则
    /// @param rule 代表机器人同意遵循的规则的动态字节数组。
    function addRule(bytes memory rule) external override onlyOwner {
        if (robotRules[rule]) {
            revert RuleAlreadyAdded(rule);
        }

        // 将规则添加到映射中
        robotRules[rule] = true;

        emit RuleAdded(rule);
    }

    /// @notice 从机器人的身份中移除规则
    /// @param rule 代表机器人不再同意遵循的规则的动态字节数组。
    function removeRule(bytes memory rule) external override onlyOwner ruleExists(rule) {
        robotRules[rule] = false;
        complianceStatus[rule] = false;

        emit RuleRemoved(rule);
    }

    /// @notice 使用其存储的规则集订阅并注册到特定的 UniversalCharter 合约
    /// @param charter UniversalCharter 合约的地址
    /// @param version 要获取和注册的规则集版本
    function subscribeAndRegisterToCharter(address charter, uint256 version) external {
        require(!subscribedCharters[charter], "已订阅此章程");
        subscribedCharters[charter] = true;

        // 直接从 UniversalCharter 合约获取规则集
        bytes[] memory ruleSet = UniversalCharter(charter).getRuleSet(version);

        // 使用获取的规则集注册为机器人的用户
        UniversalCharter(charter).registerUser(IUniversalCharter.UserType.Robot, ruleSet);

        emit SubscribedToCharter(charter);
    }

    /// @notice 退出特定的 UniversalCharter 合约
    /// @param charter 要退出的 UniversalCharter 合约的地址
    function leaveCharter(address charter) external {
        require(subscribedCharters[charter], "不再订阅此章程");

        // 调用 UniversalCharter 合约的 leaveSystem 函数
        UniversalCharter(charter).leaveSystem();

        // 退出后取消对该章程的订阅
        subscribedCharters[charter] = false;
        emit UnsubscribedFromCharter(charter);
    }

    /// @notice 更新规则的合规状态（由所有者调用）
    /// @param rule 代表规则的动态字节数组
    /// @param status 合规状态（符合则为 true，不符合则为 false）
    function updateCompliance(bytes memory rule, bool status) external onlyOwner ruleExists(rule) {
        complianceStatus[rule] = status;

        emit ComplianceChecked(msg.sender, rule);
    }

    /// @notice 检查机器人是否同意遵循特定规则，并且是否合规
    /// @param rule 要检查的规则。
    /// @return bool 如果机器人同意该规则并且合规则返回 true
    function checkCompliance(bytes memory rule) external view override returns (bool) {
        if (!robotRules[rule]) {
            revert RuleNotAgreed(rule);
        }

        return true;
    }

    /// @notice 获取规则的合规状态（译者：应为获取要检查其合规状态的规则）
    /// @param rule 要检查的规则。
    function getRule(bytes memory rule) external view returns (bool) {
        return robotRules[rule];
    }

    /// @notice 获取章程的订阅状态
    /// @param charter 要检查的章程地址。
    function getSubscribedCharters(address charter) external view returns (bool) {
        return subscribedCharters[charter];
    }

    /// @notice 获取规则的合规状态
    /// @param rule 要检查的规则。
    function getComplianceStatus(bytes memory rule) external view returns (bool) {
        return complianceStatus[rule];
    }
}
```

```solidity
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.20;

import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { SystemConfig } from "./SystemConfig.sol";

// 接口
import { IUniversalCharter } from "./interface/IUniversalCharter.sol";
import { IUniversalIdentity } from "./interface/IUniversalIdentity.sol";

/// @title UniversalCharter
/// @notice UniversalCharter合约用于管理用户的注册和合规性。

contract UniversalCharter is IUniversalCharter, OwnableUpgradeable {
    /// @notice 存储注册用户信息的结构体
    struct UserInfo {
        bool isRegistered;
        UserType userType;
        uint256 ruleSetVersion; // 用户遵循的规则集版本
    }

    /// @notice 存储注册用户的映射
    mapping(address => UserInfo) private users;

    /// @notice 按版本号存储规则集的映射
    mapping(uint256 => bytes[]) private ruleSets;

    /// @notice 跟踪规则集哈希及其对应版本的映射
    mapping(bytes32 => uint256) private ruleSetVersions;

    /// @notice 合约当前实现的版本标识符
    string public constant VERSION = "v0.0.1";

    /// @notice 跟踪规则集当前版本之变量
    uint256 private currentVersion;

    /// @notice 存储SystemConfig合约地址的变量
    SystemConfig public systemConfig;

    /// @notice 当方法在暂停状态下无法调用时的错误。将来可能重命名为`Paused`，但与`Paused`事件冲突。
    error CallPaused();

    /// @notice 在暂停时回滚
    modifier whenNotPaused() {
        if (paused()) revert CallPaused();
        _;
    }

    /// @notice 构造UniversalCharter合约
    constructor() {
        initialize({ _owner: address(0xdEaD), _systemConfig: address(0xdEaD) });
    }

    /// @dev 初始化函数
    function initialize(address _owner, address _systemConfig) public initializer {
        __Ownable_init();
        transferOwnership(_owner);
        systemConfig = SystemConfig(_systemConfig);
    }

    /// @notice 通过同意规则集来注册用户（人类或机器人）
    /// @param userType 用户类型：人类或机器人
    /// @param ruleSet 用户同意遵循的单独规则数组
    function registerUser(UserType userType, bytes[] memory ruleSet) external override whenNotPaused {
        require(!users[msg.sender].isRegistered, "用户已注册");

        // 哈希规则集以查找对应版本
        bytes32 ruleSetHash = keccak256(abi.encode(ruleSet));
        uint256 version = ruleSetVersions[ruleSetHash];
        require(version > 0, "无效或未注册的规则集");

        // 对于机器人，通过UniversalIdentity合约确保遵循每条规则
        if (userType == UserType.Robot) {
            require(_checkRobotCompliance(msg.sender, version), "机器人未遵循规则集");
        }

        // 用版本化的规则集注册用户
        users[msg.sender] = UserInfo({ isRegistered: true, userType: userType, ruleSetVersion: version });

        emit UserRegistered(msg.sender, userType, ruleSet);
    }

    /// @notice 允许用户（人类或机器人）在通过合规检查后离开系统
    function leaveSystem() external override whenNotPaused {
        require(users[msg.sender].isRegistered, "User not registered（译者建议为：用户已注销。即 User unregistered）");

        UserInfo memory userInfo = users[msg.sender];

        // 对于机器人，验证遵循规则集中的所有规则
        uint256 version = userInfo.ruleSetVersion;
        if (userInfo.userType == UserType.Robot) {
            require(_checkRobotCompliance(msg.sender, version), "机器人未遵循规则集");
        }

        users[msg.sender] = UserInfo({ isRegistered: false, userType: UserType.Human, ruleSetVersion: 0 });

        emit UserLeft(msg.sender);
    }

    /// @notice 检查用户是否遵循其注册的规则集
    /// @param user 用户（人类或机器人）的地址
    /// @param ruleSet 要验证的单独规则数组
    /// @return bool 如果用户遵循给定的规则集，则返回真
    function checkCompliance(address user, bytes[] memory ruleSet) external view override returns (bool) {
        require(users[user].isRegistered, "用户未注册");

        // 哈希提供的规则集以查找对应版本
        bytes32 ruleSetHash = keccak256(abi.encode(ruleSet));
        uint256 version = ruleSetVersions[ruleSetHash];
        require(version > 0, "无效或未注册的规则集");
        require(users[user].ruleSetVersion == version, "规则集版本不匹配");

        // 对于机器人，检查遵循UniversalIdentity合约中的每条规则
        if (users[user].userType == UserType.Robot) {
            return _checkRobotCompliance(user, version);
        }

        // 如果用户是人类，目前假设遵循（可以扩展）
        return true;
    }

    /// @notice 内部函数检查机器人与其规则集版本的合规性
    /// @dev 如果机器人未遵循任何规则，该函数将回滚；出于查看目的返回true
    /// @param robotAddress 机器人的地址
    /// @param version 要验证合规性的规则集版本
    /// @return bool 如果机器人遵循规则集中的所有规则，则返回true
	function _checkRobotCompliance(address robotAddress, uint256 version) internal view returns (bool) {
        IUniversalIdentity robot = IUniversalIdentity(robotAddress);
        bytes[] memory rules = ruleSets[version];

        for (uint256 i = 0; i < rules.length; i++) {
            if (!robot.checkCompliance(rules[i])) {
                return false;
            }
        }

        return true;
    }

    /// @notice 更新或定义一个新的规则集版本。
    /// @param newRuleSet 新的一组单独规则的数组。
    /// @dev 这个函数应该限制给授权用户（例如，合约拥有者）。
    function updateRuleSet(bytes[] memory newRuleSet) external whenNotPaused onlyOwner {
        require(newRuleSet.length > 0, "不能更新为空的规则集");

        // 哈希新规则集并确保它尚未注册
        bytes32 ruleSetHash = keccak256(abi.encode(newRuleSet));
        require(ruleSetVersions[ruleSetHash] == 0, "规则集已注册");

        // 增加版本并存储新规则集
        currentVersion += 1;
        ruleSets[currentVersion] = newRuleSet;
        ruleSetVersions[ruleSetHash] = currentVersion;

        emit RuleSetUpdated(newRuleSet, msg.sender);
    }

    /// @notice 获取规则集的最新版本。
    function getLatestRuleSetVersion() external view returns (uint256) {
        return currentVersion;
    }

    /// @notice 获取特定版本的规则集。
    /// @param version 要检索的规则集版本。
    function getRuleSet(uint256 version) external view returns (bytes[] memory) {
        return ruleSets[version];
    }

    /// @notice 获取特定规则集的版本号。
    /// @param ruleSet 要检索版本的规则集哈希。
    function getRuleSetVersion(bytes32 ruleSet) external view returns (uint256) {
        return ruleSetVersions[ruleSet];
    }

    function getUserInfo(address user) external view returns (UserInfo memory) {
        return users[user];
    }

    /// @notice 获取当前暂停状态。
    /// @return paused_ 合约是否被暂停。
    function paused() public view returns (bool paused_) {
        paused_ = systemConfig.paused();
    }
}
```

### 安全考虑事项

合规更新者：UniversalIdentity合约中的合规更新者角色对于更新合规状态（目前仅限于所有者）至关重要。确保安全的所有权以减少未经授权或恶意更新的风险是非常重要的。

规则管理：UniversalIdentity合约中的addRule、removeRule和updateCompliance等功能以及UniversalCharter合约中的updateRuleSet直接影响规则的执行。确保这些功能仅能被授权用户调用是非常重要的。

可升级合约：使用OwnableUpgradeable在初始化和升级过程中引入了风险。确保initialize函数受到保护，防止重新执行，对于避免重新初始化攻击至关重要。

gas消耗：过大的规则集可能导致高gas费用或拒绝服务风险。考虑对每个规则集允许的规则数量设置限制，以保持gas效率并避免性能问题。

### 版权

通过CC0放弃版权及相关权利。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://u.naturaldao.io/be/chapter4/erc-7777.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
