Skip to content

Commit bfbc31a

Browse files
authored
feat: use internal acl (#94)
1 parent 3497b95 commit bfbc31a

File tree

5 files changed

+47
-67
lines changed

5 files changed

+47
-67
lines changed

src/contracts/treasury/Collector.sol

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.0;
33

4+
import {AccessControlUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol';
5+
import {ReentrancyGuardUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/utils/ReentrancyGuardUpgradeable.sol';
46
import {ICollector} from './ICollector.sol';
57
import {IAccessControl} from '../dependencies/openzeppelin/contracts/IAccessControl.sol';
6-
import {ReentrancyGuard} from '../dependencies/openzeppelin/ReentrancyGuard.sol';
7-
import {VersionedInitializable} from '../misc/aave-upgradeability/VersionedInitializable.sol';
88
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
99
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
1010
import {Address} from '../dependencies/openzeppelin/contracts/Address.sol';
@@ -22,25 +22,19 @@ import {Address} from '../dependencies/openzeppelin/contracts/Address.sol';
2222
* - Same as with creation, on Sablier the `sender` and `recipient` can cancel a stream. Here, only fund admin and recipient
2323
* @author BGD Labs
2424
**/
25-
contract Collector is VersionedInitializable, ICollector, ReentrancyGuard {
25+
contract Collector is AccessControlUpgradeable, ReentrancyGuardUpgradeable, ICollector {
2626
using SafeERC20 for IERC20;
2727
using Address for address payable;
2828

2929
/*** Storage Properties ***/
30-
31-
/**
32-
* @notice Current revision of the contract.
33-
*/
34-
uint256 public constant REVISION = 6;
35-
3630
/// @inheritdoc ICollector
3731
address public constant ETH_MOCK_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
3832

3933
/// @inheritdoc ICollector
4034
bytes32 public constant FUNDS_ADMIN_ROLE = 'FUNDS_ADMIN';
4135

42-
/// @inheritdoc ICollector
43-
address public immutable ACL_MANAGER;
36+
// Reserved storage space to account for deprecated inherited storage
37+
uint256[53] private ______gap;
4438

4539
/**
4640
* @notice Counter for new stream ids.
@@ -83,33 +77,29 @@ contract Collector is VersionedInitializable, ICollector, ReentrancyGuard {
8377
_;
8478
}
8579

86-
constructor(address aclManager) {
87-
if (aclManager == address(0)) revert InvalidZeroAddress();
88-
ACL_MANAGER = aclManager;
80+
constructor() {
81+
_disableInitializers();
8982
}
9083

9184
/*** Contract Logic Starts Here */
9285

93-
/// @inheritdoc ICollector
94-
function initialize(uint256 nextStreamId) external virtual initializer {
86+
/** @notice Initializes the contracts
87+
* @param nextStreamId StreamId to set, applied if greater than 0
88+
* @param admin The default admin managing the FundsAdmins
89+
**/
90+
function initialize(uint256 nextStreamId, address admin) external virtual initializer {
91+
__AccessControl_init();
92+
__ReentrancyGuard_init();
93+
_grantRole(DEFAULT_ADMIN_ROLE, admin);
9594
if (nextStreamId != 0) {
9695
_nextStreamId = nextStreamId;
9796
}
98-
99-
_initGuard();
100-
_setFundsAdmin(fundsAdmin);
10197
}
10298

10399
/*** View Functions ***/
104-
105-
/// @inheritdoc VersionedInitializable
106-
function getRevision() internal pure override returns (uint256) {
107-
return REVISION;
108-
}
109-
110100
/// @inheritdoc ICollector
111101
function isFundsAdmin(address admin) external view returns (bool) {
112-
return IAccessControl(ACL_MANAGER).hasRole(FUNDS_ADMIN_ROLE, admin);
102+
return hasRole(FUNDS_ADMIN_ROLE, admin);
113103
}
114104

115105
/// @inheritdoc ICollector
@@ -214,7 +204,7 @@ contract Collector is VersionedInitializable, ICollector, ReentrancyGuard {
214204
}
215205

216206
function _onlyFundsAdmin() internal view returns (bool) {
217-
return IAccessControl(ACL_MANAGER).hasRole(FUNDS_ADMIN_ROLE, msg.sender);
207+
return hasRole(FUNDS_ADMIN_ROLE, msg.sender);
218208
}
219209

220210
struct CreateStreamLocalVars {

src/contracts/treasury/ICollector.sol

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,21 +119,11 @@ interface ICollector {
119119
**/
120120
function FUNDS_ADMIN_ROLE() external view returns (bytes32);
121121

122-
/**
123-
* @notice Address of the current ACL Manager.
124-
**/
125-
function ACL_MANAGER() external view returns (address);
126-
127122
/** @notice Returns the mock ETH reference address
128123
* @return address The address
129124
**/
130125
function ETH_MOCK_ADDRESS() external pure returns (address);
131126

132-
/** @notice Initializes the contracts
133-
* @param nextStreamId StreamId to set, applied if greater than 0
134-
**/
135-
function initialize(uint256 nextStreamId) external;
136-
137127
/**
138128
* @notice Checks if address is funds admin
139129
* @return bool If the address has the funds admin role

src/deployments/contracts/procedures/AaveV3SetupProcedure.sol

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ contract AaveV3SetupProcedure {
3636
address treasuryPartner;
3737
uint16 treasurySplitPercent;
3838
address proxyAdmin;
39-
address aclManager;
39+
address aclAdmin;
4040
bytes32 salt;
4141
}
4242

@@ -100,7 +100,7 @@ contract AaveV3SetupProcedure {
100100
treasuryPartner: config.treasuryPartner,
101101
treasurySplitPercent: config.treasurySplitPercent,
102102
proxyAdmin: proxyAdmin,
103-
aclManager: report.aclManager,
103+
aclAdmin: roles.poolAdmin,
104104
salt: config.salt
105105
})
106106
);
@@ -210,29 +210,27 @@ contract AaveV3SetupProcedure {
210210

211211
function _deployAaveV3Treasury(
212212
address deployedProxyAdmin,
213-
address aclManager,
213+
address aclAdmin,
214214
bytes32 salt
215215
) internal returns (address treasuryProxy, address treasuryImplementation) {
216216
if (salt != '') {
217-
treasuryImplementation = address(new Collector{salt: salt}(aclManager));
218-
Collector(treasuryImplementation).initialize(0);
217+
treasuryImplementation = address(new Collector{salt: salt}());
219218

220219
treasuryProxy = address(
221220
new TransparentUpgradeableProxy{salt: salt}(
222221
treasuryImplementation,
223222
ProxyAdmin(deployedProxyAdmin),
224-
abi.encodeWithSelector(Collector.initialize.selector, 100_000)
223+
abi.encodeWithSelector(Collector.initialize.selector, 100_000, aclAdmin)
225224
)
226225
);
227226
} else {
228-
treasuryImplementation = address(new Collector(aclManager));
229-
Collector(treasuryImplementation).initialize(0);
227+
treasuryImplementation = address(new Collector());
230228

231229
treasuryProxy = address(
232230
new TransparentUpgradeableProxy(
233231
treasuryImplementation,
234232
ProxyAdmin(deployedProxyAdmin),
235-
abi.encodeWithSelector(Collector.initialize.selector, 100_000)
233+
abi.encodeWithSelector(Collector.initialize.selector, 100_000, aclAdmin)
236234
)
237235
);
238236
}
@@ -247,7 +245,7 @@ contract AaveV3SetupProcedure {
247245
if (input.treasuryProxy == address(0)) {
248246
(treasuryProxy, treasuryImplementation) = _deployAaveV3Treasury(
249247
input.proxyAdmin,
250-
input.aclManager,
248+
input.aclAdmin,
251249
input.salt
252250
);
253251
} else {

tests/deployments/AaveV3PermissionsTest.t.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pragma solidity ^0.8.0;
33

44
import 'forge-std/Test.sol';
5+
import {IAccessControl} from 'openzeppelin-contracts/contracts/access/IAccessControl.sol';
56
import {Ownable} from '../../src/contracts/dependencies/openzeppelin/contracts/Ownable.sol';
67
import {IPoolAddressesProvider} from '../../src/contracts/interfaces/IPoolAddressesProvider.sol';
78
import '../../src/deployments/interfaces/IMarketReportTypes.sol';
@@ -305,7 +306,7 @@ contract AaveV3PermissionsTest is BatchTestProcedures {
305306
report.proxyAdmin,
306307
'Treasury proxy admin does not match with report.proxyAdmin'
307308
);
308-
assertEq(ICollector(report.treasury).ACL_MANAGER(), report.aclManager);
309+
assertEq(IAccessControl(report.treasury).hasRole(emptyBytes, roles.poolAdmin), true);
309310
}
310311
{
311312
address proxyAdminOwner = Ownable(report.proxyAdmin).owner();

tests/treasury/Collector.t.sol

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ pragma solidity ^0.8.0;
44
import {Test} from 'forge-std/Test.sol';
55
import {StdUtils} from 'forge-std/StdUtils.sol';
66

7-
import {IERC20} from 'src/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
8-
import {IAccessControl} from 'src/contracts/dependencies/openzeppelin/contracts/IAccessControl.sol';
9-
import {ACLManager} from 'src/contracts/protocol/configuration/ACLManager.sol';
10-
import {PoolAddressesProvider} from 'src/contracts/protocol/configuration/PoolAddressesProvider.sol';
11-
import {Collector} from 'src/contracts/treasury/Collector.sol';
12-
import {ICollector} from 'src/contracts/treasury/ICollector.sol';
7+
import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol';
8+
import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol';
9+
import {IERC20} from '../../src/contracts/dependencies/openzeppelin/contracts/IERC20.sol';
10+
import {IAccessControl} from '../../src/contracts/dependencies/openzeppelin/contracts/IAccessControl.sol';
11+
import {PoolAddressesProvider} from '../../src/contracts/protocol/configuration/PoolAddressesProvider.sol';
12+
import {Collector} from '../../src/contracts/treasury/Collector.sol';
13+
import {ICollector} from '../../src/contracts/treasury/ICollector.sol';
1314

1415
contract CollectorTest is StdUtils, Test {
1516
Collector public collector;
@@ -25,7 +26,7 @@ contract CollectorTest is StdUtils, Test {
2526

2627
uint256 public streamStartTime;
2728
uint256 public streamStopTime;
28-
uint256 public nextStreamID;
29+
uint256 public nextStreamID = 100_000;
2930

3031
event StreamIdChanged(uint256 indexed streamId);
3132
event CreateStream(
@@ -56,23 +57,29 @@ contract CollectorTest is StdUtils, Test {
5657
vm.prank(OWNER);
5758
provider.setACLAdmin(EXECUTOR_LVL_1);
5859

59-
ACLManager aclManager = new ACLManager(provider);
60-
6160
tokenA = IERC20(address(deployMockERC20('Token A', 'TK_A', 18)));
6261
tokenB = IERC20(address(deployMockERC20('Token B', 'TK_B', 6)));
6362

6463
streamStartTime = block.timestamp + 10;
6564
streamStopTime = block.timestamp + 70;
6665
nextStreamID = 0;
6766

68-
collector = new Collector(address(aclManager));
69-
collector.initialize(nextStreamID);
67+
address collectorImpl = address(new Collector());
68+
collector = Collector(
69+
address(
70+
new TransparentUpgradeableProxy(
71+
collectorImpl,
72+
new ProxyAdmin(address(this)), // mock proxy admin
73+
abi.encodeWithSelector(Collector.initialize.selector, nextStreamID, EXECUTOR_LVL_1)
74+
)
75+
)
76+
);
7077

7178
deal(address(tokenA), address(collector), 100 ether);
7279

7380
vm.startPrank(EXECUTOR_LVL_1);
74-
IAccessControl(address(aclManager)).grantRole(collector.FUNDS_ADMIN_ROLE(), FUNDS_ADMIN);
75-
IAccessControl(address(aclManager)).grantRole(collector.FUNDS_ADMIN_ROLE(), EXECUTOR_LVL_1);
81+
IAccessControl(address(collector)).grantRole(collector.FUNDS_ADMIN_ROLE(), FUNDS_ADMIN);
82+
IAccessControl(address(collector)).grantRole(collector.FUNDS_ADMIN_ROLE(), EXECUTOR_LVL_1);
7683
vm.stopPrank();
7784
}
7885

@@ -417,12 +424,6 @@ contract StreamsTest is CollectorTest {
417424
}
418425
}
419426

420-
contract GetRevision is CollectorTest {
421-
function test_successful() public view {
422-
assertEq(collector.REVISION(), 6);
423-
}
424-
}
425-
426427
contract FundsAdminRoleBytesTest is CollectorTest {
427428
function test_successful() public view {
428429
assertEq(collector.FUNDS_ADMIN_ROLE(), 'FUNDS_ADMIN');

0 commit comments

Comments
 (0)