DCIPs/assets/eip-6366/contracts/EIP6366Core.sol

189 lines
5.6 KiB
Solidity

// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.7;
import "./interfaces/IEIP6366Error.sol";
import "./interfaces/IEIP6366Core.sol";
/**
* @dev Implement the core of EIP-6366
*/
contract EIP6366Core is IEIP6366Core {
/**
* @dev Stored permission of an address
*/
mapping(address => uint256) private permissions;
/**
* @dev Stored delegation information
*/
mapping(bytes32 => uint256) private delegations;
/**
* @dev Transfer a subset of owning permission to a target address
* @param _to New permission owner's address
* @param _permission A subset of owning permission
*/
function transfer(
address _to,
uint256 _permission
) external virtual override returns (bool success) {
return _transfer(_to, _permission);
}
/**
* @dev Allowed a delegatee to act for permission owner's behalf
* @param _delegatee Delegatee address
* @param _permission A subset of permission
*/
function approve(
address _delegatee,
uint256 _permission
) external virtual override returns (bool success) {
return _approve(_delegatee, _permission);
}
/**
* @dev Get all owning permission of an address
* @param _owner Permission owner's address
*/
function permissionOf(
address _owner
) external view virtual override returns (uint256 permission) {
return _permissionOf(_owner);
}
/**
* @dev Checking the existance of required permission on a given permission set
* @param _required Required permission set
* @param _permission Checking permission set
*/
function permissionRequire(
uint256 _permission,
uint256 _required
) external view virtual override returns (bool isPermissioned) {
return _permissionRequire(_permission, _required);
}
/**
* @dev Checking if an actor has sufficient permission, by himself or from a delegation, on a given permission set
* @param _owner Permission owner's address
* @param _actor Actor's address
* @param _required Required permission set
*/
function hasPermission(
address _owner,
address _actor,
uint256 _required
) external view override returns (bool isPermissioned) {
return _hasPermission(_owner, _actor, _required);
}
/**
* @dev Get delegated permission that owner approved to delegatee
* @param _owner Permission owner's address
* @param _delegatee Delegatee's address
*/
function delegated(
address _owner,
address _delegatee
) external view virtual override returns (uint256 permission) {
return _delegated(_owner, _delegatee);
}
/**
* @dev Mint a new set of permission to a new owner
* @param _owner New permission owner
* @param _permission Permission
*/
function _mint(
address _owner,
uint256 _permission
) internal returns (bool) {
permissions[_owner] = _permission;
emit Transfer(address(0x0), _owner, _permission);
return true;
}
/**
* @dev Burn all permission of the owner
* @param _owner New permission owner
*/
function _burn(address _owner) internal returns (bool) {
emit Transfer(_owner, address(0x0), permissions[_owner]);
permissions[_owner] = 0;
return true;
}
/**
* @dev Create an unique key that linked permission owner and delegatee
* @param _owner Permission owner's address
* @param _delegatee Delegate's address
*/
function _uniqueKey(
address _owner,
address _delegatee
) private pure returns (bytes32) {
return keccak256(abi.encodePacked(_owner, _delegatee));
}
function _transfer(
address _to,
uint256 _permission
) internal returns (bool success) {
address owner = msg.sender;
// Prevent permission to be burnt
if (permissions[_to] & _permission > 0) {
revert IEIP6366Error.DuplicatedPermission(_permission);
}
// Clean subset of permission from owner
permissions[owner] = permissions[owner] ^ _permission;
// Set subset of permission to new owner
permissions[_to] = permissions[_to] | _permission;
emit Transfer(owner, _to, _permission);
return true;
}
function _approve(
address _delegatee,
uint256 _permission
) internal returns (bool success) {
address owner = msg.sender;
delegations[_uniqueKey(owner, _delegatee)] = _permission;
emit Approval(owner, _delegatee, _permission);
return true;
}
function _permissionOf(
address _owner
) internal view returns (uint256 permission) {
return permissions[_owner];
}
function _permissionRequire(
uint256 _permission,
uint256 _required
) internal pure returns (bool isPermissioned) {
return _required == _permission & _required;
}
function _hasPermission(
address _owner,
address _actor,
uint256 _required
) internal view returns (bool isPermissioned) {
return
_permissionRequire(
_permissionOf(_actor) | _delegated(_owner, _actor),
_required
);
}
function _delegated(
address _owner,
address _delegatee
) internal view returns (uint256 permission) {
// Delegated permission can't be the superset of owner's permission
return
delegations[_uniqueKey(_owner, _delegatee)] & permissions[_owner];
}
}