@mapprotocol/common-contracts 0.3.1 → 0.3.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapprotocol/common-contracts",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Common contracts for MAP Protocol",
5
5
  "main": "typechain-types/index.js",
6
6
  "types": "typechain-types/index.d.ts",
@@ -10,6 +10,7 @@
10
10
  "!artifacts/contracts/**/*.dbg.json",
11
11
  "typechain-types/**/*",
12
12
  "utils/**/*.ts",
13
+ "utils/dist/**/*",
13
14
  "README.md"
14
15
  ],
15
16
  "repository": {
@@ -31,12 +32,13 @@
31
32
  "test": "forge test",
32
33
  "test:hardhat": "hardhat test",
33
34
  "format": "forge fmt",
34
- "clean": "forge clean && hardhat clean && rm -rf typechain-types",
35
+ "build:utils": "cd utils && tsc",
36
+ "clean": "forge clean && hardhat clean && rm -rf typechain-types utils/dist",
35
37
  "compile": "hardhat compile",
36
38
  "typecheck": "tsc --noEmit",
37
39
  "gas-report": "forge test --gas-report",
38
40
  "coverage": "forge coverage",
39
- "prepublishOnly": "npm run clean && npm run build:hardhat && npm run typecheck"
41
+ "prepublishOnly": "npm run clean && npm run build:hardhat && npm run build:utils && npm run typecheck"
40
42
  },
41
43
  "keywords": [
42
44
  "solidity",
@@ -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
+ }
@@ -0,0 +1,37 @@
1
+ export interface DeploymentPath {
2
+ env: string;
3
+ chain: string;
4
+ }
5
+ export interface DeploymentOptions {
6
+ basePath?: string;
7
+ env: string;
8
+ }
9
+ /**
10
+ * Resolve deployment path from network name and env.
11
+ * @param network - hardhat network name (e.g. "Bsc", "Mapo_test", "Tron")
12
+ * @param env - deployment environment: "prod", "main", "test"
13
+ * @returns { env, chain } for deploy.json lookup
14
+ */
15
+ export declare function resolveDeploymentPath(network: string, env: string): DeploymentPath;
16
+ /**
17
+ * Read a deployed contract address from deploy.json.
18
+ * @param network - hardhat network name
19
+ * @param key - contract key (e.g. "Gateway", "Authority")
20
+ * @param opts - optional basePath and env overrides
21
+ */
22
+ export declare function getDeploymentByKey(network: string, key: string, opts: DeploymentOptions): Promise<string>;
23
+ /**
24
+ * Check if a contract address exists and is valid in deploy.json.
25
+ * @param network - hardhat network name
26
+ * @param key - contract key
27
+ * @param opts - optional basePath and env overrides
28
+ */
29
+ export declare function hasDeployment(network: string, key: string, opts: DeploymentOptions): Promise<boolean>;
30
+ /**
31
+ * Save a deployed contract address to deploy.json.
32
+ * @param network - hardhat network name
33
+ * @param key - contract key (e.g. "Gateway")
34
+ * @param addr - deployed address
35
+ * @param opts - optional basePath and env overrides
36
+ */
37
+ export declare function saveDeployment(network: string, key: string, addr: string, opts: DeploymentOptions): Promise<void>;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveDeploymentPath = resolveDeploymentPath;
4
+ exports.getDeploymentByKey = getDeploymentByKey;
5
+ exports.hasDeployment = hasDeployment;
6
+ exports.saveDeployment = saveDeployment;
7
+ /**
8
+ * Deploy record — read/write deployed contract addresses from deploy.json
9
+ *
10
+ * Structure:
11
+ * {
12
+ * "prod": { "Mapo": { "Relay": "0x..." }, "Bsc": { "Gateway": "0x..." } },
13
+ * "main": { "Mapo": { "Relay": "0x..." } },
14
+ * "test": { "Mapo": { "Relay": "0x..." } }
15
+ * }
16
+ */
17
+ let fs = require("fs");
18
+ let path = require("path");
19
+ function defaultDeployPath() {
20
+ return path.join(process.cwd(), "deployments");
21
+ }
22
+ /**
23
+ * Resolve deployment path from network name and env.
24
+ * @param network - hardhat network name (e.g. "Bsc", "Mapo_test", "Tron")
25
+ * @param env - deployment environment: "prod", "main", "test"
26
+ * @returns { env, chain } for deploy.json lookup
27
+ */
28
+ function resolveDeploymentPath(network, env) {
29
+ // Strip _test suffix from network name to get chain name
30
+ const chain = network.replace(/_?test$/i, "");
31
+ return { env, chain: chain.charAt(0).toUpperCase() + chain.slice(1) };
32
+ }
33
+ /**
34
+ * Read a deployed contract address from deploy.json.
35
+ * @param network - hardhat network name
36
+ * @param key - contract key (e.g. "Gateway", "Authority")
37
+ * @param opts - optional basePath and env overrides
38
+ */
39
+ async function getDeploymentByKey(network, key, opts) {
40
+ const deployPath = opts.basePath || defaultDeployPath();
41
+ const { env, chain } = resolveDeploymentPath(network, opts.env);
42
+ const data = await readDeployFile(deployPath);
43
+ const addr = data[env]?.[chain]?.[key];
44
+ if (!addr)
45
+ throw new Error(`no ${key} deployment in ${env}.${chain}`);
46
+ return addr;
47
+ }
48
+ /**
49
+ * Check if a contract address exists and is valid in deploy.json.
50
+ * @param network - hardhat network name
51
+ * @param key - contract key
52
+ * @param opts - optional basePath and env overrides
53
+ */
54
+ async function hasDeployment(network, key, opts) {
55
+ try {
56
+ const deployPath = opts.basePath || defaultDeployPath();
57
+ const { env, chain } = resolveDeploymentPath(network, opts.env);
58
+ const data = await readDeployFile(deployPath);
59
+ const addr = data[env]?.[chain]?.[key];
60
+ return !!addr && addr.length > 2 && addr !== "0x";
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ }
66
+ /**
67
+ * Save a deployed contract address to deploy.json.
68
+ * @param network - hardhat network name
69
+ * @param key - contract key (e.g. "Gateway")
70
+ * @param addr - deployed address
71
+ * @param opts - optional basePath and env overrides
72
+ */
73
+ async function saveDeployment(network, key, addr, opts) {
74
+ const deployPath = opts.basePath || defaultDeployPath();
75
+ const { env, chain } = resolveDeploymentPath(network, opts.env);
76
+ const data = await readDeployFile(deployPath);
77
+ if (!data[env])
78
+ data[env] = {};
79
+ if (!data[env][chain])
80
+ data[env][chain] = {};
81
+ data[env][chain][key] = addr;
82
+ const filePath = path.resolve(deployPath, "deploy.json");
83
+ await ensureDir(deployPath);
84
+ await fs.promises.writeFile(filePath, JSON.stringify(data, null, "\t"));
85
+ }
86
+ async function readDeployFile(basePath) {
87
+ const filePath = path.resolve(basePath, "deploy.json");
88
+ try {
89
+ const rawdata = await fs.promises.readFile(filePath, "utf-8");
90
+ return JSON.parse(rawdata);
91
+ }
92
+ catch {
93
+ return {};
94
+ }
95
+ }
96
+ async function ensureDir(dirPath) {
97
+ const absPath = path.resolve(dirPath);
98
+ try {
99
+ await fs.promises.stat(absPath);
100
+ }
101
+ catch {
102
+ await fs.promises.mkdir(absPath, { recursive: true });
103
+ }
104
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Unified deployer — auto-routes to EVM or Tron based on network name.
3
+ *
4
+ * Usage in hardhat tasks:
5
+ * const deployer = createDeployer(hre, { autoVerify: true });
6
+ * let addr = await deployer.deploy("Gateway", [admin], salt);
7
+ * let { proxy, implementation } = await deployer.deployProxy("Gateway", [admin], salt);
8
+ * let newImpl = await deployer.upgrade("Gateway", proxyAddr);
9
+ */
10
+ export interface DeployerOptions {
11
+ autoVerify?: boolean;
12
+ }
13
+ export interface DeployResult {
14
+ address: string;
15
+ hex?: string;
16
+ }
17
+ export interface DeployProxyResult {
18
+ proxy: string;
19
+ implementation: string;
20
+ proxyHex?: string;
21
+ implementationHex?: string;
22
+ }
23
+ export interface Deployer {
24
+ deploy(contractName: string, args?: any[], salt?: string): Promise<DeployResult>;
25
+ deployProxy(contractName: string, initArgs?: any[], salt?: string): Promise<DeployProxyResult>;
26
+ upgrade(contractName: string, proxyAddr: string): Promise<DeployResult>;
27
+ verify(contractName: string, address: string, constructorArgs?: any[], contractPath?: string): Promise<void>;
28
+ isTron: boolean;
29
+ network: string;
30
+ }
31
+ /**
32
+ * Create a unified deployer that auto-routes to EVM or Tron based on network.
33
+ * @param hre - hardhat runtime environment
34
+ * @param opts - options (autoVerify: auto-verify after deploy, defaults to false)
35
+ */
36
+ export declare function createDeployer(hre: any, opts?: DeployerOptions): Deployer;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDeployer = createDeployer;
4
+ const tronHelper_1 = require("./tronHelper");
5
+ const evmHelper_1 = require("./evmHelper");
6
+ const verifier_1 = require("./verifier");
7
+ /**
8
+ * Create a unified deployer that auto-routes to EVM or Tron based on network.
9
+ * @param hre - hardhat runtime environment
10
+ * @param opts - options (autoVerify: auto-verify after deploy, defaults to false)
11
+ */
12
+ function createDeployer(hre, opts = {}) {
13
+ const network = hre.network.name;
14
+ const isTron = (0, tronHelper_1.isTronNetwork)(network);
15
+ const autoVerify = opts.autoVerify || false;
16
+ async function tryVerify(contractName, address, constructorArgs, contractPath) {
17
+ if (!autoVerify)
18
+ return;
19
+ try {
20
+ await (0, verifier_1.verify)(hre, { contractName, address, constructorArgs, contractPath });
21
+ }
22
+ catch (e) {
23
+ console.log(`[warn] auto-verify failed: ${e.message || e}`);
24
+ }
25
+ }
26
+ if (isTron) {
27
+ const client = tronHelper_1.TronClient.fromHre(hre);
28
+ return {
29
+ isTron: true,
30
+ network,
31
+ async deploy(contractName, args = [], salt = "") {
32
+ let result = await client.deploy(hre.artifacts, contractName, args, salt);
33
+ await tryVerify(contractName, result.base58, args);
34
+ return { address: result.base58, hex: result.hex };
35
+ },
36
+ async deployProxy(contractName, initArgs = [], salt = "") {
37
+ let result = await client.deployProxy(hre.artifacts, contractName, initArgs, salt);
38
+ await tryVerify(contractName, result.implementation.base58);
39
+ return {
40
+ proxy: result.proxy.base58,
41
+ implementation: result.implementation.base58,
42
+ proxyHex: result.proxy.hex,
43
+ implementationHex: result.implementation.hex,
44
+ };
45
+ },
46
+ async upgrade(contractName, proxyAddr) {
47
+ let result = await client.upgradeProxy(hre.artifacts, contractName, proxyAddr);
48
+ await tryVerify(contractName, result.base58);
49
+ return { address: result.base58, hex: result.hex };
50
+ },
51
+ async verify(contractName, address, constructorArgs, contractPath) {
52
+ await (0, verifier_1.verify)(hre, { contractName, address, constructorArgs, contractPath });
53
+ },
54
+ };
55
+ }
56
+ // EVM
57
+ const { ethers, artifacts } = hre;
58
+ return {
59
+ isTron: false,
60
+ network,
61
+ async deploy(contractName, args = [], salt = "") {
62
+ let addr = await (0, evmHelper_1.evmDeploy)(ethers, artifacts, contractName, args, salt);
63
+ await tryVerify(contractName, addr, args);
64
+ return { address: addr };
65
+ },
66
+ async deployProxy(contractName, initArgs = [], salt = "") {
67
+ let result = await (0, evmHelper_1.evmDeployProxy)(ethers, artifacts, contractName, initArgs, salt);
68
+ await tryVerify(contractName, result.implementation);
69
+ return { proxy: result.proxy, implementation: result.implementation };
70
+ },
71
+ async upgrade(contractName, proxyAddr) {
72
+ let addr = await (0, evmHelper_1.evmUpgradeProxy)(ethers, contractName, proxyAddr);
73
+ await tryVerify(contractName, addr);
74
+ return { address: addr };
75
+ },
76
+ async verify(contractName, address, constructorArgs, contractPath) {
77
+ await (0, verifier_1.verify)(hre, { contractName, address, constructorArgs, contractPath });
78
+ },
79
+ };
80
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Deploy contract on EVM. If salt is provided, uses CREATE2 factory for deterministic address.
3
+ * @param ethers - ethers from hardhat runtime (hre.ethers)
4
+ * @param artifacts - hardhat artifacts (hre.artifacts)
5
+ * @param contractName - contract name to deploy
6
+ * @param args - constructor arguments array
7
+ * @param salt - optional CREATE2 salt for deterministic address
8
+ * @returns deployed contract address (0x hex)
9
+ */
10
+ export declare function evmDeploy(ethers: any, artifacts: any, contractName: string, args?: any[], salt?: string): Promise<string>;
11
+ /**
12
+ * Deploy implementation + ERC1967 proxy in one step.
13
+ * If salt is provided, proxy is deployed via factory.
14
+ * @param ethers - ethers from hardhat runtime (hre.ethers)
15
+ * @param artifacts - hardhat artifacts (hre.artifacts)
16
+ * @param contractName - implementation contract name
17
+ * @param initArgs - initialize() function arguments
18
+ * @param salt - optional CREATE2 salt for proxy
19
+ * @returns { proxy, implementation } addresses
20
+ */
21
+ export declare function evmDeployProxy(ethers: any, artifacts: any, contractName: string, initArgs?: any[], salt?: string): Promise<{
22
+ proxy: string;
23
+ implementation: string;
24
+ }>;
25
+ /**
26
+ * Upgrade a UUPS proxy to a new implementation.
27
+ * Deploys new implementation, then calls upgradeToAndCall on the proxy.
28
+ * @param ethers - ethers from hardhat runtime (hre.ethers)
29
+ * @param contractName - new implementation contract name
30
+ * @param proxyAddr - proxy address to upgrade
31
+ * @returns new implementation address
32
+ */
33
+ export declare function evmUpgradeProxy(ethers: any, contractName: string, proxyAddr: string): Promise<string>;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.evmDeploy = evmDeploy;
4
+ exports.evmDeployProxy = evmDeployProxy;
5
+ exports.evmUpgradeProxy = evmUpgradeProxy;
6
+ /**
7
+ * Deploy contract on EVM. If salt is provided, uses CREATE2 factory for deterministic address.
8
+ * @param ethers - ethers from hardhat runtime (hre.ethers)
9
+ * @param artifacts - hardhat artifacts (hre.artifacts)
10
+ * @param contractName - contract name to deploy
11
+ * @param args - constructor arguments array
12
+ * @param salt - optional CREATE2 salt for deterministic address
13
+ * @returns deployed contract address (0x hex)
14
+ */
15
+ async function evmDeploy(ethers, artifacts, contractName, args = [], salt = "") {
16
+ if (salt) {
17
+ const { evmDeployByFactory } = require("./factory");
18
+ const artifact = await artifacts.readArtifact(contractName);
19
+ const constructorArgs = args.length > 0
20
+ ? ethers.AbiCoder.defaultAbiCoder().encode(artifact.abi
21
+ .find((x) => x.type === "constructor")
22
+ ?.inputs.map((i) => i.type) || [], args)
23
+ : "0x";
24
+ return evmDeployByFactory(ethers, salt, artifact.bytecode, constructorArgs);
25
+ }
26
+ const [deployer] = await ethers.getSigners();
27
+ console.log("deploy address is:", deployer.address);
28
+ const ContractFactory = await ethers.getContractFactory(contractName);
29
+ const contract = await (await ContractFactory.deploy(...args)).waitForDeployment();
30
+ const addr = await contract.getAddress();
31
+ console.log(`${contractName} deployed: ${addr}`);
32
+ return addr;
33
+ }
34
+ /**
35
+ * Deploy implementation + ERC1967 proxy in one step.
36
+ * If salt is provided, proxy is deployed via factory.
37
+ * @param ethers - ethers from hardhat runtime (hre.ethers)
38
+ * @param artifacts - hardhat artifacts (hre.artifacts)
39
+ * @param contractName - implementation contract name
40
+ * @param initArgs - initialize() function arguments
41
+ * @param salt - optional CREATE2 salt for proxy
42
+ * @returns { proxy, implementation } addresses
43
+ */
44
+ async function evmDeployProxy(ethers, artifacts, contractName, initArgs = [], salt = "") {
45
+ const ImplFactory = await ethers.getContractFactory(contractName);
46
+ const impl = await (await ImplFactory.deploy()).waitForDeployment();
47
+ const implAddr = await impl.getAddress();
48
+ console.log(`${contractName} implementation: ${implAddr}`);
49
+ const initData = ImplFactory.interface.encodeFunctionData("initialize", initArgs);
50
+ let proxyAddr;
51
+ if (salt) {
52
+ const { evmDeployByFactory } = require("./factory");
53
+ const proxyArtifact = await artifacts.readArtifact("ERC1967Proxy");
54
+ const constructorArgs = ethers.AbiCoder.defaultAbiCoder().encode(["address", "bytes"], [implAddr, initData]);
55
+ proxyAddr = await evmDeployByFactory(ethers, salt, proxyArtifact.bytecode, constructorArgs);
56
+ }
57
+ else {
58
+ const ProxyFactory = await ethers.getContractFactory("ERC1967Proxy");
59
+ const proxy = await (await ProxyFactory.deploy(implAddr, initData)).waitForDeployment();
60
+ proxyAddr = await proxy.getAddress();
61
+ }
62
+ console.log(`${contractName} proxy: ${proxyAddr}`);
63
+ return { proxy: proxyAddr, implementation: implAddr };
64
+ }
65
+ /**
66
+ * Upgrade a UUPS proxy to a new implementation.
67
+ * Deploys new implementation, then calls upgradeToAndCall on the proxy.
68
+ * @param ethers - ethers from hardhat runtime (hre.ethers)
69
+ * @param contractName - new implementation contract name
70
+ * @param proxyAddr - proxy address to upgrade
71
+ * @returns new implementation address
72
+ */
73
+ async function evmUpgradeProxy(ethers, contractName, proxyAddr) {
74
+ const [deployer] = await ethers.getSigners();
75
+ const ImplFactory = await ethers.getContractFactory(contractName);
76
+ const impl = await (await ImplFactory.deploy()).waitForDeployment();
77
+ const implAddr = await impl.getAddress();
78
+ const proxy = await ethers.getContractAt("BaseImplementation", proxyAddr, deployer);
79
+ const oldImpl = await proxy.getImplementation();
80
+ await (await proxy.upgradeToAndCall(implAddr, "0x")).wait();
81
+ console.log(`${contractName} upgraded: ${oldImpl} -> ${implAddr}`);
82
+ return implAddr;
83
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Deploy contract via CREATE3 factory on EVM chains.
3
+ * Address only depends on salt, not bytecode.
4
+ * @param ethers - ethers from hardhat runtime (hre.ethers)
5
+ * @param salt - human-readable salt string
6
+ * @param bytecode - contract bytecode (artifact.bytecode)
7
+ * @param constructorArgs - ABI-encoded constructor arguments
8
+ * @returns deployed contract address
9
+ */
10
+ export declare function evmDeployByFactory(ethers: any, salt: string, bytecode: string, constructorArgs?: string): Promise<string>;
11
+ /**
12
+ * Get predicted factory address for a salt on EVM (CREATE3 — only needs salt).
13
+ * @param ethers - ethers from hardhat runtime
14
+ * @param salt - human-readable salt string
15
+ */
16
+ export declare function evmGetFactoryAddress(ethers: any, salt: string): Promise<string>;
17
+ /**
18
+ * Deploy contract via CREATE2 factory on Tron.
19
+ * Address depends on salt + creationCode (bytecode + constructor args).
20
+ * @param tronWeb - initialized tronweb instance
21
+ * @param artifacts - hardhat artifacts
22
+ * @param contractName - contract name to deploy
23
+ * @param salt - human-readable salt string
24
+ * @param args - constructor arguments array
25
+ * @param feeLimit - tron fee limit
26
+ * @returns deployed contract address (0x-prefixed hex)
27
+ */
28
+ export declare function tronDeployByFactory(tronWeb: any, artifacts: any, contractName: string, salt: string, args?: any[], feeLimit?: number): Promise<string>;
29
+ /**
30
+ * Get predicted factory address for a salt on Tron (CREATE2 — needs salt + codeHash).
31
+ * @param tronWeb - initialized tronweb instance
32
+ * @param salt - human-readable salt string
33
+ * @param codeHash - keccak256 of creationCode (bytecode + constructor args)
34
+ * @returns address in base58 format
35
+ */
36
+ export declare function tronGetFactoryAddress(tronWeb: any, salt: string, codeHash: string): Promise<string>;