Skip to content

Commit

Permalink
Deployment script and setups
Browse files Browse the repository at this point in the history
  • Loading branch information
brickpop committed Apr 18, 2024
1 parent 9393bd0 commit 9b95aa5
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 81 deletions.
32 changes: 19 additions & 13 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ import {IDAO} from "@aragon/osx/core/dao/IDAO.sol";
import {DAO} from "@aragon/osx/core/dao/DAO.sol";
import {createERC1967Proxy} from "@aragon/osx/utils/Proxy.sol";

uint16 constant MIN_EMERGENCY_APPROVALS = 11;
uint16 constant MIN_STD_APPROVALS = 7;

contract Deploy is Script {
DAO daoImplementation;
Multisig multisigImplementation;
Expand All @@ -33,6 +30,9 @@ contract Deploy is Script {
address tokenAddress;
address[] multisigMembers;

uint16 minStdApprovals;
uint16 minEmergencyApprovals;

address lzAppEndpoint;

constructor() {
Expand All @@ -50,6 +50,10 @@ contract Deploy is Script {
pluginRepoFactory = vm.envAddress("PLUGIN_REPO_FACTORY");
tokenAddress = vm.envAddress("TOKEN_ADDRESS");

minStdApprovals = uint16(vm.envUint("MIN_STD_APPROVALS"));
minEmergencyApprovals = uint16(vm.envUint("MIN_EMERGENCY_APPROVALS"));

// JSON list of members
string memory root = vm.projectRoot();
string memory path = string.concat(root, "/utils/members.json");
string memory json = vm.readFile(path);
Expand All @@ -75,15 +79,11 @@ contract Deploy is Script {
IPluginSetup.PreparedSetupData memory preparedSetupData2
) = prepareEmergencyMultisig(dao);

address[] memory proposerPlugins = new address[](2);
proposerPlugins[0] = p1;
proposerPlugins[1] = p2;

(
address p3,
PluginRepo pr3,
IPluginSetup.PreparedSetupData memory preparedSetupData3
) = prepareOptimisticTokenVoting(dao, proposerPlugins);
) = prepareOptimisticTokenVoting(dao, p1, p2);

// Apply installations
dao.grant(
Expand Down Expand Up @@ -174,7 +174,7 @@ contract Deploy is Script {
multisigMembers,
Multisig.MultisigSettings(
true, // onlyListed
MIN_STD_APPROVALS // minAppovals
minStdApprovals // minAppovals
),
lzAppEndpoint
);
Expand Down Expand Up @@ -221,7 +221,7 @@ contract Deploy is Script {
multisigMembers,
Multisig.MultisigSettings(
true, // onlyListed
MIN_EMERGENCY_APPROVALS // minAppovals
minEmergencyApprovals // minAppovals
),
lzAppEndpoint
);
Expand All @@ -245,7 +245,8 @@ contract Deploy is Script {

function prepareOptimisticTokenVoting(
DAO dao,
address[] memory _allowedProposerPlugins
address stdProposer,
address emergencyProposer
)
internal
returns (address, PluginRepo, IPluginSetup.PreparedSetupData memory)
Expand All @@ -269,7 +270,11 @@ contract Deploy is Script {
// Plugin settings
OptimisticTokenVotingPlugin.OptimisticGovernanceSettings
memory votingSettings = OptimisticTokenVotingPlugin
.OptimisticGovernanceSettings(200000, 60 * 60 * 24 * 4, 0);
.OptimisticGovernanceSettings(
200000, // minVetoRatio - 20%
0, // minDuration (the condition will enforce it)
0 // minProposerVotingPower
);

OptimisticTokenVotingPluginSetup.TokenSettings
memory tokenSettings = OptimisticTokenVotingPluginSetup
Expand All @@ -284,7 +289,8 @@ contract Deploy is Script {
votingSettings,
tokenSettings,
mintSettings,
_allowedProposerPlugins,
stdProposer,
emergencyProposer,
lzAppEndpoint
);

Expand Down
45 changes: 42 additions & 3 deletions src/conditions/StandardProposalCondition.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,24 @@ pragma solidity ^0.8.17;

import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {IPermissionCondition} from "@aragon/osx/core/permission/IPermissionCondition.sol";
import {IDAO} from "@aragon/osx/core/dao/IDAO.sol";
import {OptimisticTokenVotingPlugin} from "../OptimisticTokenVotingPlugin.sol";
// import {PermissionCondition} from "@aragon/osx/core/permission/PermissionCondition.sol";

/// @title PermissionCondition
/// @author Aragon Association - 2023
/// @notice An abstract contract for non-upgradeable contracts instantiated via the `new` keyword to inherit from to support customary permissions depending on arbitrary on-chain state.
abstract contract StandardProposalCondition is ERC165, IPermissionCondition {
contract StandardProposalCondition is ERC165, IPermissionCondition {
address dao;
address targetPlugin;
uint256 minDelay;

constructor(address _dao, address _targetPlugin, uint256 _minDelay) {
dao = _dao;
targetPlugin = _targetPlugin;
minDelay = _minDelay;
}

/// @notice Checks if an interface is supported by this or its parent contract.
/// @param _interfaceId The ID of the interface.
/// @return Returns `true` if the interface is supported.
Expand All @@ -27,7 +39,34 @@ abstract contract StandardProposalCondition is ERC165, IPermissionCondition {
bytes32 _permissionId,
bytes calldata _data
) external view returns (bool isPermitted) {
// TODO
return false;
(_where, _who, _permissionId);

// Is it createProposal()?
if (
_getSelector(_data) !=
OptimisticTokenVotingPlugin.createProposal.selector
) {
return false;
}

// Decode proposal params
(, , , uint64 _startDate, uint64 _endDate) = abi.decode(
_data[4:],
(bytes, IDAO.Action[], uint256, uint64, uint64)
);
if (_endDate <= _startDate) return false;
else if (_endDate - _startDate < minDelay) return false;

return true;
}

function _getSelector(
bytes memory _data
) internal pure returns (bytes4 selector) {
// Slices are only supported for bytes calldata, not bytes memory
// Bytes memory requires an assembly block
assembly {
selector := mload(add(_data, 0x20)) // 32
}
}
}
17 changes: 0 additions & 17 deletions src/setup/EmergencyMultisigPluginSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,6 @@ contract EmergencyMultisigPluginSetup is PluginSetup {
multisigBase.UPGRADE_PLUGIN_PERMISSION_ID()
);

// Grant `EXECUTE_PERMISSION` of the DAO to the plugin.
permissions[2] = PermissionLib.MultiTargetPermission(
PermissionLib.Operation.Grant,
_dao,
plugin,
PermissionLib.NO_CONDITION,
DAO(payable(_dao)).EXECUTE_PERMISSION_ID()
);

preparedSetupData.permissions = permissions;
}

Expand Down Expand Up @@ -122,14 +113,6 @@ contract EmergencyMultisigPluginSetup is PluginSetup {
PermissionLib.NO_CONDITION,
multisigBase.UPGRADE_PLUGIN_PERMISSION_ID()
);

permissions[2] = PermissionLib.MultiTargetPermission(
PermissionLib.Operation.Revoke,
_dao,
_payload.plugin,
PermissionLib.NO_CONDITION,
DAO(payable(_dao)).EXECUTE_PERMISSION_ID()
);
}

/// @inheritdoc IPluginSetup
Expand Down
17 changes: 0 additions & 17 deletions src/setup/MultisigPluginSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,6 @@ contract MultisigPluginSetup is PluginSetup {
multisigBase.UPGRADE_PLUGIN_PERMISSION_ID()
);

// Grant `EXECUTE_PERMISSION` of the DAO to the plugin.
permissions[2] = PermissionLib.MultiTargetPermission(
PermissionLib.Operation.Grant,
_dao,
plugin,
PermissionLib.NO_CONDITION,
DAO(payable(_dao)).EXECUTE_PERMISSION_ID()
);

preparedSetupData.permissions = permissions;
}

Expand Down Expand Up @@ -123,14 +114,6 @@ contract MultisigPluginSetup is PluginSetup {
PermissionLib.NO_CONDITION,
multisigBase.UPGRADE_PLUGIN_PERMISSION_ID()
);

permissions[2] = PermissionLib.MultiTargetPermission(
PermissionLib.Operation.Revoke,
_dao,
_payload.plugin,
PermissionLib.NO_CONDITION,
DAO(payable(_dao)).EXECUTE_PERMISSION_ID()
);
}

/// @inheritdoc IPluginSetup
Expand Down
71 changes: 40 additions & 31 deletions src/setup/OptimisticLzVotingPluginSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import {GovernanceERC20} from "@aragon/osx/token/ERC20/governance/GovernanceERC2
import {GovernanceWrappedERC20} from "@aragon/osx/token/ERC20/governance/GovernanceWrappedERC20.sol";
import {IGovernanceWrappedERC20} from "@aragon/osx/token/ERC20/governance/IGovernanceWrappedERC20.sol";
import {OptimisticLzVotingPlugin} from "../OptimisticLzVotingPlugin.sol";
import {StandardProposalCondition} from "../conditions/StandardProposalCondition.sol";

uint64 constant MIN_DELAY = 60 * 60 * 24 * 7 * 2;

/// @title OptimisticLzVotingPluginSetup
/// @author Aragon Association - 2022-2023
Expand Down Expand Up @@ -57,9 +60,6 @@ contract OptimisticLzVotingPluginSetup is PluginSetup {
/// @param length The array length of passed helpers.
error WrongHelpersArrayLength(uint256 length);

/// @notice Thrown when trying to prepare an installation with no proposers.
error NoProposers();

/// @notice The contract constructor deploying the plugin implementation contract and receiving the governance token base contracts to clone from.
/// @param _governanceERC20Base The base `GovernanceERC20` contract to create clones from.
/// @param _governanceWrappedERC20Base The base `GovernanceWrappedERC20` contract to create clones from.
Expand Down Expand Up @@ -88,14 +88,11 @@ contract OptimisticLzVotingPluginSetup is PluginSetup {
TokenSettings memory tokenSettings,
// only used for GovernanceERC20 (when token is not passed)
GovernanceERC20.MintSettings memory mintSettings,
address[] memory proposers,
address stdProposer,
address emergencyProposer,
OptimisticLzVotingPlugin.BridgeSettings memory _lzAppEndpoint
) = decodeInstallationParams(_installParameters);

if (proposers.length == 0) {
revert NoProposers();
}

address token = tokenSettings.addr;

// Prepare helpers.
Expand Down Expand Up @@ -162,9 +159,7 @@ contract OptimisticLzVotingPluginSetup is PluginSetup {
// Prepare permissions
PermissionLib.MultiTargetPermission[]
memory permissions = new PermissionLib.MultiTargetPermission[](
tokenSettings.addr != address(0x0)
? 3 + proposers.length
: 4 + proposers.length
tokenSettings.addr != address(0) ? 5 : 6
);

// Request the permissions to be granted
Expand Down Expand Up @@ -198,28 +193,37 @@ contract OptimisticLzVotingPluginSetup is PluginSetup {
permissionId: DAO(payable(_dao)).EXECUTE_PERMISSION_ID()
});

// Proposers can create proposals
for (uint256 i = 0; i < proposers.length; ) {
permissions[3 + i] = PermissionLib.MultiTargetPermission({
operation: PermissionLib.Operation.Grant,
where: plugin,
who: proposers[i],
condition: PermissionLib.NO_CONDITION,
permissionId: optimisticTokenVotingPluginBase
.PROPOSER_PERMISSION_ID()
});
// Deploy the Std proposal condition
StandardProposalCondition stdProposalCondition = new StandardProposalCondition(
address(_dao),
address(plugin),
MIN_DELAY
);

unchecked {
i++;
}
}
// Proposer plugins can create proposals
permissions[3] = PermissionLib.MultiTargetPermission({
operation: PermissionLib.Operation.Grant,
where: plugin,
who: stdProposer,
condition: address(stdProposalCondition),
permissionId: optimisticTokenVotingPluginBase
.PROPOSER_PERMISSION_ID()
});
permissions[4] = PermissionLib.MultiTargetPermission({
operation: PermissionLib.Operation.Grant,
where: plugin,
who: emergencyProposer,
condition: PermissionLib.NO_CONDITION,
permissionId: optimisticTokenVotingPluginBase
.PROPOSER_PERMISSION_ID()
});

if (tokenSettings.addr == address(0x0)) {
bytes32 tokenMintPermission = GovernanceERC20(token)
.MINT_PERMISSION_ID();

// The DAO can mint ERC20 tokens
permissions[3 + proposers.length] = PermissionLib
permissions[5] = PermissionLib
.MultiTargetPermission({
operation: PermissionLib.Operation.Grant,
where: token,
Expand Down Expand Up @@ -317,15 +321,17 @@ contract OptimisticLzVotingPluginSetup is PluginSetup {
TokenSettings calldata _tokenSettings,
// only used for GovernanceERC20 (when a token is not passed)
GovernanceERC20.MintSettings calldata _mintSettings,
address[] calldata _proposers,
address _stdProposer,
address _emergencyProposer,
OptimisticLzVotingPlugin.BridgeSettings calldata _lzAppEndpoint
) external pure returns (bytes memory) {
return
abi.encode(
_votingSettings,
_tokenSettings,
_mintSettings,
_proposers,
_stdProposer,
_emergencyProposer,
_lzAppEndpoint
);
}
Expand All @@ -342,23 +348,26 @@ contract OptimisticLzVotingPluginSetup is PluginSetup {
TokenSettings memory tokenSettings,
// only used for GovernanceERC20 (when token is not passed)
GovernanceERC20.MintSettings memory mintSettings,
address[] memory proposers,
address _stdProposer,
address _emergencyProposer,
OptimisticLzVotingPlugin.BridgeSettings memory _lzAppEndpoint
)
{
(
votingSettings,
tokenSettings,
mintSettings,
proposers,
_stdProposer,
_emergencyProposer,
_lzAppEndpoint
) = abi.decode(
_data,
(
OptimisticLzVotingPlugin.OptimisticGovernanceSettings,
TokenSettings,
GovernanceERC20.MintSettings,
address[],
address,
address,
OptimisticLzVotingPlugin.BridgeSettings
)
);
Expand Down

0 comments on commit 9b95aa5

Please sign in to comment.