diff --git a/source/contracts/IController.sol b/source/contracts/IController.sol index 4c77b3f22..df39a0c52 100644 --- a/source/contracts/IController.sol +++ b/source/contracts/IController.sol @@ -10,4 +10,5 @@ contract IController { function onlyInEmergency() public view returns(bool); function getAugur() public view returns (IAugur); function getTimestamp() public view returns (uint256); + function emergencyStop() public returns (bool); } diff --git a/source/contracts/external/EscapeHatchController.sol b/source/contracts/external/EscapeHatchController.sol new file mode 100644 index 000000000..ae508789f --- /dev/null +++ b/source/contracts/external/EscapeHatchController.sol @@ -0,0 +1,23 @@ +pragma solidity 0.4.20; + +import 'IController.sol'; +import 'libraries/Ownable.sol'; + + +contract EscapeHatchController is Ownable { + IController public controller; + + function setController(IController _controller) public onlyOwner returns (bool) { + controller = _controller; + return true; + } + + function emergencyStop() public onlyOwner returns (bool) { + controller.emergencyStop(); + return true; + } + + function onTransferOwnership(address, address) internal returns (bool) { + return true; + } +} \ No newline at end of file diff --git a/tests/test_escape_hatch_controller.py b/tests/test_escape_hatch_controller.py new file mode 100644 index 000000000..3c97a70aa --- /dev/null +++ b/tests/test_escape_hatch_controller.py @@ -0,0 +1,23 @@ +from ethereum.tools import tester +from ethereum.tools.tester import TransactionFailed +from utils import captureFilteredLogs, bytesToHexString, AssertLog, TokenDelta +from pytest import raises, fixture + +def test_escape_hatch_controller(contractsFixture, universe, controller): + escapeHatchController = contractsFixture.upload('external/EscapeHatchController.sol') + assert escapeHatchController.setController(controller.address) + assert escapeHatchController.controller() == controller.address + assert escapeHatchController.getOwner() == bytesToHexString(tester.a0) + + # transfer ownership of controller to the escape hatch controller + assert controller.transferOwnership(escapeHatchController.address) + assert controller.owner() == escapeHatchController.address + + # Pull escape hatch + assert escapeHatchController.emergencyStop() + assert controller.stopped() + + +@fixture +def controller(contractsFixture, kitchenSinkSnapshot): + return contractsFixture.contracts['Controller']