Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Extended PM with permission owner and delegation capabilities #604

Open
wants to merge 91 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
7d338df
Extended PM with permission manager/owner and delegation capabilites
nivida Aug 28, 2024
7876fd5
error handling improved
nivida Aug 28, 2024
45fef46
PR comments and more applied
nivida Aug 29, 2024
6e97176
PM.removeOwner fixed
nivida Aug 29, 2024
9a9ebce
added missing counter++ in pm._createPermission and renamed onlyPermi…
nivida Aug 29, 2024
503f6e1
missing comments to the events declarations added
nivida Aug 29, 2024
3b76ccc
modifier comment added for ownerAuth and other comments improved
nivida Aug 29, 2024
a1f81f1
correct initial bitmap defined in PM._createPermission
nivida Aug 29, 2024
75cc4f5
applyTarget methods updated to have a ROOT fallback
nivida Aug 29, 2024
e136441
allowedContract removed
nivida Aug 29, 2024
afc4fb7
PM._isPermissionFrozen updated
nivida Aug 29, 2024
0819fc5
codestyle++
nivida Aug 29, 2024
916df92
apply target method efficiently
novaknole Aug 29, 2024
dfc2e4e
merge conflict fixed
novaknole Aug 29, 2024
19e2104
correct error type for PM.applyMultiTargetPermissions
nivida Aug 29, 2024
92581ba
root+owner case added to PM.ownerAuth
nivida Aug 29, 2024
228fb10
owner permission check clean up
nivida Aug 29, 2024
3f14f95
ownerAuth clean up
nivida Aug 29, 2024
0af5955
passing of the Operation does simplify ownerAuth
nivida Aug 29, 2024
0eb4e29
codestyle++
nivida Aug 29, 2024
836af08
missing zero flag check added
nivida Aug 29, 2024
99e7046
_checkOwner optimized for the case when the permission isnt created a…
nivida Aug 29, 2024
beeba1b
further efficiency improvements for PM._checkOwner
nivida Aug 29, 2024
8b183ed
obviously not needed if removed
nivida Aug 29, 2024
bef54c8
error types cleaned up
nivida Aug 29, 2024
4272435
checkOwner if inverted.. looks cleaner
nivida Aug 29, 2024
e9d11dd
remove extra check
novaknole Aug 29, 2024
b647372
counters equal to 1 instead of ++
novaknole Aug 29, 2024
4b66659
not required var removed in ownerAuth modifier
nivida Aug 29, 2024
9393e16
assertions with error types updated for permission-manager.ts
nivida Aug 30, 2024
38d6b39
_flags argument removed from ownerAuth cause it is no longer in usage
nivida Aug 30, 2024
6b54964
PM fixes and test cases added for PM.grant
nivida Sep 2, 2024
5c06c3c
missing expectation added to PM.grant test cases
nivida Sep 2, 2024
b8b9940
test cases for grantWithCondition added
nivida Sep 2, 2024
67aff37
revoke test cases extended
nivida Sep 2, 2024
f707b69
undelegate cases added
nivida Sep 2, 2024
67b7b12
PM applyTarget methods updated and related test cases extended
nivida Sep 3, 2024
4fbc63f
PM.addOwner fixed
nivida Sep 3, 2024
8609cf1
tests added for PM.addOwner
nivida Sep 3, 2024
600d129
PM.removeOwner test cases added
nivida Sep 3, 2024
e6c717c
prettier run
nivida Sep 3, 2024
4254ecb
codestyle PM tests
nivida Sep 3, 2024
e0c6bee
storage gap updated from 49 to 48
nivida Sep 3, 2024
e861691
PM.createPermission test cases added
nivida Sep 4, 2024
9c7751d
delegatePermission test cases added
nivida Sep 4, 2024
748fe35
undelegatePermission test cases added
nivida Sep 4, 2024
767f940
codestyle++
nivida Sep 4, 2024
0766c95
PM.createPermission test improved
nivida Sep 5, 2024
ab11975
PM.hasPermission renamed to _checkFlags and defined as private
nivida Sep 5, 2024
c62666c
apply target methods updated
nivida Sep 9, 2024
798bd66
permissionId updated in reverted error of plugin setup processor test…
nivida Sep 9, 2024
0dd7d63
not requried 'permHash' removed from delegations mapping
nivida Sep 9, 2024
9d85d81
Revert "permissionId updated in reverted error of plugin setup proces…
nivida Sep 9, 2024
1c793dc
Options enum removed and hardcoded flag values replaced with related …
nivida Sep 9, 2024
74e06e3
setAllowedContract added
nivida Sep 9, 2024
693161c
prettier run
nivida Sep 9, 2024
dd1b061
revert checks in plugin setup processor test cases updated for new pe…
nivida Sep 9, 2024
22feda8
test for apply singlle target updated for allowedContract case
nivida Sep 9, 2024
a98f8a5
clean up
nivida Sep 9, 2024
8984904
Feature/dao execute bruteforce approach (#607)
novaknole Sep 9, 2024
2a6783b
apply target method grantee fixed
novaknole Sep 10, 2024
88fc14c
unsafe allow delegatecall
novaknole Sep 10, 2024
3614f38
DAO.execute fixed and test cases added for it
nivida Sep 10, 2024
afe70be
add tests and fixes to dao (#608)
novaknole Sep 16, 2024
e688034
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
d0a83db
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
46c191a
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
cead54b
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
154eb40
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
6abaebf
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
c6479de
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
cc44e88
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
0b10859
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
0ceabf1
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
ab63589
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
dccda8a
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
d3a9978
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
10fd26b
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
ae3fa2d
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
bd934f4
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
352f8a2
Update packages/contracts/src/core/permission/PermissionManager.sol
novaknole Sep 17, 2024
921c2fb
fix typo
novaknole Sep 17, 2024
aaa72fc
ownerAuth as internal virtual function
novaknole Sep 17, 2024
8c658ea
add natspec for struct permission:
novaknole Sep 17, 2024
b1932bf
fix more tests and cleaner
novaknole Sep 17, 2024
4ec5af9
fix more tests and cleaner (#609)
novaknole Sep 17, 2024
d8109f1
Feature/fix and improve tests (#610)
clauBv23 Sep 24, 2024
fc06bff
conflicts fixed
novaknole Sep 24, 2024
b981a6f
Feature/fix apply methods (#611)
novaknole Sep 25, 2024
0e070da
executor interface (#612)
novaknole Sep 27, 2024
c5d8db6
fix tests and typechain + loop (#613)
novaknole Sep 29, 2024
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
14 changes: 13 additions & 1 deletion packages/contracts/hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ import '@openzeppelin/hardhat-upgrades';
import * as dotenv from 'dotenv';
import 'hardhat-deploy';
import 'hardhat-gas-reporter';
import {extendEnvironment, HardhatUserConfig} from 'hardhat/config';
import {extendEnvironment, HardhatUserConfig, task} from 'hardhat/config';
import type {NetworkUserConfig} from 'hardhat/types';
import 'solidity-coverage';
import 'solidity-docgen';
import util from 'util';

dotenv.config();

const exec = util.promisify(require('child_process').exec);

const ETH_KEY = process.env.ETH_KEY;
const accounts = ETH_KEY ? ETH_KEY.split(',') : [];

Expand Down Expand Up @@ -53,6 +56,15 @@ extendEnvironment(hre => {
hre.testingFork = testingFork;
});

// Needed to override and extend in order to make coverage work with typechain
// Without this, it doesn't generate typechains the way we want with custom scripts.
task('coverage').setAction(async (args, hre, runSuper) => {
await exec('yarn typechain:osx');
await exec('yarn typechain:osx-versions');

await runSuper();
});

const ENABLE_DEPLOY_TEST = process.env.TEST_UPDATE_DEPLOY_SCRIPT !== undefined;

console.log('Is deploy test is enabled: ', ENABLE_DEPLOY_TEST);
Expand Down
7 changes: 6 additions & 1 deletion packages/contracts/scripts/generate-typechain-osx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ async function generateTypechain(): Promise<void> {
}

const dirPath = path.dirname(filePath);
if (!excludedDirs.has(dirPath)) {

// Only arrange the contracts' paths in the current
// directory without previous versions.
const containsPrefix = Array.from(excludedDirs).some(prefix => dirPath.startsWith(prefix));

if (!containsPrefix) {
jsonFiles.push(filePath);
}
});
Expand Down
91 changes: 77 additions & 14 deletions packages/contracts/src/core/dao/DAO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {ProtocolVersion} from "@aragon/osx-commons-contracts/src/utils/versionin
import {VersionComparisonLib} from "@aragon/osx-commons-contracts/src/utils/versioning/VersionComparisonLib.sol";
import {hasBit, flipBit} from "@aragon/osx-commons-contracts/src/utils/math/BitMap.sol";
import {IDAO} from "@aragon/osx-commons-contracts/src/dao/IDAO.sol";
import {IExecutor, Action} from "@aragon/osx-commons-contracts/src/executors/IExecutor.sol";

import {PermissionManager} from "../permission/PermissionManager.sol";
import {CallbackHandler} from "../utils/CallbackHandler.sol";
Expand All @@ -28,12 +29,14 @@ import {IEIP4824} from "./IEIP4824.sol";
/// @notice This contract is the entry point to the Aragon DAO framework and provides our users a simple and easy to use public interface.
/// @dev Public API of the Aragon DAO framework.
/// @custom:security-contact sirt@aragon.org
/// @custom:oz-upgrades-unsafe-allow constructor constructor delegatecall
contract DAO is
IEIP4824,
Initializable,
IERC1271,
ERC165StorageUpgradeable,
IDAO,
IExecutor,
UUPSUpgradeable,
ProtocolVersion,
PermissionManager,
Expand Down Expand Up @@ -117,6 +120,9 @@ contract DAO is
/// @notice Thrown when a function is removed but left to not corrupt the interface ID.
error FunctionRemoved();

/// @notice Thrown when initialize is called after it has already been executed.
error AlreadyInitialized();

/// @notice Emitted when a new DAO URI is set.
/// @param daoURI The new URI.
event NewURI(string daoURI);
Expand All @@ -134,8 +140,16 @@ contract DAO is
_reentrancyStatus = _NOT_ENTERED;
}

/// @notice This ensures that the initialize function cannot be called during the upgrade process.
modifier onlyCallAtInitialization() {
if (_getInitializedVersion() != 0) {
revert AlreadyInitialized();
}

_;
}

/// @notice Disables the initializers on the implementation contract to prevent it from being left uninitialized.
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}
Expand All @@ -155,10 +169,14 @@ contract DAO is
address _initialOwner,
address _trustedForwarder,
string calldata daoURI_
) external reinitializer(3) {
) external onlyCallAtInitialization reinitializer(3) {
_reentrancyStatus = _NOT_ENTERED; // added in v1.3.0

// In addition to the current interfaceId, also support previous version of the interfaceId.
_registerInterface(type(IDAO).interfaceId ^ IExecutor.execute.selector);

_registerInterface(type(IDAO).interfaceId);
_registerInterface(type(IExecutor).interfaceId);
_registerInterface(type(IERC1271).interfaceId);
_registerInterface(type(IEIP4824).interfaceId);
_registerInterface(type(IProtocolVersion).interfaceId); // added in v1.3.0
Expand Down Expand Up @@ -198,6 +216,9 @@ contract DAO is
_who: address(this),
_permissionId: keccak256("SET_SIGNATURE_VALIDATOR_PERMISSION")
});

_registerInterface(type(IDAO).interfaceId);
_registerInterface(type(IExecutor).interfaceId);
}
}

Expand Down Expand Up @@ -246,18 +267,12 @@ contract DAO is
_setMetadata(_metadata);
}

/// @inheritdoc IDAO
/// @inheritdoc IExecutor
function execute(
bytes32 _callId,
Action[] calldata _actions,
uint256 _allowFailureMap
)
external
override
nonReentrant
auth(EXECUTE_PERMISSION_ID)
returns (bytes[] memory execResults, uint256 failureMap)
{
) external override nonReentrant returns (bytes[] memory execResults, uint256 failureMap) {
// Check that the action array length is within bounds.
if (_actions.length > MAX_ACTIONS) {
revert TooManyActions();
Expand All @@ -268,14 +283,62 @@ contract DAO is
uint256 gasBefore;
uint256 gasAfter;

bool hasExecutePermission = isGranted(
address(this),
msg.sender,
EXECUTE_PERMISSION_ID,
msg.data
);

for (uint256 i = 0; i < _actions.length; ) {
Action calldata action = _actions[i];

bool isAllowed = hasExecutePermission;
bytes32 permissionId = EXECUTE_PERMISSION_ID;

// TODO: do we want to have some special way to allow registering permission for `transfer` out of this contract ?
// This could be useful as there's no function selector for such scenario and currently, to do transfer, EXECUTE_PERMISSION
// is enough, but it could be desirable that some special permission is created and even if member has EXECUTE, still won't be able
// to execute withdraw action.
if (action.data.length >= 4) {
bytes32 id = keccak256(action.data[:4]);
Permission storage targetPermission = permissions[permissionHash(action.to, id)];

if (targetPermission.created) {
isAllowed = isGranted(action.to, msg.sender, id, action.data);
permissionId = id;
}
}

if (!isAllowed) {
revert Unauthorized(action.to, msg.sender, permissionId);
}

bool success;
bytes memory data;

gasBefore = gasleft();

(bool success, bytes memory result) = _actions[i].to.call{value: _actions[i].value}(
_actions[i].data
);
(success, data) = _actions[i].to.call{value: _actions[i].value}(_actions[i].data);

gasAfter = gasleft();

if (_actions[i].to == address(this)) {
if (!success) {
bytes4 result;

assembly {
result := mload(add(data, 32))
}

if (result == Unauthorized.selector || result == UnauthorizedOwner.selector) {
gasBefore = gasleft();
(success, data) = _actions[i].to.delegatecall(_actions[i].data);
gasAfter = gasleft();
}
}
}

// Check if failure is allowed
if (!hasBit(_allowFailureMap, uint8(i))) {
// Check if the call failed.
Expand All @@ -297,7 +360,7 @@ contract DAO is
}
}

execResults[i] = result;
execResults[i] = data;

unchecked {
++i;
Expand Down
Loading
Loading