Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .soliumrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"error-reason": "error",
"max-len": "error",
"no-trailing-whitespace": "error",
"blank-lines": "error"
"blank-lines": "error",
"custom-errors": "off"
}
}
65 changes: 65 additions & 0 deletions contracts/bridging/ColonyShell.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: GPL-3.0-or-later
/*
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.8.25;
pragma experimental ABIEncoderV2;

import { BasicMetaTransaction } from "./../common/BasicMetaTransaction.sol";
import { CallWithGuards } from "../common/CallWithGuards.sol";
import { DSAuth } from "./../../lib/dappsys/auth.sol";
import { ERC20Extended } from "./../common/ERC20Extended.sol";
import { Multicall } from "./../common/Multicall.sol";
import { IColonyNetwork } from "./../colonyNetwork/IColonyNetwork.sol";

contract ColonyShell is DSAuth, BasicMetaTransaction, Multicall, CallWithGuards {
// Address of the Resolver contract used by EtherRouter for lookups and routing
address resolver; // Storage slot 2 (from DSAuth there is authority and owner at storage slots 0 and 1 respectively)

mapping(address => uint256) metatransactionNonces;

function getMetatransactionNonce(address _user) public view override returns (uint256 _nonce) {
return metatransactionNonces[_user];
}

function incrementMetatransactionNonce(address _user) internal override {
metatransactionNonces[_user] += 1;
}

// Events

event ColonyFundsClaimed(address token, uint256 balance);
event TransferMade(address token, address user, uint256 amount);

// Public functions

function claimColonyShellFunds(address _token) public {
uint256 balance = (_token == address(0x0))
? address(this).balance
: ERC20Extended(_token).balanceOf(address(this));

IColonyNetwork(owner).sendClaimColonyShellFunds(_token, balance);

emit ColonyFundsClaimed(_token, balance);
}

function transfer(address _token, address _user, uint256 _amount) public auth {
require(ERC20Extended(_token).transfer(_user, _amount), "colony-shell-transfer-failed");

emit TransferMade(_token, _user, _amount);
}
}
12 changes: 12 additions & 0 deletions contracts/colony/ColonyFunding.sol
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ contract ColonyFunding is
emit ColonyFundsClaimed(msgSender(), _token, feeToPay, remainder);
}

function claimColonyShellFunds(address _token, uint256 _balance) public stoppable {
uint256 toClaim = (_balance - nonRewardPotsTotal[_token]) - fundingPots[0].balance[_token];
uint256 feeToPay = toClaim / getRewardInverse(); // ignore-swc-110
uint256 remainder = toClaim - feeToPay;

nonRewardPotsTotal[_token] += remainder;
fundingPots[1].balance[_token] += remainder;
fundingPots[0].balance[_token] += feeToPay;

emit ColonyFundsClaimed(msgSender(), _token, feeToPay, remainder);
}

function getNonRewardPotsTotal(address _token) public view returns (uint256) {
return nonRewardPotsTotal[_token];
}
Expand Down
6 changes: 6 additions & 0 deletions contracts/colony/IColony.sol
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,12 @@ interface IColony is ColonyDataTypes, IRecovery, IBasicMetaTransaction, IMultica
/// @param _token Address of the token, `0x0` value indicates Ether
function claimColonyFunds(address _token) external;

/// @notice Move any funds received by the shell colony in `_token` denomination to the top-level domain pot,
/// siphoning off a small amount to the reward pot. If called against a colony's own token, no fee is taken.
/// @param _token Address of the token, `0x0` value indicates Ether
/// @param _balance Balance of the token held by the shell colony
function claimColonyShellFunds(address _token, uint256 _balance) external;

/// @notice Get the total amount of tokens `_token` minus amount reserved to be paid to the reputation and token holders as rewards.
/// @param _token Address of the token, `0x0` value indicates Ether
/// @return amount Total amount of tokens in funding pots other than the rewards pot (id 0)
Expand Down
9 changes: 9 additions & 0 deletions contracts/colonyNetwork/ColonyNetworkDeployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ contract ColonyNetworkDeployer is ColonyNetworkStorage {
return (address(token), colonyAddress);
}

function createColonyShell(bytes32 _salt) public onlyColonyBridge {
ICreateX(CREATEX_ADDRESS).deployCreate3AndInit(
_salt,
type(EtherRouterCreate3).creationCode,
abi.encodeWithSignature("setOwner(address)", (address(this))),
ICreateX.Values(0, 0)
);
}

/**
* @dev Generates pseudo-randomly a salt value using a diverse selection of block and
* transaction properties.
Expand Down
71 changes: 71 additions & 0 deletions contracts/colonyNetwork/ColonyNetworkShells.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// SPDX-License-Identifier: GPL-3.0-or-later
/*
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.8.25;
pragma experimental ABIEncoderV2;

import { IColony } from "./../colony/IColony.sol";
import { Multicall } from "./../common/Multicall.sol";
import { ColonyNetworkStorage } from "./ColonyNetworkStorage.sol";
import { ColonyShell } from "./../bridging/ColonyShell.sol";

contract ColonyNetworkShells is ColonyNetworkStorage, Multicall {
// To shells

function sendDeployColonyShell(bytes32 _salt) public calledByColony{
bytes memory payload = abi.encodeWithSignature(
"deployColonyShell(bytes32)",
_salt
);

require(callThroughBridgeWithGuards(payload), "colony-network-shell-deploy-failed");
}

function colonyShellTransfer(address _colony, address _token, address _user, uint256 _amount) public onlyColonyBridge {
ColonyShell(_colony).transfer(_token, _user, _amount);
}

function sendColonyShellTransfer(address _token, address _user, uint256 _amount) public calledByColony{
bytes memory payload = abi.encodeWithSignature(
"colonyShellTransfer(address,address,address,uint256)",
msgSender(),
_token,
_user,
_amount
);

require(callThroughBridgeWithGuards(payload), "colony-network-shell-transfer-failed");
}

// From shells

function claimColonyShellFunds(address _colony, address _token, uint256 _balance) public onlyColonyBridge {
IColony(_colony).claimColonyShellFunds(_token, _balance);
}

function sendClaimColonyShellFunds(address _token, uint256 _balance) public calledByColony{
bytes memory payload = abi.encodeWithSignature(
"claimColonyShellFunds(address,address,uint256)",
msgSender(),
_token,
_balance
);

require(callThroughBridgeWithGuards(payload), "colony-network-shell-claim-failed");
}
}
19 changes: 1 addition & 18 deletions contracts/colonyNetwork/ColonyNetworkSkills.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import "./ColonyNetworkStorage.sol";
import { IColonyBridge } from "./../bridging/IColonyBridge.sol";
import { CallWithGuards } from "../common/CallWithGuards.sol";

contract ColonyNetworkSkills is ColonyNetworkStorage, Multicall, CallWithGuards {
contract ColonyNetworkSkills is ColonyNetworkStorage, Multicall {
// Skills

function addSkill(
Expand Down Expand Up @@ -502,21 +502,4 @@ contract ColonyNetworkSkills is ColonyNetworkStorage, Multicall, CallWithGuards
}
return _reputation;
}

function callThroughBridgeWithGuards(bytes memory payload) internal returns (bool) {
bytes memory bridgePayload = abi.encodeWithSignature(
"sendMessage(uint256,bytes)",
getAndCacheReputationMiningChainId(),
payload
);

(bool success, bytes memory returnData) = callWithGuards(colonyBridgeAddress, bridgePayload);

// If the function call was a success, and it returned true
if (success) {
bool res = abi.decode(returnData, (bool));
return res;
}
return false;
}
}
20 changes: 19 additions & 1 deletion contracts/colonyNetwork/ColonyNetworkStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ import { CommonStorage } from "./../common/CommonStorage.sol";
import { MultiChain } from "./../common/MultiChain.sol";
import { ERC20Extended } from "./../common/ERC20Extended.sol";
import { ColonyNetworkDataTypes } from "./ColonyNetworkDataTypes.sol";
import { CallWithGuards } from "../common/CallWithGuards.sol";

// ignore-file-swc-131
// ignore-file-swc-108

contract ColonyNetworkStorage is ColonyNetworkDataTypes, DSMath, CommonStorage, MultiChain {
contract ColonyNetworkStorage is ColonyNetworkDataTypes, DSMath, CommonStorage, MultiChain, CallWithGuards {
// Number of colonies in the network
uint256 colonyCount; // Storage slot 6
// uint256 version number of the latest deployed Colony contract, used in creating new colonies
Expand Down Expand Up @@ -216,4 +217,21 @@ contract ColonyNetworkStorage is ColonyNetworkDataTypes, DSMath, CommonStorage,
}
return reputationMiningChainId;
}

function callThroughBridgeWithGuards(bytes memory payload) internal returns (bool) {
bytes memory bridgePayload = abi.encodeWithSignature(
"sendMessage(uint256,bytes)",
getAndCacheReputationMiningChainId(),
payload
);

(bool success, bytes memory returnData) = callWithGuards(colonyBridgeAddress, bridgePayload);

// If the function call was a success, and it returned true
if (success) {
bool res = abi.decode(returnData, (bool));
return res;
}
return false;
}
}
5 changes: 5 additions & 0 deletions contracts/colonyNetwork/IColonyNetwork.sol
Original file line number Diff line number Diff line change
Expand Up @@ -626,4 +626,9 @@ interface IColonyNetwork is ColonyNetworkDataTypes, IRecovery, IBasicMetaTransac
/// @param _chainId The chainId the update was bridged from
/// @param _colony The colony being queried
function addPendingReputationUpdate(uint256 _chainId, address _colony) external;

/// @notice Send the claimFunds transaction from the shell to the colony
/// @param _token The token being held by the shell
/// @param _balance The shell's current balance of the token
function sendClaimColonyShellFunds(address _token, uint256 _balance) external;
}
13 changes: 13 additions & 0 deletions docs/interfaces/icolony.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,19 @@ Move any funds received by the colony in `_token` denomination to the top-level
|_token|address|Address of the token, `0x0` value indicates Ether


### ▸ `claimColonyShellFunds(address _token, uint256 _balance)`

Move any funds received by the shell colony in `_token` denomination to the top-level domain pot, siphoning off a small amount to the reward pot. If called against a colony's own token, no fee is taken.


**Parameters**

|Name|Type|Description|
|---|---|---|
|_token|address|Address of the token, `0x0` value indicates Ether
|_balance|uint256|Balance of the token held by the shell colony


### ▸ `claimExpenditurePayout(uint256 _id, uint256 _slot, address _token)`

Claim the payout for an expenditure slot. Here the network receives a fee from each payout.
Expand Down
13 changes: 13 additions & 0 deletions docs/interfaces/icolonynetwork.md
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,19 @@ Used to track that a user is eligible to claim a reward
|_amount|uint256|The amount of CLNY to be awarded


### ▸ `sendClaimColonyShellFunds(address _token, uint256 _balance)`

Send the claimFunds transaction from the shell to the colony


**Parameters**

|Name|Type|Description|
|---|---|---|
|_token|address|The token being held by the shell
|_balance|uint256|The shell's current balance of the token


### ▸ `setColonyBridgeAddress(address _bridgeAddress)`

Called to set the address of the colony bridge contract
Expand Down
3 changes: 2 additions & 1 deletion helpers/upgradable-contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ exports.setupUpgradableColonyNetwork = async function setupUpgradableColonyNetwo
colonyNetworkENS,
colonyNetworkExtensions,
colonyNetworkSkills,
colonyNetworkShells,
contractRecovery,
) {
const deployedImplementations = {};
Expand All @@ -139,9 +140,9 @@ exports.setupUpgradableColonyNetwork = async function setupUpgradableColonyNetwo
deployedImplementations.ColonyNetworkMining = colonyNetworkMining.address;
deployedImplementations.ColonyNetworkAuction = colonyNetworkAuction.address;
deployedImplementations.ColonyNetworkENS = colonyNetworkENS.address;
deployedImplementations.ColonyNetworkSkills = colonyNetworkSkills.address;
deployedImplementations.ColonyNetworkExtensions = colonyNetworkExtensions.address;
deployedImplementations.ColonyNetworkSkills = colonyNetworkSkills.address;
deployedImplementations.ColonyNetworkShells = colonyNetworkShells.address;
deployedImplementations.ContractRecovery = contractRecovery.address;

await exports.setupEtherRouter("colonyNetwork", "IColonyNetwork", deployedImplementations, resolver);
Expand Down
6 changes: 6 additions & 0 deletions test/truffle-fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const ColonyNetworkAuction = artifacts.require("ColonyNetworkAuction");
const ColonyNetworkENS = artifacts.require("ColonyNetworkENS");
const ColonyNetworkExtensions = artifacts.require("ColonyNetworkExtensions");
const ColonyNetworkSkills = artifacts.require("ColonyNetworkSkills");
const ColonyNetworkShells = artifacts.require("ColonyNetworkShells");
const IColonyNetwork = artifacts.require("IColonyNetwork");

const ENSRegistry = artifacts.require("ENSRegistry");
Expand Down Expand Up @@ -129,6 +130,9 @@ async function deployContracts() {
const colonyNetworkSkills = await ColonyNetworkSkills.new();
ColonyNetworkSkills.setAsDeployed(colonyNetworkSkills);

const colonyNetworkShells = await ColonyNetworkShells.new();
ColonyNetworkShells.setAsDeployed(colonyNetworkShells);

const reputationMiningCycle = await ReputationMiningCycle.new();
ReputationMiningCycle.setAsDeployed(reputationMiningCycle);

Expand All @@ -149,6 +153,7 @@ async function setupColonyNetwork() {
const colonyNetworkENS = await ColonyNetworkENS.deployed();
const colonyNetworkExtensions = await ColonyNetworkExtensions.deployed();
const colonyNetworkSkills = await ColonyNetworkSkills.deployed();
const colonyNetworkShells = await ColonyNetworkShells.deployed();
// const etherRouter = await EtherRouter.deployed();
const resolver = await Resolver.deployed();
const contractRecovery = await ContractRecovery.deployed();
Expand Down Expand Up @@ -184,6 +189,7 @@ async function setupColonyNetwork() {
colonyNetworkENS,
colonyNetworkExtensions,
colonyNetworkSkills,
colonyNetworkShells,
contractRecovery,
);

Expand Down