diff --git a/.soliumrc.json b/.soliumrc.json
index 450acbc769..712f0e541b 100644
--- a/.soliumrc.json
+++ b/.soliumrc.json
@@ -12,6 +12,7 @@
"error-reason": "error",
"max-len": "error",
"no-trailing-whitespace": "error",
- "blank-lines": "error"
+ "blank-lines": "error",
+ "custom-errors": "off"
}
}
diff --git a/contracts/bridging/ColonyShell.sol b/contracts/bridging/ColonyShell.sol
new file mode 100644
index 0000000000..02a2e5f49f
--- /dev/null
+++ b/contracts/bridging/ColonyShell.sol
@@ -0,0 +1,59 @@
+// 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 .
+*/
+
+pragma solidity 0.8.25;
+pragma experimental ABIEncoderV2;
+
+import { BasicMetaTransaction } from "./../common/BasicMetaTransaction.sol";
+import { CallWithGuards } from "../common/CallWithGuards.sol";
+import { ERC20Extended } from "./../common/ERC20Extended.sol";
+import { Multicall } from "./../common/Multicall.sol";
+import { IColonyNetwork } from "./../colonyNetwork/IColonyNetwork.sol";
+
+contract ColonyShell is 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;
+ }
+
+ // Public functions
+
+ function claimColonyFunds(address _token) public {
+ uint256 tokenBalance = (_token == address(0x0))
+ ? address(this).balance
+ : ERC20Extended(_token).balanceOf(address(this));
+
+ IColonyNetwork(owner).sendClaimColonyFunds(_token, tokenBalance);
+
+ emit ColonyFundsClaimed(_token, tokenBalance);
+ }
+
+ function transfer(address _token, address _user, uint256 _amount) public auth {
+ ERC20Extended(_token).transfer(_user, _amount);
+
+ emit PaymentMade(_token, _user, _amount);
+ }
+}
diff --git a/contracts/colonyNetwork/ColonyNetworkShells.sol b/contracts/colonyNetwork/ColonyNetworkShells.sol
new file mode 100644
index 0000000000..d7b46ade57
--- /dev/null
+++ b/contracts/colonyNetwork/ColonyNetworkShells.sol
@@ -0,0 +1,82 @@
+// 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 .
+*/
+
+pragma solidity 0.8.25;
+pragma experimental ABIEncoderV2;
+
+import { IColony } from "./../colony/IColony.sol";
+import { ICreateX } from "./../../lib/createx/src/ICreateX.sol";
+import { Multicall } from "./../common/Multicall.sol";
+import { CallWithGuards } from "./../common/CallWithGuards.sol";
+import { ColonyNetworkStorage } from "./ColonyNetworkStorage.sol";
+import { ColonyShell } from "./../briding/ColonyShell.sol";
+
+contract ColonyNetworkShells is ColonyNetworkStorage, Multicall, CallWithGuards {
+ // To shells
+
+ function deployColonyShell(bytes32 _salt) public onlyColonyBridge {
+ ICreateX(CREATEX_ADDRESS).deployCreate3AndInit(
+ _salt,
+ type(EtherRouterCreate3).creationCode,
+ abi.encodeWithSignature("setOwner(address)", (address(this))),
+ ICreateX.Values(0, 0)
+ );
+ }
+
+ function sendDeployColonyShell(bytes32 _salt) public onlyColony {
+ 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 onlyColony {
+ 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 onlyColony {
+ bytes memory payload = abi.encodeWithSignature(
+ "claimColonyShellFunds(address,address,uint256)",
+ msgSender(),
+ _token,
+ _balance
+ );
+
+ require(callThroughBridgeWithGuards(payload), "colony-network-shell-claim-failed");
+ }
+}