Last active
October 20, 2021 15:14
-
-
Save kumarabhirup/94c6bd697a4bc545e5fd8245ec68b6d8 to your computer and use it in GitHub Desktop.
Solidity Library for easier Permissions Management
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity >=0.4.22 <0.9.0; | |
/** | |
* Author: Kumar Abhirup (kumareth) | |
* Version: 1.0.0 | |
* Compiles best with: 0.7.6 | |
* Many contracts have ownerOnly functions, | |
* but I believe it's safer to have multiple owner addresses | |
* to fallback to, in case you lose one. | |
* You can inherit this PermissionManagement contract | |
* to let multiple people do admin operations on your contract effectively. | |
* You can add & remove admins and moderators. | |
* You can transfer ownership (basically you can change the founder). | |
* You can change the beneficiary (the prime payable wallet) as well. | |
* You can also ban & unban addresses, | |
* to restrict certain features on your contract for certain addresses. | |
* Use modifiers like "founderOnly", "adminOnly", "moderatorOnly" & "adhereToBan" | |
* in your contract to put the permissions to use. | |
* Code: https://ipfs.io/ipfs/QmbVZevdhRwXfoeVti9GLo7tESUrSg7b2psHxugz9Dx1cg | |
* IPFS Metadata: https://ipfs.io/ipfs/Qmdh8DC3FHxCPEVEvhXzZWMHZ8y3Dbavzvtib7s7rEBmcs | |
* Access the Contract on the Ethereum Ropsten Testnet Network | |
* https://ropsten.etherscan.io/address/0xceaef9490f7516914c056bc5902633e76790a999 | |
*/ | |
contract PermissionManagement { | |
address public founder = msg.sender; | |
address payable public beneficiary = msg.sender; | |
mapping(address => bool) public admins; | |
mapping(address => bool) public moderators; | |
mapping(address => bool) public bannedAddresses; | |
enum RoleChange { | |
MADE_FOUNDER, | |
MADE_BENEFICIARY, | |
PROMOTED_TO_ADMIN, | |
PROMOTED_TO_MODERATOR, | |
DEMOTED_TO_MODERATOR, | |
KICKED_FROM_TEAM, | |
BANNED, | |
UNBANNED | |
} | |
event PermissionsModified(address _address, RoleChange _roleChange); | |
constructor ( | |
address[] memory _admins, | |
address[] memory _moderators | |
) public { | |
// require more admins for safety and backup | |
require(_admins.length > 0); | |
// make founder the admin and moderator | |
admins[founder] = true; | |
moderators[founder] = true; | |
emit PermissionsModified(founder, RoleChange.MADE_FOUNDER); | |
// give admin privileges, and also make admins moderators. | |
for (uint i = 0; i < _admins.length; i++) { | |
admins[_admins[i]] = true; | |
moderators[_admins[i]] = true; | |
emit PermissionsModified(_admins[i], RoleChange.PROMOTED_TO_ADMIN); | |
} | |
// give moderator privileges | |
for (uint i = 0; i < _moderators.length; i++) { | |
moderators[_moderators[i]] = true; | |
emit PermissionsModified(_moderators[i], RoleChange.PROMOTED_TO_MODERATOR); | |
} | |
} | |
modifier founderOnly() { | |
require( | |
msg.sender == founder, | |
"This function is restricted to the contract's founder." | |
); | |
_; | |
} | |
modifier adminOnly() { | |
require( | |
admins[msg.sender] == true, | |
"This function is restricted to the contract's admins." | |
); | |
_; | |
} | |
modifier moderatorOnly() { | |
require( | |
moderators[msg.sender] == true, | |
"This function is restricted to the contract's moderators." | |
); | |
_; | |
} | |
modifier adhereToBan() { | |
require( | |
bannedAddresses[msg.sender] != true, | |
"You are banned from accessing this function in the contract." | |
); | |
_; | |
} | |
modifier addressMustNotBeFounder(address _address) { | |
require( | |
_address != founder, | |
"Address must not be the Founder's address." | |
); | |
_; | |
} | |
modifier addressMustNotBeAdmin(address _address) { | |
require( | |
admins[_address] != true, | |
"Address must not be an Admin's address." | |
); | |
_; | |
} | |
modifier addressMustNotBeModerator(address _address) { | |
require( | |
moderators[_address] != true, | |
"Address must not be a Moderator's address." | |
); | |
_; | |
} | |
modifier addressMustNotBeBeneficiary(address _address) { | |
require( | |
_address != beneficiary, | |
"Address must not be a Beneficiary's address." | |
); | |
_; | |
} | |
function transferFoundership(address payable _founder) | |
public | |
founderOnly | |
addressMustNotBeFounder(_founder) | |
returns(address) | |
{ | |
require(_founder != msg.sender, "Lmao nice try, but you can't make yourself the founder."); | |
founder = _founder; | |
admins[_founder] = true; | |
moderators[_founder] = true; | |
emit PermissionsModified(_founder, RoleChange.MADE_FOUNDER); | |
// TODO: Tranfer beneficiary when founder is transferred. | |
// beneficiary = _founder; | |
return founder; | |
} | |
function changeBeneficiary(address payable _beneficiary) | |
public | |
adminOnly | |
returns(address) | |
{ | |
require(_beneficiary != msg.sender, "Lmao nice try, but you can't make yourself the beneficiary."); | |
beneficiary = _beneficiary; | |
emit PermissionsModified(_beneficiary, RoleChange.MADE_BENEFICIARY); | |
return beneficiary; | |
} | |
function addAdmin(address _admin) | |
public | |
adminOnly | |
returns(address) | |
{ | |
admins[_admin] = true; | |
moderators[_admin] = true; | |
emit PermissionsModified(_admin, RoleChange.PROMOTED_TO_ADMIN); | |
return _admin; | |
} | |
function removeAdmin(address _admin) | |
public | |
adminOnly | |
addressMustNotBeFounder(_admin) | |
returns(address) | |
{ | |
require(_admin != msg.sender, "You cannot remove yourself from the admin role."); | |
delete admins[_admin]; | |
emit PermissionsModified(_admin, RoleChange.DEMOTED_TO_MODERATOR); | |
return _admin; | |
} | |
function addModerator(address _moderator) | |
public | |
adminOnly | |
returns(address) | |
{ | |
moderators[_moderator] = true; | |
emit PermissionsModified(_moderator, RoleChange.PROMOTED_TO_MODERATOR); | |
return _moderator; | |
} | |
function removeModerator(address _moderator) | |
public | |
adminOnly | |
addressMustNotBeFounder(_moderator) | |
addressMustNotBeAdmin(_moderator) | |
returns(address) | |
{ | |
require(_moderator != msg.sender, "You cannot remove yourself from the moderator role."); | |
delete moderators[_moderator]; | |
emit PermissionsModified(_moderator, RoleChange.KICKED_FROM_TEAM); | |
return _moderator; | |
} | |
function ban(address _ban) | |
public | |
moderatorOnly | |
addressMustNotBeFounder(_ban) | |
addressMustNotBeAdmin(_ban) | |
addressMustNotBeModerator(_ban) | |
addressMustNotBeBeneficiary(_ban) | |
returns(address) | |
{ | |
bannedAddresses[_ban] = true; | |
emit PermissionsModified(_ban, RoleChange.BANNED); | |
return _ban; | |
} | |
function unban(address _ban) | |
public | |
moderatorOnly | |
returns(address) | |
{ | |
bannedAddresses[_ban] = false; | |
emit PermissionsModified(_ban, RoleChange.UNBANNED); | |
return _ban; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment