-
-
Save AndreiMVP/63fe2376400ebb89ece633646aa8c625 to your computer and use it in GitHub Desktop.
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.8.18; | |
interface IProofOfHumanity { | |
function isHuman(address _account) external view returns (bool); | |
function isClaimed(bytes20 _humanityId) external view returns (bool); | |
function humanityOf(address _account) external view returns (bytes20); | |
function boundTo(bytes20 _humanityId) external view returns (address); | |
} | |
interface ERC20 { | |
function transfer(address _to, uint256 _value) external returns (bool success); | |
function approve(address _spender, uint256 _value) external returns (bool success); | |
function transferFrom( | |
address _from, | |
address _to, | |
uint256 _value | |
) external returns (bool success); | |
} | |
interface IGCT is ERC20 { | |
function addDelegatedTrustee(address _member) external; | |
function addMemberToken(address _member) external; | |
function removeMemberToken(address _member) external; | |
function mintDelegate( | |
address _trustedBy, | |
address _collateral, | |
uint256 _amount | |
) external returns (uint256); | |
} | |
interface Token is ERC20 { | |
function owner() external view returns (address); | |
} | |
interface IHub { | |
function organizationSignup() external; | |
function userToToken(address) external returns (address); | |
function tokenToUser(address) external returns (address); | |
function trust(address, uint256) external; | |
function transferThrough( | |
address[] memory tokenOwners, | |
address[] memory srcs, | |
address[] memory dests, | |
uint256[] memory wads | |
) external; | |
} | |
/** @title PoHGroupCirclesCurrencyManager | |
* @dev Is GCT Owner | |
* @dev Is GCT treasury | |
* @dev Is Organization in hub? | |
*/ | |
contract PoHGroupCirclesCurrencyManager { | |
// ========== STORAGE ========== | |
address public governor; | |
IProofOfHumanity public poh; | |
IGCT public gct; | |
IHub public hub; | |
mapping(bytes20 => address) public humanityIdToToken; | |
mapping(address => bytes20) public tokenToHumanityId; | |
mapping(address => bool) public removedMember; | |
// ========== CONSTRUCTOR ========== | |
constructor( | |
address _poh, | |
address _gct, | |
address _hub | |
) { | |
governor = msg.sender; | |
poh = IProofOfHumanity(_poh); | |
gct = IGCT(_gct); | |
hub = IHub(_hub); | |
} | |
// ========== ACCESS ========== | |
modifier onlyGovernor() { | |
require(msg.sender == governor, "!governor"); | |
_; | |
} | |
// ========== GOVERNANCE ========== | |
function changeGovernor(address _governor) external onlyGovernor { | |
governor = _governor; | |
} | |
function changePoH(address _poh) external onlyGovernor { | |
poh = IProofOfHumanity(_poh); | |
} | |
function changeGCT(address _gct) external onlyGovernor { | |
gct = IGCT(_gct); | |
} | |
function changeHub(address _hub) external onlyGovernor { | |
hub = IHub(_hub); | |
} | |
function setup() external onlyGovernor { | |
hub.organizationSignup(); | |
gct.addDelegatedTrustee(address(this)); | |
} | |
// Trust must be called by this contract (as a delegate) on Hub | |
function trust(address _trustee) external onlyGovernor { | |
hub.trust(_trustee, 100); | |
} | |
function executeGovernorTx(address _destination, bytes memory _data) external onlyGovernor { | |
(bool success, ) = _destination.call(_data); | |
require(success, "!call"); | |
} | |
// ========== FUNCTIONS ========== | |
/** | |
* In order to add member to group 2 calls are needed, in order: | |
* - first from wallet owning the token `confirmToken` confirming the humanityId | |
* - second from wallet registered on PoH `confirmHuman` confirming the token | |
* | |
* Once humanityIdToToken[humanityId] == tokenToHumanityId[token], | |
* member is added to group. Token to humanity correspondence | |
* can't be changed anymore. | |
*/ | |
function confirmToken(bytes20 _humanityId) external { | |
address token = address(hub.userToToken(msg.sender)); | |
require(token != address(0x0), "!hub"); | |
require(humanityIdToToken[_humanityId] == address(0x0), "member!"); | |
tokenToHumanityId[token] = _humanityId; | |
} | |
function confirmHuman(address _token) external { | |
bytes20 humanityId = poh.humanityOf(msg.sender); | |
require(humanityId != bytes20(0x0), "!poh"); | |
require(tokenToHumanityId[_token] == humanityId, "!token"); | |
humanityIdToToken[humanityId] = _token; | |
gct.addMemberToken(_token); | |
} | |
/** | |
* Remove member from group. Member can be added back with `addMemberBack`. | |
* Can be removed by the owner of the pohId or by anyone if the pohId is | |
* not bound anyomre to any address. | |
* It is marked as removed in | |
*/ | |
function removeMember(bytes20 _humanityId) external { | |
address pohAccount = poh.boundTo(_humanityId); | |
if (pohAccount != address(0x0)) require(pohAccount == msg.sender, "!remove"); | |
address member = humanityIdToToken[_humanityId]; | |
removedMember[member] = true; | |
gct.removeMemberToken(member); | |
} | |
function addMemberBack() external { | |
bytes20 humanityId = poh.humanityOf(msg.sender); | |
require(humanityId != bytes20(0x0), "!poh"); | |
require(removedMember[humanityIdToToken[humanityId]], "!removed"); | |
address member = humanityIdToToken[humanityId]; | |
removedMember[member] = false; | |
gct.addMemberToken(member); | |
} | |
/** | |
* Minting is done is gct contract. | |
* Burning in order to redeem other tokens is done here. | |
*/ | |
function redeem(address _collateral, uint256 _wad) external { | |
_redeem(msg.sender, _collateral, _wad); | |
} | |
function redeem(address _redeemer, address _collateral, uint256 _wad) external { | |
_redeem(_redeemer, _collateral, _wad); | |
} | |
function redeemMany(address _redeemer, address[] memory _collateral, uint256[] memory _wads) external { | |
for (uint256 i = 0; i < _collateral.length; i++) { | |
_redeem(_redeemer, _collateral[i], _wads[i]); | |
} | |
} | |
function _redeem( | |
address _redeemer, | |
address _collateral, | |
uint256 _wad | |
) internal { | |
bytes20 humanityId = tokenToHumanityId[_collateral]; | |
require(poh.isClaimed(humanityId), "!poh"); | |
require(gct.transferFrom(_redeemer, address(0x0), _wad), "!burn"); | |
Token(_collateral).transfer(_redeemer, _wad); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment