Skip to content

Commit 00e0332

Browse files
authored
imp(contracts): simplified migrateClient (#533)
1 parent ff975ef commit 00e0332

File tree

5 files changed

+114
-68
lines changed

5 files changed

+114
-68
lines changed

abi/ICS26Router.json

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -522,14 +522,31 @@
522522
"name": "migrateClient",
523523
"inputs": [
524524
{
525-
"name": "subjectClientId",
525+
"name": "clientId",
526526
"type": "string",
527527
"internalType": "string"
528528
},
529529
{
530-
"name": "substituteClientId",
531-
"type": "string",
532-
"internalType": "string"
530+
"name": "counterpartyInfo",
531+
"type": "tuple",
532+
"internalType": "struct IICS02ClientMsgs.CounterpartyInfo",
533+
"components": [
534+
{
535+
"name": "clientId",
536+
"type": "string",
537+
"internalType": "string"
538+
},
539+
{
540+
"name": "merklePrefix",
541+
"type": "bytes[]",
542+
"internalType": "bytes[]"
543+
}
544+
]
545+
},
546+
{
547+
"name": "client",
548+
"type": "address",
549+
"internalType": "address"
533550
}
534551
],
535552
"outputs": [],
@@ -1107,6 +1124,12 @@
11071124
"internalType": "bytes[]"
11081125
}
11091126
]
1127+
},
1128+
{
1129+
"name": "client",
1130+
"type": "address",
1131+
"indexed": false,
1132+
"internalType": "address"
11101133
}
11111134
],
11121135
"anonymous": false
@@ -1116,16 +1139,34 @@
11161139
"name": "ICS02ClientMigrated",
11171140
"inputs": [
11181141
{
1119-
"name": "subjectClientId",
1142+
"name": "clientId",
11201143
"type": "string",
11211144
"indexed": false,
11221145
"internalType": "string"
11231146
},
11241147
{
1125-
"name": "substituteClientId",
1126-
"type": "string",
1148+
"name": "counterpartyInfo",
1149+
"type": "tuple",
11271150
"indexed": false,
1128-
"internalType": "string"
1151+
"internalType": "struct IICS02ClientMsgs.CounterpartyInfo",
1152+
"components": [
1153+
{
1154+
"name": "clientId",
1155+
"type": "string",
1156+
"internalType": "string"
1157+
},
1158+
{
1159+
"name": "merklePrefix",
1160+
"type": "bytes[]",
1161+
"internalType": "bytes[]"
1162+
}
1163+
]
1164+
},
1165+
{
1166+
"name": "client",
1167+
"type": "address",
1168+
"indexed": false,
1169+
"internalType": "address"
11291170
}
11301171
],
11311172
"anonymous": false

contracts/interfaces/IICS02Client.sol

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,17 @@ interface IICS02Client {
7474
external
7575
returns (ILightClientMsgs.UpdateResult);
7676

77-
/// @notice Migrate the underlying client of the subject client to the substitute client.
78-
/// @dev This is a privilaged operation, only the owner of ICS02Client can call this function.
79-
/// @param subjectClientId The client identifier of the subject client
80-
/// @param substituteClientId The client identifier of the substitute client
81-
function migrateClient(string calldata subjectClientId, string calldata substituteClientId) external;
77+
/// @notice Migrate a client by replacing the existing counterparty information and contract address.
78+
/// @dev This is a privilaged operation, only one with `getLightClientMigratorRole(clientId)` can call this.
79+
/// @param clientId The client identifier of the client to migrate
80+
/// @param counterpartyInfo The new counterparty client information
81+
/// @param client The address of the new client contract
82+
function migrateClient(
83+
string memory clientId,
84+
IICS02ClientMsgs.CounterpartyInfo calldata counterpartyInfo,
85+
address client
86+
)
87+
external;
8288

8389
/// @notice Submits misbehaviour to the client with the given client identifier.
8490
/// @param clientId The client identifier
@@ -94,13 +100,15 @@ interface IICS02Client {
94100

95101
/// @notice Emitted when a new client is added to the client router.
96102
/// @param clientId The newly created client identifier
97-
/// @param counterpartyInfo The counterparty client information, if provided
98-
event ICS02ClientAdded(string clientId, IICS02ClientMsgs.CounterpartyInfo counterpartyInfo);
103+
/// @param counterpartyInfo The counterparty client information
104+
/// @param client The address of the client contract
105+
event ICS02ClientAdded(string clientId, IICS02ClientMsgs.CounterpartyInfo counterpartyInfo, address client);
99106

100107
/// @notice Emitted when a client is migrated to a new client.
101-
/// @param subjectClientId The client identifier of the existing client
102-
/// @param substituteClientId The client identifier of the new client migrated to
103-
event ICS02ClientMigrated(string subjectClientId, string substituteClientId);
108+
/// @param clientId The client identifier of the migrated client
109+
/// @param counterpartyInfo The new counterparty client information
110+
/// @param client The address of the new client contract
111+
event ICS02ClientMigrated(string clientId, IICS02ClientMsgs.CounterpartyInfo counterpartyInfo, address client);
104112

105113
/// @notice Emitted when a client is updated.
106114
/// @param clientId The client identifier of the updated ILightClientMsgs

contracts/utils/ICS02ClientUpgradeable.sol

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ abstract contract ICS02ClientUpgradeable is IICS02Client, IICS02ClientErrors, Ac
9494

9595
/// @inheritdoc IICS02Client
9696
function addClient(
97-
string memory clientId,
97+
string calldata clientId,
9898
IICS02ClientMsgs.CounterpartyInfo calldata counterpartyInfo,
9999
address client
100100
)
@@ -126,7 +126,7 @@ abstract contract ICS02ClientUpgradeable is IICS02Client, IICS02ClientErrors, Ac
126126
$.clients[clientId] = ILightClient(client);
127127
$.counterpartyInfos[clientId] = counterpartyInfo;
128128

129-
emit ICS02ClientAdded(clientId, counterpartyInfo);
129+
emit ICS02ClientAdded(clientId, counterpartyInfo, client);
130130

131131
bytes32 role = getLightClientMigratorRole(clientId);
132132
require(_grantRole(role, _msgSender()), Unreachable());
@@ -148,24 +148,20 @@ abstract contract ICS02ClientUpgradeable is IICS02Client, IICS02ClientErrors, Ac
148148

149149
/// @inheritdoc IICS02Client
150150
function migrateClient(
151-
string calldata subjectClientId,
152-
string calldata substituteClientId
151+
string calldata clientId,
152+
IICS02ClientMsgs.CounterpartyInfo calldata counterpartyInfo,
153+
address client
153154
)
154155
external
155-
onlyRole(getLightClientMigratorRole(subjectClientId))
156+
onlyRole(getLightClientMigratorRole(clientId))
156157
{
157-
ICS02ClientStorage storage $ = _getICS02ClientStorage();
158+
getClient(clientId); // Ensure subject client exists
158159

159-
getClient(subjectClientId); // Ensure subject client exists
160-
ILightClient substituteClient = getClient(substituteClientId);
161-
162-
getCounterparty(subjectClientId); // Ensure subject client's counterparty exists
163-
IICS02ClientMsgs.CounterpartyInfo memory substituteCounterpartyInfo = getCounterparty(substituteClientId);
164-
165-
$.counterpartyInfos[subjectClientId] = substituteCounterpartyInfo;
166-
$.clients[subjectClientId] = substituteClient;
160+
ICS02ClientStorage storage $ = _getICS02ClientStorage();
161+
$.counterpartyInfos[clientId] = counterpartyInfo;
162+
$.clients[clientId] = ILightClient(client);
167163

168-
emit ICS02ClientMigrated(subjectClientId, substituteClientId);
164+
emit ICS02ClientMigrated(clientId, counterpartyInfo, client);
169165
}
170166

171167
/// @inheritdoc IICS02Client

packages/go-abigen/ics26router/contract.go

Lines changed: 30 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/solidity-ibc/ICS02ClientTest.t.sol

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { IICS02ClientErrors } from "../../contracts/errors/IICS02ClientErrors.so
1616
import { ICS02ClientUpgradeable } from "../../contracts/utils/ICS02ClientUpgradeable.sol";
1717
import { ERC1967Proxy } from "@openzeppelin-contracts/proxy/ERC1967/ERC1967Proxy.sol";
1818
import { ICS26Router } from "../../contracts/ICS26Router.sol";
19+
import { TestHelper } from "./utils/TestHelper.sol";
1920

2021
contract ICS02ClientTest is Test {
2122
ICS02ClientUpgradeable public ics02Client;
@@ -27,6 +28,7 @@ contract ICS02ClientTest is Test {
2728
string public clientIdentifier;
2829

2930
address public clientOwner = makeAddr("clientOwner");
31+
TestHelper public th = new TestHelper();
3032

3133
function setUp() public {
3234
ICS26Router ics26RouterLogic = new ICS26Router();
@@ -43,7 +45,7 @@ contract ICS02ClientTest is Test {
4345
IICS02ClientMsgs.CounterpartyInfo memory counterpartyInfo =
4446
IICS02ClientMsgs.CounterpartyInfo(counterpartyId, merklePrefix);
4547
vm.expectEmit();
46-
emit IICS02Client.ICS02ClientAdded("client-0", counterpartyInfo);
48+
emit IICS02Client.ICS02ClientAdded(th.FIRST_CLIENT_ID(), counterpartyInfo, lightClient);
4749
clientIdentifier = ics02Client.addClient(counterpartyInfo, lightClient);
4850
vm.stopPrank();
4951

@@ -87,10 +89,6 @@ contract ICS02ClientTest is Test {
8789
address newLightClient = makeAddr("newLightClient");
8890
IICS02ClientMsgs.CounterpartyInfo memory counterpartyInfo =
8991
IICS02ClientMsgs.CounterpartyInfo(counterpartyId, randomPrefix);
90-
vm.expectEmit();
91-
emit IICS02Client.ICS02ClientAdded("client-1", counterpartyInfo);
92-
string memory substituteIdentifier = ics02Client.addClient(counterpartyInfo, newLightClient);
93-
assertEq(2, ics02Client.getNextClientSeq());
9492

9593
vm.expectRevert(
9694
abi.encodeWithSelector(
@@ -99,18 +97,19 @@ contract ICS02ClientTest is Test {
9997
ics02Client.getLightClientMigratorRole(clientIdentifier)
10098
)
10199
);
102-
ics02Client.migrateClient(clientIdentifier, substituteIdentifier);
100+
ics02Client.migrateClient(clientIdentifier, counterpartyInfo, newLightClient);
103101
vm.stopPrank();
104102

105103
vm.startPrank(clientOwner);
106-
ics02Client.migrateClient(clientIdentifier, substituteIdentifier);
104+
ics02Client.migrateClient(clientIdentifier, counterpartyInfo, newLightClient);
107105
ILightClient fetchedLightClient = ics02Client.getClient(clientIdentifier);
108106
assertEq(address(fetchedLightClient), newLightClient, "client not migrated");
109107
vm.stopPrank();
110108

111109
IICS02ClientMsgs.CounterpartyInfo memory fetchedCounterparty = ics02Client.getCounterparty(clientIdentifier);
112110
assertEq(fetchedCounterparty.clientId, counterpartyId, "counterparty not migrated");
113111
assertEq(fetchedCounterparty.merklePrefix, randomPrefix, "counterparty not migrated");
112+
assertEq(ics02Client.getNextClientSeq(), 1, "client seq not incremented");
114113
}
115114

116115
function test_RenounceRole() public {

0 commit comments

Comments
 (0)