Aragon DAO 權限分析

        在Aragon中,一個DAO由三個內部Dapp和多個外部Dapp(用來拓展功能)共同組成,這其中外部Dapp又包括代幣、投票、資金這幾個核心功能。Dapp之間交互必然會涉及到權限管理,因此這篇文章簡要分析了Aragon DAO中的權限結構設計,爲我們開發自己的DAO提供一些參考或借鑑。

一、權限的分類

        在Aragon DAO中,權限分爲兩類。一類是角色權限,是指某Dapp中特定功能的執行權限;另一類是管理權限,是指對Dapp中角色權限的管理。

        這裏舉一個例子來說明:
        假定有合約A 、 B 、C 、D 。合約A有一個寫數據的方法f,用來更改合約A中的狀態變量X,如下:

  1. 調用 A.f() 的來更改X的權限,假定爲B,這就是角色權限。
  2. 更改a.f()的調用權限爲C(這時不是更改X) ,這是由D來負責的,這就是管理權限。

        這裏不管是角色權限還是管理權限,都可以設定爲DAO中任意Dapp(包括內部和外部)、指定地址或者任意賬號。
        在Aragon Dao中,點擊權限欄目,可以看到外部Dapp默認管理權限都是投票合約,也就是所有管理活動都必須投票通過才行,這符合DAO的本意。如下圖:

管理權限基本上均爲投票Dapp

二、權限的實現

        不管是角色權限還是管理權限,都是使用map來存儲,具體實現在ACL.sol中的ACL合約中。

2.1 下面的map記錄了Dapp的角色權限

mapping (bytes32 => bytes32) internal permissions; // permissions hash => params hash

        它的鍵是一個bytes32,代表角色的哈希值,對應的也值爲一個哈希,是權限參數數組編碼後得到的。

        角色哈希值是這樣計算的:

function roleHash(address _where, bytes32 _what) internal pure returns (bytes32) {
    return keccak256(abi.encodePacked("ROLE", _where, _what));
}

        這其中_where代表Dapp地址,_what代表進行的具體操作。比如代幣Dapp的增發功能,這裏_where就是代幣的地址 _what是一個代表增發操作的bytes32

2.2 下面的map記錄了上面得到的參數哈希對應的參數數組

mapping (bytes32 => Param[]) internal permissionParams; // params hash => params

2.3 下面的map記錄了Dapp的管理權限

mapping (bytes32 => address) internal permissionManager;

        它的鍵是一個bytes32,代表管理權限的哈希值,對應的值爲一個地址,用來代表權限擁有者的地址。
        管理權限的哈希計算在這裏就不再列出。

三、權限初始化

        我們直接從ACL合約的初始化函數開始,代碼如下:

	/**
    * @dev Initialize can only be called once. It saves the block number in which it was initialized.
    * @notice Initialize an ACL instance and set `_permissionsCreator` as the entity that can create other permissions
    * @param _permissionsCreator Entity that will be given permission over createPermission
    */
    function initialize(address _permissionsCreator) public onlyInit {
        initialized();
        require(msg.sender == address(kernel()), ERROR_AUTH_INIT_KERNEL);

        _createPermission(_permissionsCreator, this, CREATE_PERMISSIONS_ROLE, _permissionsCreator);
    }

        onlyInit 是限定只初始化一次的函數修飾符。
        函數體裏第一行是初始化,比如存儲當前blockNumber等。
        第二行是檢查調用權限,只能爲核心合約(kernel合約)。
        最後一行創建了ACL合約的初始權限,我們來看這個內部函數的定義:

	/**
    * @dev Internal createPermission for access inside the kernel (on instantiation)
    */
    function _createPermission(address _entity, address _app, bytes32 _role, address _manager) internal {
        _setPermission(_entity, _app, _role, EMPTY_PARAM_HASH);
        _setPermissionManager(_manager, _app, _role);
    }

        結合這兩個函數,我們可以看到權限初始化做了兩件事(略過相關代碼展示):

  1. 設置本合約(ACL)的角色權限爲 _permissionsCreator
  2. 設定本合約(ACL)的管理權限爲 _permissionsCreator

四、權限管理

        合約中管理權限的函數有:

  • createPermission 用來未設置過管理權限時進行設置,也可用於移除管理權限後再設置。
  • grantPermissiongrantPermissionP 更換某個Dapp的角色權限,分別對應未設置過管理權限和設置過管理權限後。
  • revokePermission 取消某個Dapp的角色權限,需要管理權限。
  • setPermissionManager 更換某個Dapp的管理權限,需要管理權限。
  • removePermissionManager 移除某個Dapp的管理權限,需要管理權限。
  • createBurnedPermissionburnPermissionManager 移除某個Dapp中不存在的角色功能,分別對應未設置過管理權限和設置後。

        下面的方法爲權限查詢函數:

  • getPermissionParamsLength 用來獲取權限參數數組的長度
  • getPermissionParam 用來獲取特定索引的權限參數
  • getPermissionManager 返回某個Dapp的管理權限
  • hasPermission 返回調用者是否有某個Dapp的某些角色權限

        ACL合約中其它方法都是不對外的內部輔助方法,不再介紹。

        好了,對 Aragon DAO 權限的簡單分析就到這了。本文主要是做了一個大致介紹,如果想要進一步深入細節,需要查閱相關合約的源代碼實現。



歡迎大家留言指出錯誤或者提出改進意見。

2019年最後一篇文章!!!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章