@mapprotocol/common-contracts 0.3.1 → 0.4.0

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.
package/README.md CHANGED
@@ -12,7 +12,7 @@ npm install @mapprotocol/common-contracts
12
12
 
13
13
  ### BaseImplementation
14
14
 
15
- Abstract base for all upgradeable protocol contracts. Combines UUPS proxy, pausable, and access control in one inheritance.
15
+ Abstract base for all upgradeable protocol contracts (UUPS + Pausable + AccessManaged).
16
16
 
17
17
  ```solidity
18
18
  import "@mapprotocol/common-contracts/contracts/base/BaseImplementation.sol";
@@ -24,12 +24,6 @@ contract MyContract is BaseImplementation {
24
24
  }
25
25
  ```
26
26
 
27
- **Includes:**
28
- - `UUPSUpgradeable` — proxy upgrade pattern
29
- - `PausableUpgradeable` — emergency pause via `trigger()`
30
- - `AccessManagedUpgradeable` — role-based function access
31
- - `getImplementation()` — read current implementation address
32
-
33
27
  ### AuthorityManager
34
28
 
35
29
  Extended `AccessManager` with enumerable role members. One instance per chain controls all protocol contracts.
@@ -38,82 +32,49 @@ Extended `AccessManager` with enumerable role members. One instance per chain co
38
32
  import "@mapprotocol/common-contracts/contracts/AuthorityManager.sol";
39
33
  ```
40
34
 
41
- **Key functions:**
42
- - `grantRole(roleId, account, delay)` — assign role
43
- - `revokeRole(roleId, account)` — remove role
44
- - `setTargetFunctionRole(target, selectors, roleId)` — restrict contract functions to a role
45
- - `getRoleMembers(roleId)` — list all members of a role
46
-
47
35
  ## TypeScript Utilities
48
36
 
49
- ### Deployment
50
-
51
37
  ```typescript
52
- import { getDeploymentByKey, saveDeployment, resolveDeploymentEnv } from "@mapprotocol/common-contracts/utils/deployment";
53
-
54
- // Read deployed address (defaults to <cwd>/deployments/deploy.json)
55
- const addr = await getDeploymentByKey("Bsc", "Gateway");
56
-
57
- // With custom suffix and path
58
- const addr = await getDeploymentByKey("Bsc", "Gateway", { suffix: "main", basePath: "./my-deployments" });
59
-
60
- // Save deployment
61
- await saveDeployment("Bsc", "Gateway", "0x...");
38
+ import { createDeployer } from "@mapprotocol/common-contracts/utils/deployer";
39
+ import { getDeploymentByKey, saveDeployment } from "@mapprotocol/common-contracts/utils/deployRecord";
40
+ import { TronClient, tronToHex, tronFromHex } from "@mapprotocol/common-contracts/utils/tronHelper";
41
+ import { verify } from "@mapprotocol/common-contracts/utils/verifier";
42
+ import { addressToHex } from "@mapprotocol/common-contracts/utils/addressCodec";
62
43
  ```
63
44
 
64
- ### Tron Interaction
45
+ ### Quick Start
65
46
 
66
47
  ```typescript
67
- import { createTronWeb, tronDeploy, getTronContract, tronToHex, tronFromHex } from "@mapprotocol/common-contracts/utils/tronHelper";
68
-
69
- // Address conversion (pure, no RPC needed)
70
- const hex = tronToHex("TXyz..."); // -> "0x..."
71
- const base58 = tronFromHex("0x..."); // -> "TXyz..."
72
-
73
- // Deploy contract on Tron
74
- const tronWeb = createTronWeb({ rpcUrl: "https://api.trongrid.io", privateKey: "..." });
75
- const addr = await tronDeploy(tronWeb, artifacts, "MyContract", [arg1, arg2]);
76
-
77
- // Read-only (no privateKey needed)
78
- const readOnly = createTronWeb({ rpcUrl: "https://api.trongrid.io" });
79
- const contract = await getTronContract(readOnly, artifacts, "MyContract", addr);
48
+ // Unified deployer auto-routes EVM / Tron
49
+ const deployer = createDeployer(hre, { autoVerify: true });
50
+ let result = await deployer.deploy("Gateway", [bridge, owner, wtoken]);
51
+ let proxy = await deployer.deployProxy("Gateway", [admin]);
52
+
53
+ // Deploy record
54
+ const addr = getDeploymentByKey("Bsc", "Gateway", { env: "prod" });
55
+ saveDeployment("Bsc", "Gateway", "0x...", { env: "prod" });
56
+
57
+ // Tron client
58
+ let client = TronClient.fromHre(hre);
59
+ let gw = await client.getContract(hre.artifacts, "Gateway", addr);
60
+ await gw.setWtoken(client.toHex(wtoken)).sendAndWait();
61
+ let val = await gw.wToken().call();
80
62
  ```
81
63
 
82
- ### Address Encoding
83
-
84
- ```typescript
85
- import { addressToHex, isTronAddress, isSolanaChain } from "@mapprotocol/common-contracts/utils/addressCodec";
86
-
87
- // Auto-detect format and convert to hex
88
- addressToHex("0xAbC..."); // EVM -> lowercase hex
89
- addressToHex("TXyz..."); // Tron -> extract 20-byte address
90
- addressToHex("So11111..."); // Solana -> full base58 decode
91
-
92
- // Type checks
93
- isTronAddress("TXyz..."); // true (validates 0x41 prefix byte)
94
- isSolanaChain("Sol"); // true
95
- ```
64
+ See JSDoc in each module's source for full API details and edge cases.
96
65
 
97
66
  ## Forge Script Base
98
67
 
99
- For monorepo projects, `script/Base.s.sol` provides deployment primitives:
100
-
101
68
  ```solidity
102
- import {BaseScript} from "../../common/script/Base.s.sol";
69
+ import {BaseScript} from "@mapprotocol/common-contracts/script/base/Base.s.sol";
103
70
 
104
71
  contract MyDeploy is BaseScript {
105
72
  function run() public broadcast {
106
- // CREATE2 factory deployment (deterministic address)
73
+ (address proxy, address impl) = deployProxy(type(MyContract).creationCode, initData);
107
74
  address addr = deployByFactory("my_salt", type(MyContract).creationCode, abi.encode(arg));
108
-
109
- // Check factory availability
110
- require(isFactoryAvailable(), "no factory on this chain");
111
-
112
- // UUPS proxy upgrade
113
- upgradeProxy(proxyAddr, newImplAddr);
114
-
115
- // Deploy new impl + upgrade in one step
116
75
  deployAndUpgrade(proxyAddr, type(MyContractV2).creationCode);
76
+ address relay = readDeployment("Relay");
77
+ saveDeployment("Gateway", addr);
117
78
  }
118
79
  }
119
80
  ```
@@ -121,43 +82,12 @@ contract MyDeploy is BaseScript {
121
82
  ## Development
122
83
 
123
84
  ```bash
124
- # Build
125
- forge build # Foundry
126
- npm run build:hardhat # Hardhat + TypeChain
127
-
128
- # Test
129
- forge test
130
- forge test --gas-report
131
-
132
- # Format
133
- forge fmt
134
-
135
- # Publish
136
- npm run prepublishOnly # clean + build + typecheck
137
- npm publish
85
+ forge build && forge test # Solidity
86
+ npm run build:hardhat # Hardhat + TypeChain
87
+ npm run build:utils # TypeScript utilities
88
+ npm run prepublishOnly && npm publish
138
89
  ```
139
90
 
140
- ## Package Contents
141
-
142
- | Path | Description |
143
- |------|-------------|
144
- | `contracts/**/*.sol` | Solidity source files |
145
- | `artifacts/**/*.json` | Compiled ABI + bytecode |
146
- | `typechain-types/**/*` | TypeChain generated types |
147
- | `utils/*.ts` | Shared TypeScript utilities |
148
-
149
- ## Requirements
150
-
151
- - Solidity ^0.8.20
152
- - Node.js >= 18
153
- - OpenZeppelin Contracts 5.4.0
154
-
155
91
  ## License
156
92
 
157
93
  MIT
158
-
159
- ## Links
160
-
161
- - [Repository](https://github.com/mapprotocol/mapo-contracts-v2/tree/main/common)
162
- - [Issues](https://github.com/mapprotocol/mapo-contracts-v2/issues)
163
- - [MAP Protocol](https://mapprotocol.io)
package/package.json CHANGED
@@ -1,15 +1,29 @@
1
1
  {
2
2
  "name": "@mapprotocol/common-contracts",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Common contracts for MAP Protocol",
5
5
  "main": "typechain-types/index.js",
6
6
  "types": "typechain-types/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./typechain-types/index.d.ts",
10
+ "default": "./typechain-types/index.js"
11
+ },
12
+ "./utils/*": {
13
+ "types": "./utils/dist/*.d.ts",
14
+ "default": "./utils/dist/*.js"
15
+ },
16
+ "./contracts/*": "./contracts/*",
17
+ "./script/*": "./script/*"
18
+ },
7
19
  "files": [
8
20
  "contracts/**/*.sol",
9
21
  "artifacts/contracts/**/*.json",
10
22
  "!artifacts/contracts/**/*.dbg.json",
11
23
  "typechain-types/**/*",
12
24
  "utils/**/*.ts",
25
+ "utils/dist/**/*",
26
+ "script/base/**/*.sol",
13
27
  "README.md"
14
28
  ],
15
29
  "repository": {
@@ -31,12 +45,13 @@
31
45
  "test": "forge test",
32
46
  "test:hardhat": "hardhat test",
33
47
  "format": "forge fmt",
34
- "clean": "forge clean && hardhat clean && rm -rf typechain-types",
48
+ "build:utils": "cd utils && tsc",
49
+ "clean": "forge clean && hardhat clean && rm -rf typechain-types utils/dist",
35
50
  "compile": "hardhat compile",
36
51
  "typecheck": "tsc --noEmit",
37
52
  "gas-report": "forge test --gas-report",
38
53
  "coverage": "forge coverage",
39
- "prepublishOnly": "npm run clean && npm run build:hardhat && npm run typecheck"
54
+ "prepublishOnly": "npm run clean && npm run build:hardhat && npm run build:utils && npm run typecheck"
40
55
  },
41
56
  "keywords": [
42
57
  "solidity",
@@ -0,0 +1,231 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ import {Script, stdJson, console} from "forge-std/Script.sol";
5
+ import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
6
+ import {IFactory} from "./interfaces/IFactory.sol";
7
+
8
+ /**
9
+ * @title BaseScript
10
+ * @notice Base contract for deployment scripts with full lifecycle support
11
+ * @dev Inherit this in your deployment scripts.
12
+ *
13
+ * Features:
14
+ * - Private key management (mainnet / testnet)
15
+ * - Direct deployment and CREATE2 factory deployment
16
+ * - Proxy deployment (implementation + ERC1967Proxy)
17
+ * - UUPS proxy upgrade
18
+ * - deploy.json record read/write
19
+ *
20
+ * Usage:
21
+ * contract MyDeploy is BaseScript {
22
+ * function run() public broadcast {
23
+ * // Direct deploy
24
+ * address impl = deployDirect(type(MyContract).creationCode, abi.encode(arg));
25
+ *
26
+ * // Factory deploy (deterministic address)
27
+ * address addr = deployByFactory("my_salt", type(MyContract).creationCode, abi.encode(arg));
28
+ *
29
+ * // Proxy deploy (impl + proxy)
30
+ * (address proxy, address impl) = deployProxy(type(MyContract).creationCode, initData);
31
+ * (address proxy, address impl) = deployProxyByFactory("my_salt", type(MyContract).creationCode, initData);
32
+ *
33
+ * // Upgrade
34
+ * upgradeProxy(proxy, newImplAddr);
35
+ * address newImpl = deployAndUpgrade(proxy, type(MyContractV2).creationCode);
36
+ *
37
+ * // Deploy record
38
+ * address relay = readDeployment("Relay");
39
+ * saveDeployment("Gateway", addr);
40
+ * }
41
+ * }
42
+ */
43
+ abstract contract BaseScript is Script {
44
+ IFactory constant private FACTORY = IFactory(0x6258e4d2950757A749a4d4683A7342261ce12471);
45
+ using stdJson for string;
46
+
47
+ address internal broadcaster;
48
+ uint256 private broadcasterPK;
49
+
50
+ constructor() {
51
+ uint256 privateKey;
52
+ if (block.chainid == 212) {
53
+ privateKey = vm.envUint("TESTNET_PRIVATE_KEY");
54
+ } else {
55
+ privateKey = vm.envUint("PRIVATE_KEY");
56
+ }
57
+ broadcaster = vm.addr(privateKey);
58
+ broadcasterPK = privateKey;
59
+ }
60
+
61
+ modifier broadcast() {
62
+ vm.startBroadcast(broadcasterPK);
63
+ _;
64
+ vm.stopBroadcast();
65
+ }
66
+
67
+ // ============================================================
68
+ // Factory (CREATE2) deployment
69
+ // ============================================================
70
+
71
+ /// @notice Deploy contract via CREATE2 factory with deterministic address
72
+ function deployByFactory(
73
+ string memory salt,
74
+ bytes memory creationCode,
75
+ bytes memory constructorArgs
76
+ ) internal returns (address addr) {
77
+ require(address(FACTORY).code.length > 0, "factory not deployed on this chain");
78
+ bytes32 saltHash = keccak256(bytes(salt));
79
+ addr = FACTORY.getAddress(saltHash);
80
+ if (addr.code.length > 0) revert("already deployed");
81
+ bytes memory code = abi.encodePacked(creationCode, constructorArgs);
82
+ FACTORY.deploy(saltHash, code, 0);
83
+ }
84
+
85
+ /// @notice Deploy implementation + proxy via CREATE2 factory
86
+ function deployProxyByFactory(
87
+ string memory salt,
88
+ bytes memory implCreationCode,
89
+ bytes memory initData
90
+ ) internal returns (address proxy, address impl) {
91
+ impl = deployDirect(implCreationCode, bytes(""));
92
+ proxy = deployByFactory(salt, type(ERC1967Proxy).creationCode, abi.encode(impl, initData));
93
+ console.log("Proxy:", proxy);
94
+ console.log("Implementation:", impl);
95
+ }
96
+
97
+ /// @notice Check if the CREATE2 factory is available on this chain
98
+ function isFactoryAvailable() internal view returns (bool) {
99
+ return address(FACTORY).code.length > 0;
100
+ }
101
+
102
+ /// @notice Get the predicted address for a given salt
103
+ function getFactoryAddress(string memory salt) internal view returns (address) {
104
+ require(isFactoryAvailable(), "factory not deployed on this chain");
105
+ return FACTORY.getAddress(keccak256(bytes(salt)));
106
+ }
107
+
108
+ /// @notice Check if a contract is already deployed at the factory address
109
+ function isFactoryDeployed(string memory salt) internal view returns (bool) {
110
+ if (!isFactoryAvailable()) return false;
111
+ return FACTORY.getAddress(keccak256(bytes(salt))).code.length > 0;
112
+ }
113
+
114
+ // ============================================================
115
+ // Direct deployment
116
+ // ============================================================
117
+
118
+ /// @notice Deploy a new contract directly (non-deterministic address)
119
+ function deployDirect(
120
+ bytes memory creationCode,
121
+ bytes memory constructorArgs
122
+ ) internal returns (address addr) {
123
+ bytes memory code = abi.encodePacked(creationCode, constructorArgs);
124
+ assembly {
125
+ addr := create(0, add(code, 0x20), mload(code))
126
+ }
127
+ require(addr != address(0), "deploy failed");
128
+ }
129
+
130
+ /// @notice Deploy implementation + proxy directly
131
+ function deployProxy(
132
+ bytes memory implCreationCode,
133
+ bytes memory initData
134
+ ) internal returns (address proxy, address impl) {
135
+ impl = deployDirect(implCreationCode, bytes(""));
136
+ ERC1967Proxy p = new ERC1967Proxy(impl, initData);
137
+ proxy = address(p);
138
+ console.log("Proxy:", proxy);
139
+ console.log("Implementation:", impl);
140
+ }
141
+
142
+ // ============================================================
143
+ // Upgrade
144
+ // ============================================================
145
+
146
+ /// @notice Upgrade a UUPS proxy to a new implementation
147
+ function upgradeProxy(address proxy, address newImpl) internal {
148
+ address oldImpl = _getImplementation(proxy);
149
+ (bool success,) = proxy.call(
150
+ abi.encodeWithSignature("upgradeToAndCall(address,bytes)", newImpl, bytes(""))
151
+ );
152
+ require(success, "upgrade failed");
153
+ console.log("Upgraded:", oldImpl, "->", newImpl);
154
+ }
155
+
156
+ /// @notice Deploy new implementation and upgrade proxy in one step
157
+ function deployAndUpgrade(address proxy, bytes memory implCreationCode) internal returns (address newImpl) {
158
+ newImpl = deployDirect(implCreationCode, bytes(""));
159
+ upgradeProxy(proxy, newImpl);
160
+ }
161
+
162
+ // ============================================================
163
+ // Deploy record (deploy.json) read/write
164
+ // ============================================================
165
+
166
+ /// @notice Read a deployed address from deployments/deploy.json
167
+ function readDeployment(string memory key) internal view returns (address) {
168
+ (string memory env, string memory chain) = _resolveDeploymentPath();
169
+ return _readDeploymentByPath(env, chain, key);
170
+ }
171
+
172
+ /// @notice Read a deployed address for a specific env and chain
173
+ function _readDeploymentByPath(string memory env, string memory chain, string memory key) internal view returns (address addr) {
174
+ string memory filePath = "deployments/deploy.json";
175
+ if (!vm.exists(filePath)) {
176
+ revert(string(abi.encodePacked("deploy.json not found: ", filePath)));
177
+ }
178
+ string memory json = vm.readFile(filePath);
179
+ // JSON path: .prod.Bsc.Gateway
180
+ string memory jsonPath = string(abi.encodePacked(".", env, ".", chain, ".", key));
181
+ addr = json.readAddress(jsonPath);
182
+ }
183
+
184
+ /// @notice Save a deployed address to deployments/deploy.json
185
+ function saveDeployment(string memory key, address addr) internal {
186
+ (string memory env, string memory chain) = _resolveDeploymentPath();
187
+ string memory filePath = "deployments/deploy.json";
188
+ // JSON path: .prod.Bsc.Gateway
189
+ string memory jsonPath = string(abi.encodePacked(".", env, ".", chain, ".", key));
190
+ string memory json = vm.readFile(filePath);
191
+ bool exists = vm.keyExistsJson(json, jsonPath);
192
+ if (!exists) {
193
+ revert(string(abi.encodePacked("key not found: ", env, ".", chain, ".", key)));
194
+ }
195
+ vm.writeJson(vm.toString(addr), filePath, jsonPath);
196
+ }
197
+
198
+ // ============================================================
199
+ // Internal helpers
200
+ // ============================================================
201
+
202
+ /// @notice Resolve deployment path (env, chain) based on chainId and NETWORK_ENV
203
+ /// @return env "prod", "main", or "test"
204
+ /// @return chain "Mapo", "Bsc", etc.
205
+ function _resolveDeploymentPath() internal view returns (string memory env, string memory chain) {
206
+ uint256 chainId = block.chainid;
207
+ env = vm.envString("NETWORK_ENV"); // required: test/prod/main
208
+
209
+ if (chainId == 212 || chainId == 22776) chain = "Mapo";
210
+ else if (chainId == 11155111 || chainId == 1) chain = "Eth";
211
+ else if (chainId == 97 || chainId == 56) chain = "Bsc";
212
+ else if (chainId == 8453) chain = "Base";
213
+ else if (chainId == 42161) chain = "Arb";
214
+ else if (chainId == 10) chain = "Op";
215
+ else if (chainId == 130) chain = "Uni";
216
+ else if (chainId == 137) chain = "Pol";
217
+ else if (chainId == 196) chain = "Xlayer";
218
+ else revert("unknown chain");
219
+ }
220
+
221
+ /// @notice Read current implementation address from a UUPS proxy
222
+ function _getImplementation(address proxy) internal view returns (address) {
223
+ (bool success, bytes memory data) = proxy.staticcall(
224
+ abi.encodeWithSignature("getImplementation()")
225
+ );
226
+ if (success && data.length == 32) {
227
+ return abi.decode(data, (address));
228
+ }
229
+ return address(0);
230
+ }
231
+ }
@@ -0,0 +1,7 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ interface IFactory {
5
+ function getAddress(bytes32 salt) external view returns (address);
6
+ function deploy(bytes32 salt, bytes memory creationCode, uint256 value) external;
7
+ }
package/utils/deployer.ts CHANGED
@@ -13,12 +13,17 @@ import { verify as _verify } from "./verifier";
13
13
  */
14
14
 
15
15
  export interface DeployerOptions {
16
- autoVerify?: boolean; // auto verify after deploy/upgrade, defaults to false
16
+ /**
17
+ * Auto-verify contracts after deploy/upgrade.
18
+ * Failures are logged as warnings, never thrown — call deployer.verify() for explicit error handling.
19
+ * Defaults to false.
20
+ */
21
+ autoVerify?: boolean;
17
22
  }
18
23
 
19
24
  export interface DeployResult {
20
- address: string; // primary address (0x hex for EVM, base58 for Tron)
21
- hex?: string; // 0x hex (Tron only, EVM same as address)
25
+ address: string; // EVM: 0x hex address. Tron: base58 (T...) address.
26
+ hex?: string; // Tron only: 0x hex address. Undefined on EVM.
22
27
  }
23
28
 
24
29
  export interface DeployProxyResult {
@@ -29,9 +34,16 @@ export interface DeployProxyResult {
29
34
  }
30
35
 
31
36
  export interface Deployer {
37
+ /**
38
+ * Deploy a contract.
39
+ * @param contractName - artifact name
40
+ * @param args - constructor arguments as raw values
41
+ * @param salt - "" or omitted = direct deploy; non-empty string = CREATE2 factory (deterministic address)
42
+ */
32
43
  deploy(contractName: string, args?: any[], salt?: string): Promise<DeployResult>;
33
44
  deployProxy(contractName: string, initArgs?: any[], salt?: string): Promise<DeployProxyResult>;
34
45
  upgrade(contractName: string, proxyAddr: string): Promise<DeployResult>;
46
+ /** Verify explicitly (throws on failure, unlike autoVerify which only warns). */
35
47
  verify(contractName: string, address: string, constructorArgs?: any[], contractPath?: string): Promise<void>;
36
48
  isTron: boolean;
37
49
  network: string;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Convert any address format to hex bytes.
3
+ * - EVM address (0x prefix): return as-is lowercase
4
+ * - Tron address (T prefix, 34 chars, 0x41 byte): convert via tronToHex
5
+ * - Solana/other base58 address: base58 decode to full bytes
6
+ * @param addr - address in any supported format
7
+ */
8
+ export declare function addressToHex(addr: string): string;
9
+ /** Check if a string is valid base58 encoding. */
10
+ export declare function isBase58(addr: string): boolean;
11
+ /** Check if address is Tron format (T prefix, 34 chars, 0x41 first byte after decode). */
12
+ export declare function isTronAddress(addr: string): boolean;
13
+ /** Check if chain name is Solana. */
14
+ export declare function isSolanaChain(chainName: string): boolean;
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.addressToHex = addressToHex;
7
+ exports.isBase58 = isBase58;
8
+ exports.isTronAddress = isTronAddress;
9
+ exports.isSolanaChain = isSolanaChain;
10
+ /**
11
+ * Multi-chain address encoding — converts EVM, Tron, and Solana addresses to hex bytes.
12
+ */
13
+ const bs58_1 = __importDefault(require("bs58"));
14
+ const tronHelper_1 = require("./tronHelper");
15
+ /**
16
+ * Convert any address format to hex bytes.
17
+ * - EVM address (0x prefix): return as-is lowercase
18
+ * - Tron address (T prefix, 34 chars, 0x41 byte): convert via tronToHex
19
+ * - Solana/other base58 address: base58 decode to full bytes
20
+ * @param addr - address in any supported format
21
+ */
22
+ function addressToHex(addr) {
23
+ if (addr.startsWith("0x")) {
24
+ return addr.toLowerCase();
25
+ }
26
+ if (isTronAddress(addr)) {
27
+ return (0, tronHelper_1.tronToHex)(addr);
28
+ }
29
+ if (isBase58(addr)) {
30
+ const decoded = bs58_1.default.decode(addr);
31
+ return "0x" + Buffer.from(decoded).toString("hex");
32
+ }
33
+ throw new Error(`Unknown address format: ${addr}`);
34
+ }
35
+ /** Check if a string is valid base58 encoding. */
36
+ function isBase58(addr) {
37
+ const base58Chars = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
38
+ for (const char of addr) {
39
+ if (!base58Chars.includes(char)) {
40
+ return false;
41
+ }
42
+ }
43
+ return true;
44
+ }
45
+ /** Check if address is Tron format (T prefix, 34 chars, 0x41 first byte after decode). */
46
+ function isTronAddress(addr) {
47
+ if (!addr.startsWith("T") || addr.length !== 34 || !isBase58(addr))
48
+ return false;
49
+ try {
50
+ const decoded = bs58_1.default.decode(addr);
51
+ // Tron: 0x41 (1 byte) + address (20 bytes) + checksum (4 bytes) = 25 bytes
52
+ return decoded.length === 25 && decoded[0] === 0x41;
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ /** Check if chain name is Solana. */
59
+ function isSolanaChain(chainName) {
60
+ return chainName === "Sol" || chainName === "sol_test";
61
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Get codeHash for a contract deployment.
3
+ * @param artifacts - hardhat artifacts (hre.artifacts)
4
+ * @param contractName - contract name (e.g. "Gateway", "AuthorityManager")
5
+ * @param args - constructor arguments array
6
+ */
7
+ export declare function getCodeHash(artifacts: any, contractName: string, args?: any[]): Promise<string>;
8
+ /**
9
+ * Get codeHash for an ERC1967Proxy deployment.
10
+ * @param artifacts - hardhat artifacts (hre.artifacts)
11
+ * @param implAddress - implementation address
12
+ * @param implName - implementation contract name (for encoding initData)
13
+ * @param initArgs - arguments for initialize() function
14
+ */
15
+ export declare function getProxyCodeHash(artifacts: any, implAddress: string, implName: string, initArgs?: any[]): Promise<string>;
16
+ /**
17
+ * Get codeHash for a custom proxy deployment.
18
+ * @param artifacts - hardhat artifacts (hre.artifacts)
19
+ * @param proxyName - proxy contract name (e.g. "MyCustomProxy")
20
+ * @param implAddress - implementation address
21
+ * @param implName - implementation contract name (for encoding initData)
22
+ * @param initArgs - arguments for initialize() function
23
+ */
24
+ export declare function getCustomProxyCodeHash(artifacts: any, proxyName: string, implAddress: string, implName: string, initArgs?: any[]): Promise<string>;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCodeHash = getCodeHash;
4
+ exports.getProxyCodeHash = getProxyCodeHash;
5
+ exports.getCustomProxyCodeHash = getCustomProxyCodeHash;
6
+ /**
7
+ * Calculate creationCode hash for CREATE2 address prediction.
8
+ */
9
+ const { keccak256, Interface } = require("ethers");
10
+ /**
11
+ * Get codeHash for a contract deployment.
12
+ * @param artifacts - hardhat artifacts (hre.artifacts)
13
+ * @param contractName - contract name (e.g. "Gateway", "AuthorityManager")
14
+ * @param args - constructor arguments array
15
+ */
16
+ async function getCodeHash(artifacts, contractName, args = []) {
17
+ const artifact = await artifacts.readArtifact(contractName);
18
+ let bytecode = artifact.bytecode;
19
+ if (!bytecode.startsWith("0x"))
20
+ bytecode = "0x" + bytecode;
21
+ if (args.length > 0) {
22
+ const iface = new Interface(artifact.abi);
23
+ const encoded = iface.encodeDeploy(args);
24
+ return keccak256(bytecode + encoded.slice(2));
25
+ }
26
+ return keccak256(bytecode);
27
+ }
28
+ /**
29
+ * Get codeHash for an ERC1967Proxy deployment.
30
+ * @param artifacts - hardhat artifacts (hre.artifacts)
31
+ * @param implAddress - implementation address
32
+ * @param implName - implementation contract name (for encoding initData)
33
+ * @param initArgs - arguments for initialize() function
34
+ */
35
+ async function getProxyCodeHash(artifacts, implAddress, implName, initArgs = []) {
36
+ return getCustomProxyCodeHash(artifacts, "ERC1967Proxy", implAddress, implName, initArgs);
37
+ }
38
+ /**
39
+ * Get codeHash for a custom proxy deployment.
40
+ * @param artifacts - hardhat artifacts (hre.artifacts)
41
+ * @param proxyName - proxy contract name (e.g. "MyCustomProxy")
42
+ * @param implAddress - implementation address
43
+ * @param implName - implementation contract name (for encoding initData)
44
+ * @param initArgs - arguments for initialize() function
45
+ */
46
+ async function getCustomProxyCodeHash(artifacts, proxyName, implAddress, implName, initArgs = []) {
47
+ const proxyArtifact = await artifacts.readArtifact(proxyName);
48
+ let bytecode = proxyArtifact.bytecode;
49
+ if (!bytecode.startsWith("0x"))
50
+ bytecode = "0x" + bytecode;
51
+ let initData = "0x";
52
+ if (initArgs.length > 0) {
53
+ const implArtifact = await artifacts.readArtifact(implName);
54
+ const iface = new Interface(implArtifact.abi);
55
+ initData = iface.encodeFunctionData("initialize", initArgs);
56
+ }
57
+ const { AbiCoder } = require("ethers");
58
+ const constructorArgs = AbiCoder.defaultAbiCoder().encode(["address", "bytes"], [implAddress, initData]);
59
+ return keccak256(bytecode + constructorArgs.slice(2));
60
+ }