powerdlz23 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/package.json +1 -1
  2. package/polymer/polymer-template/.env.example +27 -0
  3. package/polymer/polymer-template/.gitmodules +6 -0
  4. package/polymer/polymer-template/.gitpod.yml +10 -0
  5. package/polymer/polymer-template/Justfile +97 -0
  6. package/polymer/polymer-template/README.md +312 -0
  7. package/polymer/polymer-template/config/alt-config.json +42 -0
  8. package/polymer/polymer-template/config.json +42 -0
  9. package/polymer/polymer-template/contracts/XCounter.sol +89 -0
  10. package/polymer/polymer-template/contracts/XCounterUC.sol +100 -0
  11. package/polymer/polymer-template/contracts/arguments.js +7 -0
  12. package/polymer/polymer-template/contracts/base/CustomChanIbcApp.sol +205 -0
  13. package/polymer/polymer-template/contracts/base/GeneralMiddleware.sol +200 -0
  14. package/polymer/polymer-template/contracts/base/UniversalChanIbcApp.sol +93 -0
  15. package/polymer/polymer-template/foundry.toml +6 -0
  16. package/polymer/polymer-template/hardhat.config.js +66 -0
  17. package/polymer/polymer-template/ibc.json +26 -0
  18. package/polymer/polymer-template/img/gh_template.png +0 -0
  19. package/polymer/polymer-template/package-lock.json +7672 -0
  20. package/polymer/polymer-template/package.json +34 -0
  21. package/polymer/polymer-template/remappings.txt +5 -0
  22. package/polymer/polymer-template/scripts/deploy.js +51 -0
  23. package/polymer/polymer-template/scripts/private/_create-channel-config.js +62 -0
  24. package/polymer/polymer-template/scripts/private/_create-channel.js +96 -0
  25. package/polymer/polymer-template/scripts/private/_deploy-config.js +62 -0
  26. package/polymer/polymer-template/scripts/private/_events.js +241 -0
  27. package/polymer/polymer-template/scripts/private/_helpers.js +113 -0
  28. package/polymer/polymer-template/scripts/private/_sanity-check-custom.js +69 -0
  29. package/polymer/polymer-template/scripts/private/_sanity-check-universal.js +120 -0
  30. package/polymer/polymer-template/scripts/private/_sanity-check.js +21 -0
  31. package/polymer/polymer-template/scripts/private/_send-packet-config.js +53 -0
  32. package/polymer/polymer-template/scripts/private/_set-contracts-config.js +50 -0
  33. package/polymer/polymer-template/scripts/private/_switch-clients.js +90 -0
  34. package/polymer/polymer-template/scripts/private/_update-vibc-address.js +52 -0
  35. package/polymer/polymer-template/scripts/private/_vibc-helpers.js +118 -0
  36. package/polymer/polymer-template/scripts/send-packet.js +38 -0
  37. package/polymer/polymer-template/scripts/send-universal-packet.js +44 -0
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "ibc-app-solidity-template",
3
+ "version": "1.0.0",
4
+ "description": "Template project to start building IBC enabled Solidity contracts, with Hardhat and Foundry support",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/open-ibc/ibc-app-solidity-template.git"
12
+ },
13
+ "keywords": [
14
+ "IBC",
15
+ "Solidity"
16
+ ],
17
+ "author": "Polymer Labs",
18
+ "license": "MIT",
19
+ "bugs": {
20
+ "url": "https://github.com/open-ibc/ibc-app-solidity-template/issues"
21
+ },
22
+ "homepage": "https://github.com/open-ibc/ibc-app-solidity-template#readme",
23
+ "devDependencies": {
24
+ "@nomicfoundation/hardhat-foundry": "^1.1.1",
25
+ "@nomicfoundation/hardhat-toolbox": "^4.0.0",
26
+ "hardhat": "^2.19.5"
27
+ },
28
+ "dependencies": {
29
+ "@openzeppelin/contracts": "^4.7.6",
30
+ "axios": "^1.6.7",
31
+ "dotenv": "^16.4.1",
32
+ "hardhat-verify": "^1.0.0"
33
+ }
34
+ }
@@ -0,0 +1,5 @@
1
+ @open-ibc/vibc-core-smart-contracts/=lib/vibc-core-smart-contracts/
2
+ @lazyledger/protobuf3-solidity-lib/=lib/protobuf3-solidity-lib/
3
+ ds-test/=lib/forge-std/lib/ds-test/src/
4
+ forge-std/=lib/forge-std/src/
5
+
@@ -0,0 +1,51 @@
1
+ // We require the Hardhat Runtime Environment explicitly here. This is optional
2
+ // but useful for running the script in a standalone fashion through `node <script>`.
3
+ //
4
+ // You can also run a script with `npx hardhat run <script>`. If you do that, Hardhat
5
+ // will compile your contracts, add the Hardhat Runtime Environment's members to the
6
+ // global scope, and execute the script.
7
+ const hre = require("hardhat");
8
+ const {getConfigPath} = require('./private/_helpers.js');
9
+ const { getDispatcherAddress, getUcHandlerAddress } = require('./private/_vibc-helpers.js');
10
+
11
+ async function main() {
12
+ const config = require(getConfigPath());
13
+ const argsObject = require('../contracts/arguments.js');
14
+ const networkName = hre.network.name;
15
+
16
+ // The config should have a deploy object with the network name as the key and contract type as the value
17
+ const contractType = config["deploy"][`${networkName}`];
18
+ const args = argsObject[`${contractType}`];
19
+ if (!args) {
20
+ console.warn(`No arguments found for contract type: ${contractType}`);
21
+ }
22
+
23
+ // TODO: update to switch statement when supporting more networks
24
+ let constructorArgs;
25
+ if (config.isUniversal) {
26
+ const ucHandlerAddr = getUcHandlerAddress(networkName);
27
+ constructorArgs = [ucHandlerAddr, ...(args ?? [])];
28
+ } else if (!config.isUniversal) {
29
+ const dispatcherAddr = getDispatcherAddress(networkName);
30
+ constructorArgs = [dispatcherAddr, ...(args ?? [])];
31
+ }
32
+
33
+ // Deploy the contract
34
+ // NOTE: when adding additional args to the constructor, add them to the array as well
35
+ const myContract = await hre.ethers.deployContract(contractType, constructorArgs);
36
+
37
+ await myContract.waitForDeployment();
38
+
39
+ // NOTE: Do not change the output string, its output is formatted to be used in the deploy-config.js script
40
+ // to update the config.json file
41
+ console.log(
42
+ `Contract ${contractType} deployed to ${myContract.target} on network ${networkName}`
43
+ );
44
+ }
45
+
46
+ // We recommend this pattern to be able to use async/await everywhere
47
+ // and properly handle errors.
48
+ main().catch((error) => {
49
+ console.error(error);
50
+ process.exitCode = 1;
51
+ });
@@ -0,0 +1,62 @@
1
+ const { exec } = require("child_process");
2
+ const { getConfigPath, updateConfigCreateChannel, getWhitelistedNetworks } = require('./_helpers.js');
3
+ const { setupIbcChannelEventListener } = require('./_events.js');
4
+
5
+ // Function to run the deploy script and capture output
6
+ function createChannelAndCapture() {
7
+ const config = require(getConfigPath());
8
+ const srcChain = config.createChannel.srcChain;
9
+
10
+ // Check if the source chain from user input is whitelisted
11
+ const allowedNetworks = getWhitelistedNetworks();
12
+ if (!allowedNetworks.includes(srcChain)) {
13
+ console.error('❌ Invalid network name');
14
+ return;
15
+ }
16
+ exec(`npx hardhat run scripts/private/_create-channel.js --network ${srcChain}`, (error, stdout, stderr) => {
17
+ if (error) {
18
+ console.error(`exec error: ${error}`);
19
+ return;
20
+ }
21
+
22
+ // Process stdout to find the contract address and network
23
+ const output = stdout.trim();
24
+ const match = output.match(/Channel created: (\S+) with portID (\S+) on network (\S+), Counterparty: (\S+) on network (\S+)/);
25
+
26
+ if (match) {
27
+ const channel = match[1];
28
+ const portId = match[2];
29
+ const network = match[3];
30
+ const cpChannel = match[4];
31
+ const cpNetwork = match[5];
32
+
33
+ console.log(`
34
+ 🎊 Created Channel 🎊
35
+ -----------------------------------------
36
+ 🛣️ Channel ID: ${channel}
37
+ 🔗 Port ID: ${portId}
38
+ 🌍 Network: ${network}
39
+ -----------------------------------------
40
+ 🛣️ Counterparty Channel ID: ${cpChannel}
41
+ 🪐 Counterparty Network: ${cpNetwork}
42
+ -----------------------------------------\n`
43
+ );
44
+
45
+ // Update the config.json file
46
+ updateConfigCreateChannel(network, channel, cpNetwork, cpChannel);
47
+ console.log(`🆗 Updated config.json with ${channel} on network ${network} and ${cpChannel} on network ${cpNetwork}`);
48
+ } else {
49
+ console.error("❌ Could not find required parameters in output");
50
+ }
51
+ });
52
+ }
53
+
54
+ async function main() {
55
+ await setupIbcChannelEventListener();
56
+ createChannelAndCapture();
57
+ }
58
+
59
+ main().catch((error) => {
60
+ console.error(error);
61
+ process.exitCode = 1;
62
+ });
@@ -0,0 +1,96 @@
1
+ // We require the Hardhat Runtime Environment explicitly here. This is optional
2
+ // but useful for running the script in a standalone fashion through `node <script>`.
3
+ //
4
+ // You can also run a script with `npx hardhat run <script>`. If you do that, Hardhat
5
+ // will compile your contracts, add the Hardhat Runtime Environment's members to the
6
+ // global scope, and execute the script.
7
+ const hre = require('hardhat');
8
+ const { getConfigPath, addressToPortId } = require('./_helpers');
9
+ const { getIbcApp } = require('./_vibc-helpers.js');
10
+ const ibcConfig = require('../../ibc.json');
11
+
12
+ function createDummyProof() {
13
+ return {
14
+ proof: [
15
+ {
16
+ path: [
17
+ {
18
+ prefix: hre.ethers.toUtf8Bytes("prefixExample1"),
19
+ suffix: hre.ethers.toUtf8Bytes("suffixExample1"),
20
+ },
21
+ // Add more OpIcs23ProofPath objects as needed
22
+ ],
23
+ key: hre.ethers.toUtf8Bytes("keyExample"),
24
+ value: hre.ethers.toUtf8Bytes("valueExample"),
25
+ prefix: hre.ethers.toUtf8Bytes("prefixExample")
26
+ },
27
+ // Add more OpIcs23Proof objects as needed
28
+ ],
29
+ height: 123456, // example block height
30
+ };
31
+ }
32
+
33
+ async function main() {
34
+ const config = require(getConfigPath());
35
+ const chanConfig = config.createChannel;
36
+ const networkName = hre.network.name;
37
+
38
+ // Get the contract type from the config and get the contract
39
+ const ibcApp = await getIbcApp(networkName);
40
+ const connectedChannelsBefore = await ibcApp.getConnectedChannels();
41
+
42
+ // Prepare the arguments to create the channel
43
+ const connHop1 = ibcConfig[chanConfig.srcChain][`${config.proofsEnabled ? 'op-client' : 'sim-client'}`].canonConnFrom;
44
+ const connHop2 = ibcConfig[chanConfig.dstChain][`${config.proofsEnabled ? 'op-client' : 'sim-client'}`].canonConnTo;
45
+ const srcPortId = addressToPortId(`polyibc.${chanConfig.srcChain}`, chanConfig.srcAddr);
46
+ const dstPortId = addressToPortId(`polyibc.${chanConfig.dstChain}`, chanConfig.dstAddr);
47
+
48
+ const local = {
49
+ portId: srcPortId,
50
+ channelId: hre.ethers.encodeBytes32String(''),
51
+ version: chanConfig.version,
52
+ };
53
+
54
+ const cp = {
55
+ portId: dstPortId,
56
+ channelId: hre.ethers.encodeBytes32String(''),
57
+ version: '',
58
+ };
59
+
60
+ // Create the channel
61
+ // Note: The proofHeight and proof are dummy values and will be dropped in the future
62
+ await ibcApp.createChannel(
63
+ local,
64
+ chanConfig.ordering,
65
+ chanConfig.fees,
66
+ [ connHop1, connHop2 ],
67
+ cp,
68
+ createDummyProof()
69
+ );
70
+
71
+ if (!config.proofsEnabled) {
72
+ // Wait for the channel handshake to complete
73
+ await new Promise((r) => setTimeout(r, 90000));
74
+
75
+ // Get the connected channels and print the new channel along with its counterparty
76
+ const connectedChannelsAfter = await ibcApp.getConnectedChannels();
77
+
78
+ if (connectedChannelsAfter!== undefined && connectedChannelsAfter.length > connectedChannelsBefore.length) {
79
+
80
+ const newChannelBytes = connectedChannelsAfter[connectedChannelsAfter.length - 1].channelId;
81
+ const newChannel = hre.ethers.decodeBytes32String(newChannelBytes);
82
+
83
+ const cpChannelBytes = connectedChannelsAfter[connectedChannelsAfter.length - 1].cpChannelId;
84
+ const cpChannel = hre.ethers.decodeBytes32String(cpChannelBytes);
85
+
86
+ console.log(`✅ Channel created: ${newChannel} with portID ${srcPortId} on network ${networkName}, Counterparty: ${cpChannel} on network ${chanConfig.dstChain}`);
87
+ }
88
+ }
89
+ }
90
+
91
+ // We recommend this pattern to be able to use async/await everywhere
92
+ // and properly handle errors.
93
+ main().catch((error) => {
94
+ console.error(error);
95
+ process.exitCode = 1;
96
+ });
@@ -0,0 +1,62 @@
1
+ const { exec } = require("child_process");
2
+ const { updateConfigDeploy, getWhitelistedNetworks } = require('./_helpers');
3
+
4
+ // Run script with source and destination networks as arguments
5
+ // Example:
6
+ // $ node deploy-config.js optimism base
7
+ const source = process.argv[2];
8
+ const destination = process.argv[3];
9
+
10
+ if (!source || !destination) {
11
+ console.error('Usage: node deploy-config.js <source_network> <destination_network>');
12
+ process.exit(1);
13
+ }
14
+
15
+ // Function to run the deploy script and capture output
16
+ function deployAndCapture(network, isSource) {
17
+ const allowedNetworks = getWhitelistedNetworks();
18
+ if (!allowedNetworks.includes(network)) {
19
+ console.error('Invalid network. Please provide a valid network as an argument.');
20
+ return;
21
+ }
22
+ exec(`npx hardhat run scripts/deploy.js --network ${network}`, (error, stdout, stderr) => {
23
+ if (error) {
24
+ console.error(`exec error: ${error}`);
25
+ return;
26
+ } else {
27
+ console.log(stdout);
28
+ }
29
+
30
+ // Process stdout to find the contract address and network
31
+ const output = stdout.trim();
32
+ const match = output.match(/Contract (\S+) deployed to (\S+) on network (\S+)/);
33
+
34
+ if (match) {
35
+ const contractType = match[1];
36
+ const address = match[2];
37
+ const network = match[3];
38
+
39
+ console.log(`
40
+ ✅ Deployment Successful ✅
41
+ -------------------------------
42
+ 📄 Contract Type: ${contractType}
43
+ 📍 Address: ${address}
44
+ 🌍 Network: ${network}
45
+ -------------------------------\n
46
+ `);
47
+
48
+ // Update the config.json file
49
+ updateConfigDeploy(network, address, isSource);
50
+ console.log(`🆗 Updated ${process.env.CONFIG_PATH || 'config.json'} with address ${address} on network ${network}`);
51
+ } else {
52
+ console.error("❌ Could not find contract address and network in output");
53
+ }
54
+ });
55
+ }
56
+
57
+ function main() {
58
+ deployAndCapture(source, true);
59
+ deployAndCapture(destination, false);
60
+ }
61
+
62
+ main();
@@ -0,0 +1,241 @@
1
+ const hre = require("hardhat");
2
+ const { areAddressesEqual, getConfigPath } = require("./_helpers.js");
3
+ const { getDispatcher, getUcHandlerAddress } = require("./_vibc-helpers.js");
4
+
5
+ const explorerOpUrl = "https://optimism-sepolia.blockscout.com/";
6
+ const explorerBaseUrl = "https://base-sepolia.blockscout.com/";
7
+
8
+ function filterChannelEvents(portAddress) {
9
+ const config = require(getConfigPath());
10
+ return areAddressesEqual(portAddress, config.createChannel["srcAddr"]) || areAddressesEqual(portAddress, config.createChannel["dstAddr"]);
11
+ }
12
+
13
+ function listenForIbcChannelEvents(network, source, dispatcher) {
14
+ const explorerUrl = network === "optimism" ? explorerOpUrl : explorerBaseUrl;
15
+ console.log(`👂 Listening for IBC channel events on ${network}...`);
16
+ dispatcher.on(
17
+ "OpenIbcChannel",
18
+ (portAddress, version, ordering, feeEnabled, connectionHops, counterparytPortId, counterpartyChannelId, event) => {
19
+ const txHash = event.log.transactionHash;
20
+ const counterpartyChannelIdString = hre.ethers.decodeBytes32String(counterpartyChannelId);
21
+ const url = `${explorerUrl}tx/${txHash}`;
22
+
23
+ if (filterChannelEvents(portAddress)) {
24
+ console.log(`
25
+ -------------------------------------------`);
26
+ if (source) {
27
+ console.log(`
28
+ 🙋‍♀️ CHANNEL OPEN INIT !!! 🙋‍♀️`);
29
+ } else {
30
+ console.log(`
31
+ 🙋‍♂️ CHANNEL OPEN TRY !!! 🙋‍♂️`);
32
+ }
33
+
34
+ console.log(`
35
+ -------------------------------------------
36
+ 🔔 Event name: ${event.log.fragment.name}
37
+ ⛓️ Network: ${network}
38
+ 🔗 Port Address: ${portAddress}
39
+ 🔗 Counterparty Port ID: ${counterparytPortId}
40
+ 🛣️ Counterparty Channel ID: ${counterpartyChannelIdString}
41
+ 🦘 Connection Hops: ${connectionHops}
42
+ 🔀 Ordering: ${ordering}
43
+ 💰 Fee Enabled: ${feeEnabled}
44
+ #️⃣ Version: ${version}
45
+ -------------------------------------------
46
+ 🧾 TxHash: ${txHash}
47
+ 🔍 Explorer URL: ${url}
48
+ -------------------------------------------\n`);
49
+
50
+ if (source) {
51
+ console.log(` ⏱️ Waiting for channel open try...`);
52
+ } else {
53
+ console.log(` ⏱️ Waiting for channel open ack...`);
54
+ }
55
+ }
56
+ }
57
+ );
58
+
59
+ dispatcher.on("ConnectIbcChannel", (portAddress, channelId, event) => {
60
+ const txHash = event.log.transactionHash;
61
+ const channelIdString = hre.ethers.decodeBytes32String(channelId);
62
+ const url = `${explorerUrl}tx/${txHash}`;
63
+ if (filterChannelEvents(portAddress)) {
64
+ console.log(`
65
+ -------------------------------------------`);
66
+ if (source) {
67
+ console.log(`
68
+ 👩‍❤️‍💋‍👨 CHANNEL OPEN ACK !!! 👩‍❤️‍💋‍👨`);
69
+ } else {
70
+ console.log(`
71
+ 🤵‍♂️💍👰‍♀️ CHANNEL OPEN CONFIRM !!! 👰‍♀️💍🤵‍♂️`);
72
+ }
73
+ console.log(`
74
+ -------------------------------------------
75
+ 🔔 Event name: ${event.log.fragment.name}
76
+ ⛓️ Network: ${network}
77
+ 🔗 Port Address: ${portAddress}
78
+ 🛣️ Channel ID: ${channelIdString}
79
+ -------------------------------------------
80
+ 🧾 TxHash: ${txHash}
81
+ 🔍 Explorer URL: ${url}
82
+ -------------------------------------------\n`);
83
+ if (source) {
84
+ console.log(` ⏱️ Waiting for channel open confirm...`);
85
+ } else {
86
+ console.log(` ⏱️ Waiting for channel creation overview...`);
87
+ }
88
+ }
89
+ dispatcher.removeAllListeners();
90
+ });
91
+
92
+ dispatcher.on("CloseIbcChannel", (portAddress, channelId, event) => {
93
+ const txHash = event.log.transactionHash;
94
+ const channelIdString = hre.ethers.decodeBytes32String(channelId);
95
+ const url = `${explorerUrl}tx/${txHash}`;
96
+ if (filterChannelEvents(portAddress)) {
97
+ console.log(`
98
+ -------------------------------------------
99
+ 🔗 🔒 IBC CHANNEL CLOSED !!! 🔗 🔒
100
+ -------------------------------------------
101
+ 🔔 Event name: ${event.log.fragment.name}
102
+ ⛓️ Network: ${network}
103
+ 🔗 Port Address: ${portAddress}
104
+ 🛣️ Channel ID: ${channelIdString}
105
+ -------------------------------------------
106
+ 🧾 TxHash: ${txHash}
107
+ 🔍 Explorer URL: ${url}
108
+ -------------------------------------------\n`);
109
+ }
110
+ dispatcher.removeAllListeners();
111
+ });
112
+ }
113
+
114
+ function filterPacketEvents(portAddress, network) {
115
+ const config = require(getConfigPath());
116
+ const sendPacketConfig = config.sendPacket;
117
+ const ucHandlerAddr = getUcHandlerAddress(network);
118
+
119
+ return areAddressesEqual(portAddress, sendPacketConfig[`${network}`].portAddr) || areAddressesEqual(portAddress, ucHandlerAddr);
120
+ }
121
+
122
+ function listenForIbcPacketEvents(network, dispatcher) {
123
+ const explorerUrl = network === "optimism" ? explorerOpUrl : explorerBaseUrl;
124
+ console.log(`👂 Listening for IBC packet events on ${network}...`);
125
+
126
+ dispatcher.on("SendPacket", (sourcePortAddress, sourceChannelId, packet, sequence, timeoutTimestamp, event) => {
127
+ const txHash = event.log.transactionHash;
128
+ const sourceChannelIdString = hre.ethers.decodeBytes32String(sourceChannelId);
129
+ const url = `${explorerUrl}tx/${txHash}`;
130
+
131
+ if (filterPacketEvents(sourcePortAddress, network)) {
132
+ console.log(`
133
+ -------------------------------------------
134
+ 📦 📮 PACKET HAS BEEN SENT !!! 📦 📮
135
+ -------------------------------------------
136
+ 🔔 Event name: ${event.log.fragment.name}
137
+ ⛓️ Network: ${network}
138
+ 🔗 Source Port Address: ${sourcePortAddress}
139
+ 🛣️ Source Channel ID: ${sourceChannelIdString}
140
+ 📈 Sequence: ${sequence}
141
+ ⏳ Timeout Timestamp: ${timeoutTimestamp}
142
+ -------------------------------------------
143
+ 🧾 TxHash: ${txHash}
144
+ 🔍 Explorer URL: ${url}
145
+ -------------------------------------------\n`);
146
+ console.log(` ⏱️ Waiting for packet receipt...`);
147
+ }
148
+ });
149
+
150
+ dispatcher.on("RecvPacket", (destPortAddress, destChannelId, sequence, event) => {
151
+ const txHash = event.log.transactionHash;
152
+ const destChannelIdString = hre.ethers.decodeBytes32String(destChannelId);
153
+ const url = `${explorerUrl}tx/${txHash}`;
154
+
155
+ if (filterPacketEvents(destPortAddress,network)) {
156
+ console.log(`
157
+ -------------------------------------------
158
+ 📦 📬 PACKET IS RECEIVED !!! 📦 📬
159
+ -------------------------------------------
160
+ 🔔 Event name: ${event.log.fragment.name}
161
+ ⛓️ Network: ${network}
162
+ 🔗 Destination Port Address: ${destPortAddress}
163
+ 🛣️ Destination Channel ID: ${destChannelIdString}
164
+ 📈 Sequence: ${sequence}
165
+ -------------------------------------------
166
+ 🧾 TxHash: ${txHash}
167
+ 🔍 Explorer URL: ${url}
168
+ -------------------------------------------\n`);
169
+ console.log(` ⏱️ Waiting for write acknowledgement...`);
170
+ }
171
+ });
172
+
173
+ dispatcher.on("WriteAckPacket", (writerPortAddress, writerChannelId, sequence, ackPacket, event) => {
174
+ const txHash = event.log.transactionHash;
175
+ const writerChannelIdString = hre.ethers.decodeBytes32String(writerChannelId);
176
+ const url = `${explorerUrl}tx/${txHash}`;
177
+ if (filterPacketEvents(writerPortAddress, network)) {
178
+ console.log(`
179
+ -------------------------------------------
180
+ 📦 📝 ACKNOWLEDGEMENT WRITTEN !!! 📦 📝
181
+ -------------------------------------------
182
+ 🔔 Event name: ${event.log.fragment.name}
183
+ ⛓️ Network: ${network}
184
+ 🔗 Destination Port Address: ${writerPortAddress}
185
+ 🛣️ Channel ID: ${writerChannelIdString}
186
+ 📈 Sequence: ${sequence}
187
+ -------------------------------------------
188
+ 🧾 TxHash: ${txHash}
189
+ 🔍 Explorer URL: ${url}
190
+ -------------------------------------------\n`);
191
+ console.log(` ⏱️ Waiting for acknowledgement...`);
192
+ }
193
+ dispatcher.removeAllListeners();
194
+ });
195
+
196
+ dispatcher.on("Acknowledgement", (sourcePortAddress, sourceChannelId, sequence, event) => {
197
+ const txHash = event.log.transactionHash;
198
+ const sourceChannelIdString = hre.ethers.decodeBytes32String(sourceChannelId);
199
+ const url = `${explorerUrl}tx/${txHash}`;
200
+ if (filterPacketEvents(sourcePortAddress, network)) {
201
+ console.log(`
202
+ -------------------------------------------
203
+ 📦 🏁 PACKET IS ACKNOWLEDGED !!! 📦 🏁
204
+ -------------------------------------------
205
+ 🔔 Event name: ${event.log.fragment.name}
206
+ ⛓️ Network: ${network}
207
+ 🔗 Source Port Address: ${sourcePortAddress}
208
+ 🛣️ Source Channel ID: ${sourceChannelIdString}
209
+ 📈 Sequence: ${sequence}
210
+ -------------------------------------------
211
+ 🧾 TxHash: ${txHash}
212
+ 🔍 Explorer URL: ${url}
213
+ -------------------------------------------\n`);
214
+ }
215
+ dispatcher.removeAllListeners();
216
+ });
217
+ }
218
+
219
+ async function setupIbcPacketEventListener() {
220
+ console.log("🔊 Setting up IBC packet event listener...")
221
+ // Get the dispatchers for both source and destination to listen for IBC packet events
222
+ const opDispatcher = await getDispatcher("optimism");
223
+ const baseDispatcher = await getDispatcher("base");
224
+ listenForIbcPacketEvents("optimism", opDispatcher);
225
+ listenForIbcPacketEvents("base", baseDispatcher);
226
+ }
227
+
228
+ async function setupIbcChannelEventListener() {
229
+ console.log("🔊 Setting up IBC channel event listener...")
230
+ const config = require(getConfigPath());
231
+ const opIsSource = config.createChannel.srcChain === "optimism";
232
+ const baseIsSource = config.createChannel.srcChain === "base";
233
+
234
+ // Get the dispatchers for both source and destination to listen for IBC packet events
235
+ const opDispatcher = await getDispatcher("optimism");
236
+ const baseDispatcher = await getDispatcher("base");
237
+ listenForIbcChannelEvents("optimism", opIsSource , opDispatcher);
238
+ listenForIbcChannelEvents("base", baseIsSource, baseDispatcher);
239
+ }
240
+
241
+ module.exports = { listenForIbcChannelEvents, listenForIbcPacketEvents, setupIbcPacketEventListener, setupIbcChannelEventListener };
@@ -0,0 +1,113 @@
1
+ const fs = require('fs');
2
+ const axios = require('axios');
3
+ const hre = require('hardhat');
4
+ const ibcConfig = require("../../ibc.json");
5
+
6
+ // Function to get the path to the configuration file
7
+ function getConfigPath() {
8
+ const path = require('path');
9
+ const configRelativePath = process.env.CONFIG_PATH ? process.env.CONFIG_PATH : 'config.json';
10
+ // console.log(`📔 Using config file at ${configRelativePath}`);
11
+ const configPath = path.join(__dirname, '../..' , configRelativePath);
12
+ return configPath;
13
+ }
14
+
15
+ // Function to update config.json
16
+ function updateConfigDeploy(network, address, isSource) {
17
+ try {
18
+ const configPath = getConfigPath();
19
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
20
+ // Update the config object
21
+ if (!config.isUniversal) {
22
+ if (isSource) {
23
+ config["createChannel"]["srcChain"] = network;
24
+ config["createChannel"]["srcAddr"] = address;
25
+ } else {
26
+ config["createChannel"]["dstChain"] = network;
27
+ config["createChannel"]["dstAddr"] = address;
28
+ }
29
+
30
+ config["sendPacket"][`${network}`]["portAddr"] = address;
31
+ } else if (config.isUniversal){
32
+ // When using the universal channel, we can skip channel creation and instead update the sendUniversalPacket field in the config
33
+ const client = config.proofsEnabled ? 'op-client' : 'sim-client';
34
+ config["sendUniversalPacket"][`${network}`]["portAddr"] = address;
35
+ config["sendUniversalPacket"][`${network}`]["channelId"] = ibcConfig[`${network}`][`${client}`]["universalChannel"];
36
+ }
37
+
38
+ // Write the updated config back to the file
39
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
40
+ } catch (error) {
41
+ console.error('❌ Error updating config:', error);
42
+ }
43
+ }
44
+
45
+ // Function to update config.json
46
+ function updateConfigCreateChannel(network, channel, cpNetwork, cpChannel) {
47
+ try {
48
+ const configPath = getConfigPath();
49
+ const upConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
50
+
51
+ // Update the config object
52
+ upConfig["sendPacket"][`${network}`]["channelId"] = channel;
53
+ upConfig["sendPacket"][`${cpNetwork}`]["channelId"] = cpChannel;
54
+
55
+ // Write the updated config back to the file
56
+ fs.writeFileSync(configPath, JSON.stringify(upConfig, null, 2));
57
+ } catch (error) {
58
+ console.error('❌ Error updating config:', error);
59
+ }
60
+ }
61
+
62
+ async function fetchABI(explorerUrl, contractAddress) {
63
+ try {
64
+ const response = await axios.get(`${explorerUrl}api/v2/smart-contracts/${contractAddress}`);
65
+ if (response.status === 200) {
66
+ const abi = response.data.abi;
67
+ return abi;
68
+ } else {
69
+ console.error(`❌ Failed to fetch ABI, status code: ${response.status}`);
70
+ return null;
71
+ }
72
+ } catch (error) {
73
+ console.error('❌ Error fetching ABI:', error);
74
+ return null;
75
+ }
76
+ }
77
+
78
+ function areAddressesEqual(address1, address2) {
79
+ // Validate input addresses
80
+ if (!hre.ethers.isAddress(address1) || !hre.ethers.isAddress(address2)) {
81
+ throw new Error('❌ One or both addresses are not valid Ethereum addresses');
82
+ }
83
+ // Normalize addresses to checksummed format
84
+
85
+ const checksumAddress1 = hre.ethers.getAddress(address1);
86
+ const checksumAddress2 = hre.ethers.getAddress(address2);
87
+
88
+ // Compare addresses
89
+ const areEqual = checksumAddress1 === checksumAddress2;
90
+ return areEqual;
91
+ }
92
+
93
+ // Helper function to convert an address to a port ID
94
+ function addressToPortId(portPrefix, address) {
95
+ const config = require(getConfigPath());
96
+ const simAddOn = config.proofsEnabled ? '-proofs-1' :'-sim';
97
+ const suffix = address.slice(2);
98
+ return `${portPrefix}${simAddOn}.${suffix}`;
99
+ }
100
+
101
+ function getWhitelistedNetworks() {
102
+ return Object.keys(ibcConfig);
103
+ }
104
+
105
+ module.exports = {
106
+ getConfigPath,
107
+ updateConfigDeploy,
108
+ updateConfigCreateChannel,
109
+ fetchABI,
110
+ areAddressesEqual,
111
+ addressToPortId,
112
+ getWhitelistedNetworks
113
+ };