Skip to content
This repository was archived by the owner on May 9, 2024. It is now read-only.

Commit d88949e

Browse files
authored
Add renouceAdmin function (#592)
* Add renounceAdmin function to FeeHandlers * Add tests for renounceAdmin functions * Fix indentation
1 parent 9cd2120 commit d88949e

File tree

4 files changed

+105
-8
lines changed

4 files changed

+105
-8
lines changed

contracts/handlers/fee/BasicFeeHandler.sol

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ contract BasicFeeHandler is IFeeHandler, AccessControl {
3636
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
3737
}
3838

39+
/**
40+
@notice Removes admin role from {_msgSender()} and grants it to {newAdmin}.
41+
@notice Only callable by an address that currently has the admin role.
42+
@param newAdmin Address that admin role will be granted to.
43+
*/
44+
function renounceAdmin(address newAdmin) external onlyAdmin {
45+
address sender = _msgSender();
46+
require(sender != newAdmin, 'Cannot renounce oneself');
47+
grantRole(DEFAULT_ADMIN_ROLE, newAdmin);
48+
renounceRole(DEFAULT_ADMIN_ROLE, sender);
49+
}
50+
3951
/**
4052
@notice Collects fee for deposit.
4153
@param sender Sender of the deposit.

contracts/handlers/fee/FeeHandlerWithOracle.sol

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe {
2525

2626
struct OracleMessageType {
2727
// Base Effective Rate - effective rate between base currencies of source and dest networks (eg. MATIC/ETH)
28-
uint256 ber;
28+
uint256 ber;
2929
// Token Effective Rate - rate between base currency of destination network and token that is being trasferred (eg. MATIC/USDT)
3030
uint256 ter;
3131
uint256 dstGasPrice;
@@ -51,6 +51,18 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe {
5151

5252
// Admin functions
5353

54+
/**
55+
@notice Removes admin role from {_msgSender()} and grants it to {newAdmin}.
56+
@notice Only callable by an address that currently has the admin role.
57+
@param newAdmin Address that admin role will be granted to.
58+
*/
59+
function renounceAdmin(address newAdmin) external onlyAdmin {
60+
address sender = _msgSender();
61+
require(sender != newAdmin, 'Cannot renounce oneself');
62+
grantRole(DEFAULT_ADMIN_ROLE, newAdmin);
63+
renounceRole(DEFAULT_ADMIN_ROLE, sender);
64+
}
65+
5466
/**
5567
@notice Sets the fee oracle address for signature verification.
5668
@param oracleAddress Fee oracle address.
@@ -101,7 +113,7 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe {
101113
}
102114

103115
function _calculateFee(address sender, uint8 fromDomainID, uint8 destinationDomainID, bytes32 resourceID, bytes calldata depositData, bytes calldata feeData) internal view returns(uint256 fee, address tokenAddress) {
104-
/**
116+
/**
105117
Message:
106118
ber * 10^18: uint256
107119
ter * 10^18: uint256
@@ -120,7 +132,7 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe {
120132
121133
amount: uint256
122134
total: 321
123-
*/
135+
*/
124136

125137
require(feeData.length == 321, "Incorrect feeData length");
126138

@@ -132,9 +144,9 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe {
132144

133145
OracleMessageType memory oracleMessage = abi.decode(feeDataDecoded.message, (OracleMessageType));
134146
require(block.timestamp <= oracleMessage.expiresAt, "Obsolete oracle data");
135-
require((oracleMessage.fromDomainID == fromDomainID)
136-
&& (oracleMessage.toDomainID == destinationDomainID)
137-
&& (oracleMessage.resourceID == resourceID),
147+
require((oracleMessage.fromDomainID == fromDomainID)
148+
&& (oracleMessage.toDomainID == destinationDomainID)
149+
&& (oracleMessage.resourceID == resourceID),
138150
"Incorrect deposit params"
139151
);
140152

@@ -144,12 +156,12 @@ contract FeeHandlerWithOracle is IFeeHandler, AccessControl, ERC20Safe {
144156

145157
address tokenHandler = IBridge(_bridgeAddress)._resourceIDToHandlerAddress(resourceID);
146158
address tokenAddress = IERCHandler(tokenHandler)._resourceIDToTokenContractAddress(resourceID);
147-
159+
148160
// txCost = dstGasPrice * _gasUsed * Token Effective Rate (rate of dest base currency to token)
149161
uint256 txCost = oracleMessage.dstGasPrice * _gasUsed * oracleMessage.ter / 1e18;
150162

151163
fee = feeDataDecoded.amount * _feePercent / 1e4; // 100 for percent and 100 to avoid precision loss
152-
164+
153165
if (fee < txCost) {
154166
fee = txCost;
155167
}

test/handlers/fee/basic/admin.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* Copyright 2022 ChainSafe Systems
3+
* SPDX-License-Identifier: LGPL-3.0-only
4+
*/
5+
6+
const TruffleAssert = require("truffle-assertions");
7+
8+
const Helpers = require("../../../helpers");
9+
10+
const BasicFeeHandlerContract = artifacts.require("BasicFeeHandler");
11+
12+
contract("BasicFeeHandler - [admin]", async accounts => {
13+
const domainID = 1;
14+
const initialRelayers = accounts.slice(0, 3);
15+
const currentFeeHandlerAdmin = accounts[0];
16+
17+
const assertOnlyAdmin = (method, ...params) => {
18+
return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role");
19+
};
20+
21+
let BridgeInstance;
22+
let BasicFeeHandlerInstance;
23+
let ADMIN_ROLE;
24+
25+
beforeEach(async () => {
26+
BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]);
27+
BasicFeeHandlerInstance = await BasicFeeHandlerContract.new(BridgeInstance.address);
28+
29+
ADMIN_ROLE = await BasicFeeHandlerInstance.DEFAULT_ADMIN_ROLE();
30+
});
31+
32+
it("should set fee property", async () => {
33+
const fee = 3;
34+
assert.equal(await BasicFeeHandlerInstance._fee.call(), "0");
35+
await BasicFeeHandlerInstance.changeFee(fee);
36+
assert.equal(await BasicFeeHandlerInstance._fee.call(), fee);
37+
});
38+
39+
it("should require admin role to change fee property", async () => {
40+
const fee = 3;
41+
await assertOnlyAdmin(BasicFeeHandlerInstance.changeFee, fee);
42+
});
43+
44+
it('FeeHandlerWithOracle admin should be changed to expectedFeeHandlerWithOracleAdmin', async () => {
45+
const expectedFeeHandlerWithOracleAdmin = accounts[1];
46+
47+
// check current admin
48+
assert.isTrue(await BasicFeeHandlerInstance.hasRole(ADMIN_ROLE, currentFeeHandlerAdmin));
49+
50+
await TruffleAssert.passes(BasicFeeHandlerInstance.renounceAdmin(expectedFeeHandlerWithOracleAdmin))
51+
assert.isTrue(await BasicFeeHandlerInstance.hasRole(ADMIN_ROLE, expectedFeeHandlerWithOracleAdmin));
52+
53+
// check that former admin is no longer admin
54+
assert.isFalse(await BasicFeeHandlerInstance.hasRole(ADMIN_ROLE, currentFeeHandlerAdmin));
55+
});
56+
});

test/handlers/fee/withOracle/admin.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,21 @@
1212
contract("FeeHandlerWithOracle - [admin]", async accounts => {
1313
const domainID = 1;
1414
const initialRelayers = accounts.slice(0, 3);
15+
const currentFeeHandlerAdmin = accounts[0];
1516

1617
const assertOnlyAdmin = (method, ...params) => {
1718
return TruffleAssert.reverts(method(...params, {from: initialRelayers[1]}), "sender doesn't have admin role");
1819
};
1920

2021
let BridgeInstance;
2122
let FeeHandlerWithOracleInstance;
23+
let ADMIN_ROLE;
2224

2325
beforeEach(async () => {
2426
BridgeInstance = awaitBridgeInstance = await Helpers.deployBridge(domainID, accounts[0]);
2527
FeeHandlerWithOracleInstance = await FeeHandlerWithOracleContract.new(BridgeInstance.address);
28+
29+
ADMIN_ROLE = await FeeHandlerWithOracleInstance.DEFAULT_ADMIN_ROLE();
2630
});
2731

2832
it("should set fee oracle", async () => {
@@ -53,4 +57,17 @@
5357
const feePercent = 5;
5458
await assertOnlyAdmin(FeeHandlerWithOracleInstance.setFeeProperties, gasUsed, feePercent);
5559
});
60+
61+
it('FeeHandlerWithOracle admin should be changed to expectedFeeHandlerWithOracleAdmin', async () => {
62+
const expectedFeeHandlerWithOracleAdmin = accounts[1];
63+
64+
// check current admin
65+
assert.isTrue(await FeeHandlerWithOracleInstance.hasRole(ADMIN_ROLE, currentFeeHandlerAdmin));
66+
67+
await TruffleAssert.passes(FeeHandlerWithOracleInstance.renounceAdmin(expectedFeeHandlerWithOracleAdmin))
68+
assert.isTrue(await FeeHandlerWithOracleInstance.hasRole(ADMIN_ROLE, expectedFeeHandlerWithOracleAdmin));
69+
70+
// check that former admin is no longer admin
71+
assert.isFalse(await FeeHandlerWithOracleInstance.hasRole(ADMIN_ROLE, currentFeeHandlerAdmin));
72+
});
5673
});

0 commit comments

Comments
 (0)