Implementeer Role-Based Access Control (RBAC) in Solidity Smart Contracts
description
Met deze prompt kan de gebruiker veilige en onderhoudbare Solidity smart contracts bouwen door fijnmazige toegangscontrole te implementeren. Het lost het veelvoorkomende probleem van ongeautoriseerde contractinteracties op en verhoogt de contractbeveiliging. Vergeleken met algemene contractontwerp-prompts richt het zich specifiek op permissiebeheer, een cruciaal aspect voor veel gedecentraliseerde applicaties.
prompt
Help me een Solidity smart contract te maken dat rolgebaseerde toegangscontrole implementeert. Voeg functies toe zoals het definiëren van rollen, het toewijzen en intrekken van rollen aan adressen, en het beperken van functie-toegang op basis van rollen. Leg uit hoe ik OpenZeppelin's AccessCo ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Hier is een voorbeeld van een Solidity smart contract dat rolgebaseerde toegangscontrole (RBAC) implementeert met behulp van OpenZeppelin's AccessControl. Dit contract definieert drie rollen: ADMIN, MINTER en standaardgebruiker. Het bevat functies voor het toewijzen en intrekken van rollen, en functies zoals mint en burn die alleen door bepaalde rollen kunnen worden uitgevoerd.
**Stap 1: Installatie van OpenZeppelin's Contracts**
Zorg dat je OpenZeppelin Contracts hebt geïnstalleerd via npm:
```bash
npm install @openzeppelin/contracts
```
**Stap 2: Solidity Contract**
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
contract MyToken is AccessControl {
// Definieer rollen met keccak256 hashes
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");
bytes32 public constant MINTER_ROLE = keccak256("MINTER");
// Balansen van adressen
mapping(address => uint256) private balances;
// Events
event Transfer(address indexed from, address indexed to, uint256 amount);
event Mint(address indexed to, uint256 amount);
event Burn(address indexed from, uint256 amount);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
constructor() {
// Geef de deployer de ADMIN en MINTER rollen
_setupRole(ADMIN_ROLE, msg.sender);
_setupRole(MINTER_ROLE, msg.sender);
// Verhoog het admin van alle rollen naar de DEFAULT_ADMIN_ROLE
_setRoleAdmin(ADMIN_ROLE, DEFAULT_ADMIN_ROLE);
_setRoleAdmin(MINTER_ROLE, ADMIN_ROLE);
}
// Modifier om te controleren op ADMIN rol
modifier onlyAdmin() {
require(hasRole(ADMIN_ROLE, msg.sender), "Geen admin rechten");
_;
}
// Modifier om te controleren op MINTER rol
modifier onlyMinter() {
require(hasRole(MINTER_ROLE, msg.sender), "Geen minter rechten");
_;
}
// Functie om rollen toe te wijzen
function grantRole(bytes32 role, address account) public onlyAdmin {
grantRole(role, account);
}
// Functie om rollen in te trekken
function revokeRole(bytes32 role, address account) public onlyAdmin {
revokeRole(role, account);
}
// Mint functie, alleen toegankelijk voor MINTERS
function mint(address to, uint256 amount) public onlyMinter {
balances[to] += amount;
emit Mint(to, amount);
emit Transfer(address(0), to, amount);
}
// Burn functie, alleen toegankelijk voor adressen met voldoende balans
function burn(uint256 amount) public {
require(balances[msg.sender] >= amount, "Onvoldoende balans");
balances[msg.sender] -= amount;
emit Burn(msg.sender, amount);
emit Transfer(msg.sender, address(0), amount);
}
// Lees saldo van een adres
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
}
```
---
### Uitleg
- **AccessControl** van OpenZeppelin wordt gebruikt voor rolbeheer.
- **Rollen** worden gedefinieerd met `keccak256` hashes: `ADMIN_ROLE`, `MINTER_ROLE`.
- De **constructor** geeft de deployer de ADMIN- en MINTER-rollen.
- **`grantRole` en `revokeRole`** functies maken het mogelijk rollen toe te wijzen en in te trekken, maar alleen door een **ADMIN**.
- **`mint`** kan alleen door adressen met de MINTER-rol worden uitgevoerd.
- **`burn`** wordt door de eigenaar zelf uitgevoerd en vermindert hun eigen balans.
- Rollen kunnen worden beheerd via de functies en zorgen voor een veilige rol-gebaseerde permissie.
---
### Hoe gebruik je dit contract?
1. Deploy het contract.
2. Verleen extra rollen aan adressen met `grantRole`.
3. Alleen adressen met de juiste rollen kunnen minten of andere beheertaken uitvoeren.
4. Rollen kunnen worden ingetrokken of toegekend via de bijbehorende functies.
---
Als je liever je eigen RBAC-systeem wilt implementeren zonder OpenZeppelin, kun je bijvoorbeeld een `mapping(bytes32 => mapping(address => bool))` gebruiken om rollen bij te houden en eigen functies schrijven voor toewijzen, intrekken en controle. Maar OpenZeppelin biedt een veilige en beproefde basis voor dit soort functionaliteit.
provider: deepseek
model: deepseek-chat
Zeker! Ik help je met het maken van een Solidity smart contract met rolgebaseerde toegangscontrole. Ik zal beide benaderingen uitleggen: gebruik van OpenZeppelin's AccessControl en een eenvoudige eigen implementatie.
## Optie 1: Gebruik van OpenZeppelin AccessControl (Aanbevolen)
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyTokenWithRBAC is ERC20, AccessControl {
// Definieer rol constants als bytes32
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
constructor() ERC20("MyToken", "MTK") {
// Stel de deployer in als de eerste admin
_grantRole(ADMIN_ROLE, msg.sender);
// ADMIN_ROLE kan MINTER_ROLE en BURNER_ROLE beheren
_setRoleAdmin(MINTER_ROLE, ADMIN_ROLE);
_setRoleAdmin(BURNER_ROLE, ADMIN_ROLE);
}
// Mint functie - alleen voor MINTER_ROLE
function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
_mint(to, amount);
}
// Burn functie - alleen voor BURNER_ROLE
function burn(address from, uint256 amount) external onlyRole(BURNER_ROLE) {
_burn(from, amount);
}
// Admin functie om rollen toe te wijzen
function assignRole(bytes32 role, address account) external onlyRole(ADMIN_ROLE) {
grantRole(role, account);
}
// Admin functie om rollen in te trekken
function revokeRole(bytes32 role, address account) external onlyRole(ADMIN_ROLE) {
revokeRole(role, account);
}
// Hulpfunctie om rollen te controleren
function hasRole(bytes32 role, address account) public view override returns (bool) {
return super.hasRole(role, account);
}
}
```
## Optie 2: Eigen RBAC Implementatie
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract CustomRBAC {
// Rol definities
string public constant ADMIN = "ADMIN";
string public constant MINTER = "MINTER";
string public constant BURNER = "BURNER";
// Eigenaar van het contract
address public owner;
// Mapping van adres naar rollen
mapping(address => mapping(string => bool)) private roles;
// Events voor transparantie
event RoleGranted(string indexed role, address indexed account, address indexed sender);
event RoleRevoked(string indexed role, address indexed account, address indexed sender);
modifier onlyOwner() {
require(msg.sender == owner, "Alleen eigenaar");
_;
}
modifier onlyRole(string memory role) {
require(hasRole(role, msg.sender), "Toegang geweigerd: rol vereist");
_;
}
constructor() {
owner = msg.sender;
// Stel de eigenaar in als admin
_grantRole(ADMIN, msg.sender);
}
// Rol toewijzen (alleen voor admins)
function grantRole(string memory role, address account) external onlyRole(ADMIN) {
_grantRole(role, account);
}
// Rol intrekken (alleen voor admins)
function revokeRole(string memory role, address account) external onlyRole(ADMIN) {
_revokeRole(role, account);
}
// Interne functie voor roltoewijzing
function _grantRole(string memory role, address account) internal {
roles[account][role] = true;
emit RoleGranted(role, account, msg.sender);
}
// Interne functie voor rolintrekking
function _revokeRole(string memory role, address account) internal {
roles[account][role] = false;
emit RoleRevoked(role, account, msg.sender);
}
// Controleer of adres een rol heeft
function hasRole(string memory role, address account) public view returns (bool) {
return roles[account][role];
}
// Voorbeeld functies met rolbeperkingen
function mint() external onlyRole(MINTER) {
// Mint logica hier
}
function burn() external onlyRole(BURNER) {
// Burn logica hier
}
// Admin-only functie voor beheer
function adminFunction() external onlyRole(ADMIN) {
// Admin-specifieke logica
}
}
```
## Gebruiksvoorbeelden en Implementatie
### 1. Contract Deployen
```javascript
// Na deployen heeft de deployer automatisch ADMIN_ROLE
const contract = await MyTokenWithRBAC.deploy();
```
### 2. Rollen Toewijzen
```javascript
// Als admin, wijs MINTER_ROLE toe aan een adres
await contract.assignRole(contract.MINTER_ROLE, "0x123...");
// Of gebruik de OpenZeppelin functie direct
await contract.grantRole(contract.MINTER_ROLE, "0x123...");
```
### 3. Rollen Controleren
```javascript
// Check of een adres een rol heeft
const hasMinterRole = await contract.hasRole(contract.MINTER_ROLE, "0x123...");
```
### 4. Beveiligde Functies Gebruiken
```solidity
// Alleen MINTER_ROLE kan deze functie aanroepen
function mintTokens(address to, uint256 amount) public onlyRole(MINTER_ROLE) {
// Mint logica
}
// Alleen BURNER_ROLE kan deze functie aanroepen
function burnTokens(address from, uint256 amount) public onlyRole(BURNER_ROLE) {
// Burn logica
}
```
## Aanbevelingen en Best Practices
1. **Gebruik OpenZeppelin AccessControl** - Dit is de veiligste en meest geteste aanpak
2. **Role Hierarchie** - Stel in dat ADMIN_ROLE andere rollen kan beheren
3. **Events** - Log alle rolwijzigingen voor transparantie
4. **Access Control Checks** - Voer checks uit aan het begin van functies
5. **Minimal Privilege** - Geef alleen de benodigde rechten
## Installatie OpenZeppelin
```bash
npm install @openzeppelin/contracts
```
De OpenZeppelin implementatie is aanbevolen omdat deze:
- Uitgebreid getest en geaudit is
- Gas-efficient is
- Standaard ERC-165 ondersteuning heeft
- Flexibele rolhiërarchie ondersteunt
Heb je nog specifieke vragen over de implementatie?