diff --git a/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPIncreaseCoreTimelockDelayAction.sol b/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPIncreaseCoreTimelockDelayAction.sol new file mode 100644 index 000000000..aec11c0b0 --- /dev/null +++ b/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPIncreaseCoreTimelockDelayAction.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import "../../governance/UpdateCoreTimelockDelayAction.sol"; +import "../../address-registries/L2AddressRegistry.sol"; + +///@notice Increase core timelock day to eight days. +/// For discussion / rationale, see https://forum.arbitrum.foundation/t/rfc-constitutional-aip-security-council-improvement-proposal/20541 +contract AIPIncreaseCoreTimelockDelayAction is UpdateCoreTimelockDelayAction { + constructor() + UpdateCoreTimelockDelayAction( + ICoreGovTimelockGetter(0x56C4E9Eb6c63aCDD19AeC2b1a00e4f0d7aBda9d3), + 8 days + ) + {} +} diff --git a/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPIncreaseNonEmergencySCThresholdAction.sol b/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPIncreaseNonEmergencySCThresholdAction.sol new file mode 100644 index 000000000..71cee407d --- /dev/null +++ b/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPIncreaseNonEmergencySCThresholdAction.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import "../../governance/SetSCThresholdAction.sol"; + +///@notice increase the non-emergency Security Council Threshold from 7 to 9. +/// For discussion / rationale, see https://forum.arbitrum.foundation/t/rfc-constitutional-aip-security-council-improvement-proposal/20541 +contract AIPIncreaseNonEmergencySCThresholdAction is SetSCThresholdAction { + constructor() + SetSCThresholdAction(IGnosisSafe(0xADd68bCb0f66878aB9D37a447C7b9067C5dfa941), 7, 9) + {} +} diff --git a/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPRemoveNonEmergencySCAction.sol b/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPRemoveNonEmergencySCAction.sol new file mode 100644 index 000000000..42a785bcb --- /dev/null +++ b/src/gov-action-contracts/AIPs/SCImprovementAIP/AIPRemoveNonEmergencySCAction.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import "../../../security-council-mgmt/interfaces/ISecurityCouncilManager.sol"; +import "../../../interfaces/ICoreTimelock.sol"; + +///@notice Effectively "remove" the non emergency security council; prevent it from proposing in the timelock and don't update it in security council elections +/// For discussion / rationale, see https://forum.arbitrum.foundation/t/rfc-constitutional-aip-security-council-improvement-proposal/20541 +contract AIPRemoveNonEmergencySCAction { + ISecurityCouncilManager public constant securityCouncilManager = + ISecurityCouncilManager(0xD509E5f5aEe2A205F554f36E8a7d56094494eDFC); + ICoreTimelock public constant timelock = + ICoreTimelock(0x34d45e99f7D8c45ed05B5cA72D54bbD1fb3F98f0); + address nonEmergecySC = 0xADd68bCb0f66878aB9D37a447C7b9067C5dfa941; + + function perform() external { + // revoke SC's role on timelock + timelock.revokeRole(timelock.PROPOSER_ROLE(), nonEmergecySC); + + // remove SC from elections + securityCouncilManager.removeSecurityCouncil( + SecurityCouncilData({ + securityCouncil: nonEmergecySC, + updateAction: 0x9BF7b8884Fa381a45f8CB2525905fb36C996297a, + chainId: 42_161 + }) + ); + } +} diff --git a/src/gov-action-contracts/governance/SetSCThresholdAction.sol b/src/gov-action-contracts/governance/SetSCThresholdAction.sol new file mode 100644 index 000000000..c13287f92 --- /dev/null +++ b/src/gov-action-contracts/governance/SetSCThresholdAction.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import "../../security-council-mgmt/interfaces/IGnosisSafe.sol"; + +interface _IGnosisSafe { + function changeThreshold(uint256 _threshold) external; +} + +///@notice Set the minimum signing threshold for a security council gnosis safe. Assumes that the safe has the UpgradeExecutor added as a module. +contract SetSCThresholdAction { + IGnosisSafe public immutable gnosisSafe; + uint256 public immutable oldThreshold; + uint256 public immutable newThreshold; + + constructor(IGnosisSafe _gnosisSafe, uint256 _oldThreshold, uint256 _newThreshold) { + gnosisSafe = _gnosisSafe; + oldThreshold = _oldThreshold; + newThreshold = _newThreshold; + } + + function perform() external { + // sanity check old threshold + require( + gnosisSafe.getThreshold() == oldThreshold, "SecSCThresholdAction: WRONG_OLD_THRESHOLD" + ); + + gnosisSafe.execTransactionFromModule({ + to: address(gnosisSafe), + value: 0, + data: abi.encodeWithSelector(_IGnosisSafe.changeThreshold.selector, newThreshold), + operation: OpEnum.Operation.Call + }); + // sanity check new threshold was set + require( + gnosisSafe.getThreshold() == newThreshold, "SecSCThresholdAction: NEW_THRESHOLD_NOT_SET" + ); + } +} diff --git a/src/gov-action-contracts/governance/UpdateCoreTimelockDelayAction.sol b/src/gov-action-contracts/governance/UpdateCoreTimelockDelayAction.sol new file mode 100644 index 000000000..cb2f913e9 --- /dev/null +++ b/src/gov-action-contracts/governance/UpdateCoreTimelockDelayAction.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.16; + +import "../address-registries/L2AddressRegistry.sol"; + +///@notice Update core timelock delay — the minimum amount of time after a passed-proposal is queued before it can be executed. +contract UpdateCoreTimelockDelayAction { + IArbitrumTimelock public immutable timelock; + uint256 public immutable newDelay; + + constructor(ICoreGovTimelockGetter _l2AddressRegistry, uint256 _newDelay) { + timelock = _l2AddressRegistry.coreGovTimelock(); + newDelay = _newDelay; + } + + function perform() external { + timelock.updateDelay(newDelay); + // sanity check: + require(timelock.getMinDelay() == newDelay, "UpdateTimelockDelayAction: DELAY_NOT_SET"); + } +}