ERC-5982 역할 기반 접근 제어 표준 (Role-based Access Control)

Review · 기타 · 2022-11-15 작성

스마트 컨트랙트의 권한을 역할(role) 단위로 조회·부여·생성·삭제하는 공통 인터페이스를 정의합니다. 역할은 bytes32 값으로 표현하고 역할의 힘은 특정 함수를 호출할 수 있는 능력으로 정의합니다.

왜 필요한가

스마트 컨트랙트에는 토큰 발행이나 설정 변경처럼 아무나 호출하면 안 되는 특권 기능이 있습니다. 이를 지키는 가장 단순한 방법은 소유자(owner) 계정 하나에 모든 권한을 몰아주는 소유권 기반 접근 제어입니다. 반면 역할 기반 접근 제어는 여러 사용자에게 하나 이상의 역할을 지정하고 역할에 따라 특권 기능 접근을 허용하는 방식입니다. 최소 권한 원칙(principle of least privilege)에 따라 여러 사람에게 꼭 필요한 권한만 나눠 줄 수 있어 소유권 기반보다 안전하고 유연합니다. 다만 이런 역할 관리를 컨트랙트마다 제각각 구현하면 지갑이나 도구가 권한 구조를 일관된 방식으로 읽기 어렵습니다. 이 표준은 역할을 읽고 부여하고 만들고 없애는 방법과 역할 메타데이터를 표현하는 방법을 하나의 공통 인터페이스로 정의합니다.

구현해야 하는 것

심층 설명

역할의 표현과 생성 규칙

역할은 bytes32 값 하나로 표현합니다. 값은 역할 이름의 keccak256 해시로 계산하는 것이 권장되며(RECOMMENDED) 형식은 bytes32 role = keccak256("<role_name>")입니다. 예를 들어 발행자 역할은 bytes32 role = keccak256("MINTER")로 만듭니다. 사람이 읽는 역할 이름에서 역할 값이 그대로 계산되므로, 이름만 알면 누구나 같은 역할 값을 얻을 수 있습니다.

필수 인터페이스 IERC_ACL_CORE

표준을 따르는 컨트랙트는 IERC_ACL_CORE를 반드시 구현해야 합니다(MUST). 이 인터페이스는 세 함수로 구성됩니다. hasRole(bytes32 role, address account)는 계정이 역할을 가졌는지 조회하고 grantRole(bytes32 role, address account)는 역할을 부여하며 revokeRole(bytes32 role, address account)는 역할을 회수합니다. 함수 이름과 매개변수는 OpenZeppelin 구현과의 하위 호환이 가능하도록 선택되었습니다. 또 자기 역할을 스스로 포기하는 renounceRole은 별도 함수로 채택하지 않고 revokeRole에 통합해 인터페이스를 단순하게 만들었습니다.

권장 확장 IERC_ACL_GENERAL

IERC_ACL_GENERAL은 구현이 권장되는(RECOMMENDED) 선택 확장입니다. 임의 데이터 _data를 함께 넘기는 확장판 grantRole, revokeRole, hasRole이 있고 역할을 만들고 없애는 createRole과 destroyRole, 역할의 메서드 권한을 정하는 setRolePower가 있습니다. createRole은 그 역할을 관리하는 역할(adminOfRole)과 이름(name), 설명(desc), URI를 함께 받습니다. canGrantRole, canRevokeRole, canExecute 같은 조회 함수로 어떤 역할이 역할 부여, 회수, 메서드 실행을 할 수 있는지 미리 확인할 수 있습니다. 상태 변화는 RoleGranted, RoleRevoked, RoleCreated, RoleDestroyed, RolePowerSet 이벤트로 기록합니다. 이 함수들의 _data 매개변수는 ERC-5750을 따르는 것으로, 이후 확장을 가능하게 합니다.

역할의 힘은 메서드 호출 능력

이 표준은 역할이 가진 힘(role power)을 bytes4 메서드 셀렉터로 식별되는 특정 메서드를 호출할 수 있는 능력으로 정의합니다. 역할이 추상적인 직함에 그치지 않고 어떤 함수를 호출할 수 있는가로 구체화되는 것입니다. setRolePower(bytes32 role, bytes4 methods, bytes calldata _data)로 역할에 메서드 권한을 설정하면 RolePowerSet 이벤트가 기록되고 canExecute(bytes32 executor, bytes4 methods, bytes32 calldata payload, bytes calldata _data)로 특정 역할이 특정 메서드를 실행할 수 있는지 미리 조회할 수 있습니다.

역할 메타데이터 IERC_ACL_METADATA

IERC_ACL_METADATA는 구현해도 되는(MAY) 선택 확장입니다. roleName(bytes32)은 역할의 이름을, roleDescription(bytes32)은 역할의 설명을, roleURI(bytes32)는 역할과 연결된 URI를 돌려줍니다. 역할 자체는 bytes32 값이라 사람이 읽기 어렵기 때문에, 이 인터페이스를 구현하면 지갑이나 도구가 역할의 의미를 읽을 수 있는 형태로 보여 줄 수 있습니다. IERC_ACL_GENERAL의 createRole도 역할을 만들 때 name, desc, uri를 함께 받아 RoleCreated 이벤트로 남깁니다.

ERC-165 지원과 제안 상태

준수 컨트랙트는 ERC-165 식별자를 구현하는 것이 좋습니다(SHOULD). 이 제안은 ERC-165와 ERC-5750을 필요 조건(requires)으로 둡니다. 한편 원문의 하위 호환성(Backwards Compatibility) 절과 보안 고려 사항(Security Considerations) 절은 둘 다 논의 필요(Needs discussion)로만 적혀 있어 아직 내용이 채워지지 않았습니다. 이 제안은 현재 Review 상태로, 확정된 표준이 아니며 앞으로 내용이 바뀔 수 있습니다.

ERC 원문 · ← ERCs