Skip to content

Commit

Permalink
Introduce Korporatio extension WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
kronosapiens committed Mar 1, 2023
1 parent ba3a875 commit 5ace2e1
Show file tree
Hide file tree
Showing 5 changed files with 477 additions and 0 deletions.
198 changes: 198 additions & 0 deletions contracts/extensions/Korporatio.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
This file is part of The Colony Network.
The Colony Network is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The Colony Network is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with The Colony Network. If not, see <http://www.gnu.org/licenses/>.
*/

pragma solidity 0.7.3;
pragma experimental ABIEncoderV2;

import "./../../lib/dappsys/erc20.sol";
import "./../colonyNetwork/IColonyNetwork.sol";
import "./ColonyExtensionMeta.sol";

// ignore-file-swc-108


contract Korporatio is ColonyExtensionMeta {

// Constants

// Events

event StakeSubmitted(uint256 indexed stakeId, address indexed staker);
event StakeCancelled(uint256 indexed stakeId);
event StakeReclaimed(uint256 indexed stakeId);
event StakeSlashed(uint256 indexed stakeId);

// Data structures

struct Stake {
address staker;
uint256 amount;
uint256 cancelledAt;
}

// Storage

address colonyNetworkAddress;
uint256 stakeFraction;
uint256 claimDelay;

uint256 numStakes;
mapping (uint256 => Stake) stakes;

// Modifiers

modifier onlyRootArchitect() {
require(
colony.hasUserRole(msgSender(), 1, ColonyDataTypes.ColonyRole.Architecture),
"ux-gate-caller-not-root-architect"
);
_;
}

// Overrides

/// @notice Returns the identifier of the extension
function identifier() public override pure returns (bytes32) {
return keccak256("Korporatio");
}

/// @notice Returns the version of the extension
function version() public override pure returns (uint256) {
return 1;
}

/// @notice Configures the extension
/// @param _colony The colony in which the extension holds permissions
function install(address _colony) public override auth {
require(address(colony) == address(0x0), "extension-already-installed");

colony = IColony(_colony);
colonyNetworkAddress = colony.getColonyNetwork();
}

/// @notice Called when upgrading the extension
function finishUpgrade() public override auth {}

/// @notice Called when deprecating (or undeprecating) the extension
function deprecate(bool _deprecated) public override auth {
deprecated = _deprecated;
}

/// @notice Called when uninstalling the extension
function uninstall() public override auth {
selfdestruct(address(uint160(address(colony))));
}

// Public

function setStakeFraction(uint256 _stakeFraction) public onlyRootArchitect {
stakeFraction = _stakeFraction;
}

function setClaimDelay(uint256 _claimDelay) public onlyRootArchitect {
claimDelay = _claimDelay;
}

function submitStake(
bytes memory _colonyKey,
bytes memory _colonyValue,
uint256 _colonyBranchMask,
bytes32[] memory _colonySiblings,
bytes memory _userKey,
bytes memory _userValue,
uint256 _userBranchMask,
bytes32[] memory _userSiblings
)
public
notDeprecated
{
bytes32 rootHash = IColonyNetwork(colonyNetworkAddress).getReputationRootHash();
uint256 rootSkillId = colony.getDomain(1).skillId;

uint256 colonyReputation = checkReputation(rootHash, rootSkillId, address(0x0), _colonyKey, _colonyValue, _colonyBranchMask, _colonySiblings);
uint256 userReputation = checkReputation(rootHash, rootSkillId, msgSender(), _userKey, _userValue, _userBranchMask, _userSiblings);

uint256 requiredStake = wmul(colonyReputation, stakeFraction);
require(userReputation >= requiredStake, "ux-gate-insufficient-rep");

stakes[++numStakes] = Stake({
staker: msgSender(),
amount: requiredStake,
cancelledAt: UINT256_MAX
});

colony.obligateStake(msgSender(), 1, requiredStake);

emit StakeSubmitted(numStakes, msgSender());
}

function cancelStake(uint256 _stakeId) public {
require(stakes[_stakeId].staker == msgSender(), "ux-gate-cannot-cancel");

stakes[_stakeId].cancelledAt = block.timestamp;

emit StakeCancelled(_stakeId);
}

function reclaimStake(uint256 _stakeId) public {
Stake storage stake = stakes[_stakeId];
require(stake.cancelledAt + claimDelay <= block.timestamp, "ux-gate-cannot-reclaim");

uint256 stakeAmount = stake.amount;
colony.deobligateStake(msgSender(), 1, stakeAmount);

delete stakes[_stakeId];

emit StakeReclaimed(_stakeId);
}

function slashStake(uint256 _stakeId, bool _punish) public {
require(stakes[_stakeId].amount > 0, "ux-gate-cannot-slash");

require(
colony.hasInheritedUserRole(msgSender(), 1, ColonyDataTypes.ColonyRole.Arbitration, UINT256_MAX, 1),
"staked-expenditure-caller-not-arbitration"
);

address staker = stakes[_stakeId].staker;
uint256 amount = stakes[_stakeId].amount;
delete stakes[_stakeId];

colony.transferStake(1, UINT256_MAX, address(this), staker, 1, amount, address(0x0));
if (_punish) { colony.emitDomainReputationPenalty(1, UINT256_MAX, 1, staker, -int256(amount)); }

emit StakeSlashed(_stakeId);
}

// View

function getNumStakes() external view returns (uint256) {
return numStakes;
}

function getStakeFraction() external view returns (uint256) {
return stakeFraction;
}

function getClaimDelay() external view returns (uint256) {
return claimDelay;
}

function getStake(uint256 _id) external view returns (Stake memory stake) {
return stakes[_id];
}
}
2 changes: 2 additions & 0 deletions migrations/9_setup_extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const VotingReputation = artifacts.require("./VotingReputation");
const VotingReputationMisalignedRecovery = artifacts.require("./VotingReputationMisalignedRecovery");
const TokenSupplier = artifacts.require("./TokenSupplier");
const Whitelist = artifacts.require("./Whitelist");
const Korporatio = artifacts.require("./Korporatio");

const Resolver = artifacts.require("./Resolver");
const EtherRouter = artifacts.require("./EtherRouter");
Expand Down Expand Up @@ -53,4 +54,5 @@ module.exports = async function (deployer, network, accounts) {
await addExtension(colonyNetwork, "TokenSupplier", "TokenSupplier", [TokenSupplier]);
await addExtension(colonyNetwork, "IVotingReputation", "VotingReputation", [VotingReputation, VotingReputationMisalignedRecovery]);
await addExtension(colonyNetwork, "Whitelist", "Whitelist", [Whitelist]);
await addExtension(colonyNetwork, "Korporatio", "Korporatio", [Korporatio]);
};
1 change: 1 addition & 0 deletions scripts/check-recovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ walkSync("./contracts/").forEach((contractName) => {
"contracts/extensions/EvaluatedExpenditure.sol",
"contracts/extensions/StakedExpenditure.sol",
"contracts/extensions/FundingQueue.sol",
"contracts/extensions/Korporatio.sol",
"contracts/extensions/OneTxPayment.sol",
"contracts/extensions/ReputationBootstrapper.sol",
"contracts/extensions/StreamingPayments.sol",
Expand Down
1 change: 1 addition & 0 deletions scripts/check-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ walkSync("./contracts/").forEach((contractName) => {
"contracts/extensions/FundingQueue.sol",
"contracts/extensions/ColonyExtension.sol",
"contracts/extensions/ColonyExtensionMeta.sol",
"contracts/extensions/Korporatio.sol",
"contracts/extensions/OneTxPayment.sol",
"contracts/extensions/ReputationBootstrapper.sol",
"contracts/extensions/StreamingPayments.sol",
Expand Down
Loading

0 comments on commit 5ace2e1

Please sign in to comment.