Skip to content

Commit 47e8f4d

Browse files
committed
feat: enable multiple pausers and unpausers
1 parent a769748 commit 47e8f4d

14 files changed

+66
-51
lines changed

contracts/ICS20Transfer.sol

+5-4
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,23 @@ contract ICS20Transfer is
7878
/// @param ics26Router The ICS26Router contract address
7979
/// @param escrowLogic Is the address of the Escrow logic contract
8080
/// @param ibcERC20Logic Is the address of the IBCERC20 logic contract
81-
/// @param pauser The address that can pause and unpause the contract
81+
/// @param pausers The addresses that can pause the contract
82+
/// @param unpausers The addresses that can unpause the contract
8283
/// @inheritdoc IICS20Transfer
8384
function initialize(
8485
address ics26Router,
8586
address escrowLogic,
8687
address ibcERC20Logic,
87-
address pauser,
88-
address unpauser,
88+
address[] memory pausers,
89+
address[] memory unpausers,
8990
address permit2
9091
)
9192
public
9293
initializer
9394
{
9495
__ReentrancyGuardTransient_init();
9596
__Multicall_init();
96-
__IBCPausable_init(pauser, unpauser);
97+
__IBCPausable_init(pausers, unpausers);
9798

9899
ICS20TransferStorage storage $ = _getICS20TransferStorage();
99100

contracts/interfaces/IICS20Transfer.sol

+4-4
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ interface IICS20Transfer {
7676
/// @param ics26Router The ICS26Router contract address
7777
/// @param escrowLogic The address of the Escrow logic contract
7878
/// @param ibcERC20Logic The address of the IBCERC20 logic contract
79-
/// @param pauser The address that can pause the contract
80-
/// @param unpauser The address that can unpause the contract
79+
/// @param pausers The addresses that can pause the contract
80+
/// @param unpausers The addresses that can unpause the contract
8181
/// @param permit2 The address of the permit2 contract
8282
function initialize(
8383
address ics26Router,
8484
address escrowLogic,
8585
address ibcERC20Logic,
86-
address pauser,
87-
address unpauser,
86+
address[] memory pausers,
87+
address[] memory unpausers,
8888
address permit2
8989
)
9090
external;

contracts/utils/IBCPausableUpgradeable.sol

+7-7
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,18 @@ abstract contract IBCPausableUpgradeable is
2020
bytes32 public constant UNPAUSER_ROLE = keccak256("UNPAUSER_ROLE");
2121

2222
/// @dev Initializes the contract in unpaused state.
23-
/// @param pauser The address that is granted the `PAUSER_ROLE`
24-
/// @param unpauser The address that is granted the `UNPAUSER_ROLE`
25-
function __IBCPausable_init(address pauser, address unpauser) internal onlyInitializing {
23+
/// @param pausers The addresses that are granted the `PAUSER_ROLE`
24+
/// @param unpausers The addresses that are granted the `UNPAUSER_ROLE`
25+
function __IBCPausable_init(address[] memory pausers, address[] memory unpausers) internal onlyInitializing {
2626
__Pausable_init();
2727
__AccessControl_init();
2828

29-
if (pauser != address(0)) {
30-
_grantRole(PAUSER_ROLE, pauser);
29+
for (uint256 i = 0; i < pausers.length; i++) {
30+
_grantRole(PAUSER_ROLE, pausers[i]);
3131
}
3232

33-
if (unpauser != address(0)) {
34-
_grantRole(UNPAUSER_ROLE, unpauser);
33+
for (uint256 i = 0; i < unpausers.length; i++) {
34+
_grantRole(UNPAUSER_ROLE, unpausers[i]);
3535
}
3636
}
3737

deployments/devnet/11155111.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"ibcERC20Implementation": "0x50B244F8F3cAC4444f44cfD8B4ddc1805823E017",
1212
"ics26Router": "0x15cB0fC94d072B367a1A2D7f0c8fF9792aB9f546",
1313
"implementation": "0x23A45521Dda9ed9C47F4C8cf44282544FdAdF6D9",
14-
"pauser": "0x0000000000000000000000000000000000000000",
15-
"unpauser": "0x0000000000000000000000000000000000000000",
14+
"pausers": [],
15+
"unpausers": [],
1616
"permit2": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
1717
"proxy": "0xbb87C1ACc6306ad2233a4c7BBE75a1230409b358"
1818
},

deployments/local/31337.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
"ibcERC20Implementation": "0x0000000000000000000000000000000000000000",
1111
"ics26Router": "0x0000000000000000000000000000000000000000",
1212
"implementation": "0x0000000000000000000000000000000000000000",
13-
"pauser": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
14-
"unpauser": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
13+
"pausers": ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"],
14+
"unpausers": ["0x70997970C51812dc3A010C7d01b50e0d17dc79C8"],
1515
"permit2": "0x0000000000000000000000000000000000000000",
1616
"proxy": "0x0000000000000000000000000000000000000000"
1717
},

deployments/testnet-staging/11155111.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"ibcERC20Implementation": "0xbAfa1093C913d92992634a6c9b148a3229191927",
1212
"ics26Router": "0x718AbdD2f29A6aC1a34A3e20Dae378B5d3d2B0E9",
1313
"implementation": "0xa453828f345b85520444C6B4b23c8bA9F6A46fe6",
14-
"pauser": "0xAe3E5CCaF3216de61090E68Cf5a191f3b75CaAd3",
15-
"unpauser": "0x0000000000000000000000000000000000000000",
14+
"pausers": ["0xAe3E5CCaF3216de61090E68Cf5a191f3b75CaAd3"],
15+
"unpausers": [],
1616
"permit2": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
1717
"proxy": "0xE80DC519EE86146057B9dBEfBa900Edd7a2385e4"
1818
},

scripts/E2ETestDeploy.s.sol

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ contract E2ETestDeploy is Script, IICS07TendermintMsgs, DeploySP1ICS07Tendermint
7676
ics26Router: address(routerProxy),
7777
escrowImplementation: escrowLogic,
7878
ibcERC20Implementation: ibcERC20Logic,
79-
pauser: address(0),
80-
unpauser: address(0),
79+
pausers: new address[](0),
80+
unpauser: new address[](0),
8181
permit2: address(0)
8282
});
8383

scripts/deployments/DeployProxiedICS20Transfer.sol

+25-17
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ abstract contract DeployProxiedICS20Transfer is Deployments {
2828
deployment.ics26Router,
2929
deployment.escrowImplementation,
3030
deployment.ibcERC20Implementation,
31-
deployment.pauser,
32-
deployment.unpauser,
31+
deployment.pausers,
32+
deployment.unpausers,
3333
deployment.permit2
3434
)
3535
);
@@ -86,22 +86,30 @@ contract DeployProxiedICS20TransferScript is DeployProxiedICS20Transfer, Script
8686
"transfer app address doesn't match with the one in ics26Router"
8787
);
8888

89-
if (deployment.pauser != address(0)) {
90-
IBCPausableUpgradeable ipu = IBCPausableUpgradeable(address(transferProxy));
89+
if (deployment.pausers.length != 0) {
90+
for (uint32 i = 0; i < deployment.pausers.length; i++) {
91+
address pauser = deployment.pausers[i];
9192

92-
vm.assertTrue(
93-
ipu.hasRole(ipu.PAUSER_ROLE(), deployment.pauser),
94-
"pauser address doesn't have pauser role"
95-
);
93+
IBCPausableUpgradeable ipu = IBCPausableUpgradeable(address(transferProxy));
94+
95+
vm.assertTrue(
96+
ipu.hasRole(ipu.PAUSER_ROLE(), pauser),
97+
string.concat("pauser address (", Strings.toHexString(pauser), ") doesn't have pauser role")
98+
);
99+
}
96100
}
97101

98-
if (deployment.unpauser != address(0)) {
99-
IBCPausableUpgradeable ipu = IBCPausableUpgradeable(address(transferProxy));
102+
if (deployment.unpausers.length != 0) {
103+
for (uint32 i = 0; i < deployment.unpausers.length; i++) {
104+
address unpauser = deployment.unpausers[i];
105+
106+
IBCPausableUpgradeable ipu = IBCPausableUpgradeable(address(transferProxy));
100107

101-
vm.assertTrue(
102-
ipu.hasRole(ipu.UNPAUSER_ROLE(), deployment.unpauser),
103-
"unpauser address doesn't have unpauser role"
104-
);
108+
vm.assertTrue(
109+
ipu.hasRole(ipu.UNPAUSER_ROLE(), unpauser),
110+
string.concat("unpauser address (", Strings.toHexString(unpauser), ") doesn't have unpauser role")
111+
);
112+
}
105113
}
106114
}
107115

@@ -152,13 +160,13 @@ contract DeployProxiedICS20TransferScript is DeployProxiedICS20Transfer, Script
152160
vm.serializeAddress("ics20Transfer", "implementation", deployment.implementation);
153161
vm.serializeAddress("ics20Transfer", "escrowImplementation", deployment.escrowImplementation);
154162
vm.serializeAddress("ics20Transfer", "ibcERC20Implementation", deployment.ibcERC20Implementation);
155-
vm.serializeAddress("ics20Transfer", "pauser", deployment.pauser);
156-
vm.serializeAddress("ics20Transfer", "unpauser", deployment.unpauser);
163+
vm.serializeAddress("ics20Transfer", "pausers", deployment.pausers);
164+
vm.serializeAddress("ics20Transfer", "unpausers", deployment.unpausers);
157165
vm.serializeAddress("ics20Transfer", "ics26Router", deployment.ics26Router);
158166
string memory output = vm.serializeAddress("ics20Transfer", "permit2", deployment.permit2);
159167

160168
vm.writeJson(output, path, ".ics20Transfer");
161169

162170
return address(transferProxy);
163171
}
164-
}
172+
}

scripts/helpers/Deployments.sol

+4-4
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ abstract contract Deployments {
102102
address ibcERC20Implementation;
103103

104104
// admin control
105-
address pauser;
106-
address unpauser;
105+
address[] pausers;
106+
address[] unpausers;
107107
address permit2;
108108
address proxy;
109109
}
@@ -122,8 +122,8 @@ abstract contract Deployments {
122122
ibcERC20Implementation: vm.parseJsonAddress(json, ".ics20Transfer.ibcERC20Implementation"),
123123
ics26Router: vm.parseJsonAddress(json, ".ics20Transfer.ics26Router"),
124124
implementation: vm.parseJsonAddress(json, ".ics20Transfer.implementation"),
125-
pauser: vm.parseJsonAddress(json, ".ics20Transfer.pauser"),
126-
unpauser: vm.parseJsonAddress(json, ".ics20Transfer.unpauser"),
125+
pausers: vm.parseJsonAddressArray(json, ".ics20Transfer.pausers"),
126+
unpausers: vm.parseJsonAddressArray(json, ".ics20Transfer.unpausers"),
127127
permit2: vm.parseJsonAddress(json, ".ics20Transfer.permit2"),
128128
proxy: vm.parseJsonAddress(json, ".ics20Transfer.proxy")
129129
});

test/solidity-ibc/FixtureTest.t.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ abstract contract FixtureTest is Test, IICS07TendermintMsgs {
6565
address(ics20TransferLogic),
6666
abi.encodeCall(
6767
ICS20Transfer.initialize,
68-
(address(routerProxy), escrowLogic, ibcERC20Logic, address(0), address(0), address(0))
68+
(address(routerProxy), escrowLogic, ibcERC20Logic, new address[](0), new address[](0), address(0))
6969
)
7070
);
7171

test/solidity-ibc/IBCAdminTest.t.sol

+9-3
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,17 @@ contract IBCAdminTest is Test {
3333
address public ics20Pauser = makeAddr("ics20Pauser");
3434
address public ics20Unpauser = makeAddr("ics20Unpauser");
3535

36+
address[] public ics20Pausers = new address[](1);
37+
address[] public ics20Unpausers = new address[](1);
38+
3639
string public clientId;
3740
string public counterpartyId = "42-dummy-01";
3841
bytes[] public merklePrefix = [bytes("ibc"), bytes("")];
3942

4043
function setUp() public {
44+
ics20Pausers[0] = ics20Pauser;
45+
ics20Unpausers[0] = ics20Unpauser;
46+
4147
// ============ Step 1: Deploy the logic contracts ==============
4248
DummyLightClient lightClient = new DummyLightClient(ILightClientMsgs.UpdateResult.Update, 0, false);
4349
address escrowLogic = address(new Escrow());
@@ -54,7 +60,7 @@ contract IBCAdminTest is Test {
5460
address(ics20TransferLogic),
5561
abi.encodeCall(
5662
ICS20Transfer.initialize,
57-
(address(routerProxy), escrowLogic, ibcERC20Logic, ics20Pauser, ics20Unpauser, address(0))
63+
(address(routerProxy), escrowLogic, ibcERC20Logic, ics20Pausers, ics20Unpausers, address(0))
5864
)
5965
);
6066

@@ -352,9 +358,9 @@ contract IBCAdminTest is Test {
352358
vm.prank(unauthorized);
353359
vm.expectRevert(abi.encodeWithSelector(IICS20Errors.ICS20Unauthorized.selector, unauthorized));
354360
ics20Transfer.grantUnpauserRole(newUnpauser);
355-
assertFalse(ics20Transfer.hasRole(ics20Transfer.PAUSER_ROLE(), newUnpauser));
361+
assertFalse(ics20Transfer.hasRole(ics20Transfer.UNPAUSER_ROLE(), newUnpauser));
356362

357-
// Revoke the pauser role from an unauthorized account
363+
// Revoke the unpauser role from an unauthorized account
358364
vm.prank(unauthorized);
359365
vm.expectRevert(abi.encodeWithSelector(IICS20Errors.ICS20Unauthorized.selector, unauthorized));
360366
ics20Transfer.revokeUnpauserRole(ics20Unpauser);

test/solidity-ibc/ICS20TransferTest.t.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ contract ICS20TransferTest is Test, DeployPermit2, PermitSignature {
5050
address(ics20TransferLogic),
5151
abi.encodeCall(
5252
ICS20Transfer.initialize,
53-
(address(this), escrowLogic, ibcERC20Logic, address(0), address(0), address(permit2))
53+
(address(this), escrowLogic, ibcERC20Logic, new address[](0), new address[](0), address(permit2))
5454
)
5555
);
5656

test/solidity-ibc/ICS26RouterTest.t.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ contract ICS26RouterTest is Test {
102102
address(ics20TransferLogic),
103103
abi.encodeCall(
104104
ICS20Transfer.initialize,
105-
(address(ics26Router), escrowLogic, ibcERC20Logic, address(0), address(0), address(0))
105+
(address(ics26Router), escrowLogic, ibcERC20Logic, new address[](0), new address[](0), address(0))
106106
)
107107
);
108108
ICS20Transfer ics20Transfer = ICS20Transfer(address(transferProxy));

test/solidity-ibc/IntegrationTest.t.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ contract IntegrationTest is Test, DeployPermit2, PermitSignature {
8080
address(ics20TransferLogic),
8181
abi.encodeCall(
8282
ICS20Transfer.initialize,
83-
(address(routerProxy), escrowLogic, ibcERC20Logic, address(0), address(0), address(permit2))
83+
(address(routerProxy), escrowLogic, ibcERC20Logic, new address[](0), new address[](0), address(permit2))
8484
)
8585
);
8686

0 commit comments

Comments
 (0)