@skalenetwork/upgrade-tools 4.0.0-develop.2 → 4.0.0-ownership-helpers.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.
@@ -0,0 +1,14 @@
1
+ import { Instance } from "@skalenetwork/skale-contracts-ethers-v6";
2
+ export declare class OwnershipAdmin {
3
+ private instance;
4
+ private contractMetadata;
5
+ private contractNames;
6
+ private isMetadataLoaded;
7
+ private readonly;
8
+ constructor(instance: Instance, contractNames: string[], readonly?: boolean);
9
+ loadContractMetadata(confirmFindings?: boolean): Promise<void>;
10
+ private confirmMetadata;
11
+ private displayFindings;
12
+ private handleUserRejection;
13
+ private groupMetadataByPattern;
14
+ }
@@ -0,0 +1,83 @@
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.OwnershipAdmin = void 0;
7
+ const utils_1 = require("./utils");
8
+ const permission_utils_1 = require("./permission-utils");
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ class OwnershipAdmin {
11
+ constructor(instance, contractNames, readonly = true) {
12
+ this.instance = instance;
13
+ this.contractMetadata = new Map();
14
+ this.isMetadataLoaded = false;
15
+ // If true, does not allow to send transactions to blockchain
16
+ this.readonly = readonly;
17
+ this.contractNames = contractNames;
18
+ }
19
+ async loadContractMetadata(confirmFindings = true) {
20
+ await Promise.all(this.contractNames.map(async (contractName) => {
21
+ // Already checks the contractName is in the instance
22
+ const address = await this.instance.getContractAddress(contractName);
23
+ if (!this.contractMetadata.has(address)) {
24
+ const pattern = await (0, utils_1.detectPattern)(address);
25
+ const details = {
26
+ address,
27
+ name: contractName,
28
+ pattern,
29
+ permissionModel: await (0, permission_utils_1.getPermissionModels)(address)
30
+ };
31
+ this.contractMetadata.set(address, details);
32
+ }
33
+ }));
34
+ this.isMetadataLoaded = true;
35
+ if (this.contractMetadata.size !== this.contractNames.length) {
36
+ throw new Error("Some contract names did not yield metadata. Names duplicated? Aborting...");
37
+ }
38
+ if (confirmFindings) {
39
+ await this.confirmMetadata();
40
+ }
41
+ }
42
+ async confirmMetadata() {
43
+ this.displayFindings();
44
+ const userConfirmed = await (0, utils_1.promptUserConfirmation)();
45
+ if (!userConfirmed) {
46
+ this.handleUserRejection();
47
+ }
48
+ console.log(chalk_1.default.green("\nUser confirmed. Proceeding...\n"));
49
+ }
50
+ displayFindings() {
51
+ console.log(chalk_1.default.cyan("\n=== Contract Pattern Detection Results ===\n"));
52
+ const groupedByPattern = this.groupMetadataByPattern();
53
+ for (const [pattern, contracts] of Object.entries(groupedByPattern)) {
54
+ const minContractsToDisplay = 0;
55
+ if (contracts.length > minContractsToDisplay) {
56
+ console.log(chalk_1.default.bold(`\n${pattern} Pattern (${contracts.length} contracts):`));
57
+ for (const contract of contracts) {
58
+ console.log(chalk_1.default.gray(` - ${contract.name} (${contract.address}) - Permission Models: ${contract.permissionModel?.join(", ") || "None"}`));
59
+ }
60
+ }
61
+ }
62
+ console.log(chalk_1.default.cyan("\n==========================================\n"));
63
+ }
64
+ handleUserRejection() {
65
+ console.log(chalk_1.default.yellow("\nUser did not confirm. Aborting and clearing metadata..."));
66
+ this.contractMetadata.clear();
67
+ this.isMetadataLoaded = false;
68
+ throw new Error("User aborted the operation. Metadata has been cleared.");
69
+ }
70
+ groupMetadataByPattern() {
71
+ const grouped = Object.values(utils_1.Pattern).
72
+ reduce((acc, pattern) => {
73
+ acc[pattern] = [];
74
+ return acc;
75
+ }, {});
76
+ for (const metadata of this.contractMetadata.values()) {
77
+ grouped[metadata.pattern].push(metadata);
78
+ }
79
+ return grouped;
80
+ }
81
+ }
82
+ exports.OwnershipAdmin = OwnershipAdmin;
83
+ //# sourceMappingURL=ownershipAdmin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownershipAdmin.js","sourceRoot":"","sources":["../../../src/ownership-transfer/ownershipAdmin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { AddressLike } from "ethers";
2
+ export declare enum PermissionModel {
3
+ OWNABLE = "OWNABLE",
4
+ ROLE_BASED = "ROLE_BASED",
5
+ ACCESS_MANAGED = "ACCESS_MANAGED"
6
+ }
7
+ export declare const isOwnable: (contractAddress: AddressLike) => Promise<boolean>;
8
+ export declare const isAccessControl: (contractAddress: AddressLike) => Promise<boolean>;
9
+ export declare const isAccessManaged: (contractAddress: AddressLike) => Promise<boolean>;
10
+ export declare const transferOwnership: (contractAddress: AddressLike, newOwner: AddressLike) => Promise<{
11
+ to: string;
12
+ data: string;
13
+ } | boolean>;
14
+ export declare const getPermissionModels: (address: AddressLike) => Promise<PermissionModel[]>;
@@ -0,0 +1,176 @@
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.getPermissionModels = exports.transferOwnership = exports.isAccessManaged = exports.isAccessControl = exports.isOwnable = exports.PermissionModel = void 0;
7
+ const ethers_1 = require("ethers");
8
+ const utils_1 = require("./utils");
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const hardhat_1 = require("hardhat");
11
+ var PermissionModel;
12
+ (function (PermissionModel) {
13
+ // Does not fully complete the process of Ownable2Step
14
+ PermissionModel["OWNABLE"] = "OWNABLE";
15
+ // This works also for ACCESS_MANAGER contracts - i.e they are ROLE_BASED
16
+ PermissionModel["ROLE_BASED"] = "ROLE_BASED";
17
+ PermissionModel["ACCESS_MANAGED"] = "ACCESS_MANAGED";
18
+ })(PermissionModel || (exports.PermissionModel = PermissionModel = {}));
19
+ /*
20
+ * ABI for Ownable interface - includes owner() function
21
+ */
22
+ const OWNABLE_ABI = [
23
+ "function transferOwnership(address newOwner)",
24
+ "function owner() view returns (address)"
25
+ ];
26
+ /*
27
+ * ABI for AccessControl interface
28
+ */
29
+ const ACCESS_CONTROL_ABI = [
30
+ "function hasRole(bytes32 role, address account) view returns (bool)",
31
+ "function grantRole(bytes32 role, address account)",
32
+ "function revokeRole(bytes32 role, address account)"
33
+ ];
34
+ /*
35
+ * ABI for AccessManaged interface - includes authority() function
36
+ */
37
+ const ACCESS_MANAGED_ABI = [
38
+ "function authority() view returns (address)"
39
+ ];
40
+ const verifyOwnableInterface = async (contract, contractAddress) => {
41
+ /*
42
+ * Verify owner() exists and returns non-zero address
43
+ */
44
+ const owner = await contract.owner();
45
+ if (owner === hardhat_1.ethers.ZeroAddress) {
46
+ return false;
47
+ }
48
+ /*
49
+ * Verify transferOwnership() exists by checking bytecode
50
+ */
51
+ return await (0, utils_1.hasFunctionSelector)(contractAddress, "transferOwnership(address)");
52
+ };
53
+ /*
54
+ * Checks if a contract implements the Ownable interface.
55
+ * A contract is considered Ownable if it has both owner() and transferOwnership() functions.
56
+ * We verify this by reading the current owner and doing a static call (dry run) of transferOwnership.
57
+ *
58
+ * @param contractAddress - The address of the contract to check
59
+ * @returns true if the contract is Ownable, false otherwise
60
+ */
61
+ const isOwnable = async (contractAddress) => {
62
+ try {
63
+ const resolvedAddress = await hardhat_1.ethers.resolveAddress(contractAddress);
64
+ if (!await (0, utils_1.isContractAddress)(resolvedAddress)) {
65
+ return false;
66
+ }
67
+ const contract = new ethers_1.Contract(resolvedAddress, OWNABLE_ABI, hardhat_1.ethers.provider);
68
+ return await verifyOwnableInterface(contract, resolvedAddress);
69
+ }
70
+ catch {
71
+ return false;
72
+ }
73
+ };
74
+ exports.isOwnable = isOwnable;
75
+ const verifyAccessControlInterface = async (contract, contractAddress) => {
76
+ /*
77
+ * Verify hasRole() view function exists
78
+ */
79
+ await contract.hasRole(hardhat_1.ethers.ZeroHash, hardhat_1.ethers.ZeroAddress);
80
+ /*
81
+ * Verify grantRole() exists by checking bytecode
82
+ */
83
+ return await (0, utils_1.hasFunctionSelector)(contractAddress, "grantRole(bytes32,address)") &&
84
+ await (0, utils_1.hasFunctionSelector)(contractAddress, "revokeRole(bytes32,address)");
85
+ };
86
+ /*
87
+ * Checks if a contract implements the AccessControl interface.
88
+ * A contract is considered AccessControl if it has hasRole() and grantRole() functions.
89
+ * We verify this by calling hasRole() and doing a static call (dry run) of grantRole().
90
+ *
91
+ * @param contractAddress - The address of the contract to check
92
+ * @returns true if the contract is AccessControl, false otherwise
93
+ */
94
+ const isAccessControl = async (contractAddress) => {
95
+ try {
96
+ const resolvedAddress = await hardhat_1.ethers.resolveAddress(contractAddress);
97
+ if (!await (0, utils_1.isContractAddress)(resolvedAddress)) {
98
+ return false;
99
+ }
100
+ const contract = new ethers_1.Contract(resolvedAddress, ACCESS_CONTROL_ABI, hardhat_1.ethers.provider);
101
+ return await verifyAccessControlInterface(contract, resolvedAddress);
102
+ }
103
+ catch {
104
+ return false;
105
+ }
106
+ };
107
+ exports.isAccessControl = isAccessControl;
108
+ /*
109
+ * Checks if a contract implements the AccessManaged interface.
110
+ * A contract is considered AccessManaged if it has an authority() function
111
+ * that returns a non-zero address pointing to a manager contract.
112
+ *
113
+ * @param contractAddress - The address of the contract to check
114
+ * @returns true if the contract is AccessManaged, false otherwise
115
+ */
116
+ const isAccessManaged = async (contractAddress) => {
117
+ try {
118
+ const resolvedAddress = await hardhat_1.ethers.resolveAddress(contractAddress);
119
+ const isContract = await (0, utils_1.isContractAddress)(resolvedAddress);
120
+ if (!isContract) {
121
+ return false;
122
+ }
123
+ const contract = new ethers_1.Contract(resolvedAddress, ACCESS_MANAGED_ABI, hardhat_1.ethers.provider);
124
+ /*
125
+ * Try to call authority() - if it succeeds and returns non-zero address,
126
+ * The contract is AccessManaged
127
+ */
128
+ const authorityAddress = await contract.authority();
129
+ return await (0, exports.isAccessControl)(authorityAddress);
130
+ }
131
+ catch {
132
+ return false;
133
+ }
134
+ };
135
+ exports.isAccessManaged = isAccessManaged;
136
+ /*
137
+ * Transfers ownership of an Ownable contract to a new owner.
138
+ * This function encodes the transferOwnership call data for the transaction.
139
+ *
140
+ * @param contractAddress - The address of the Ownable contract
141
+ * @param newOwner - The address of the new owner
142
+ * @returns Transaction object with the encoded transferOwnership call or true
143
+ * if the new owner is already the desired owner
144
+ *
145
+ * @dev The address must have already been verified as an Ownable contract before calling this function.
146
+ */
147
+ const transferOwnership = async (contractAddress, newOwner) => {
148
+ const resolvedContractAddress = await hardhat_1.ethers.resolveAddress(contractAddress);
149
+ const resolvedNewOwner = await hardhat_1.ethers.resolveAddress(newOwner);
150
+ const contract = new ethers_1.Contract(resolvedContractAddress, OWNABLE_ABI, hardhat_1.ethers.provider);
151
+ if (await contract.owner() === resolvedNewOwner) {
152
+ return true;
153
+ }
154
+ const data = contract.interface.encodeFunctionData("transferOwnership", [resolvedNewOwner]);
155
+ console.log(chalk_1.default.green(`Prepared transferOwnership transaction for ${resolvedContractAddress} to new owner ${resolvedNewOwner}`));
156
+ return {
157
+ data,
158
+ "to": resolvedContractAddress
159
+ };
160
+ };
161
+ exports.transferOwnership = transferOwnership;
162
+ const getPermissionModels = async (address) => {
163
+ const models = [];
164
+ if (await (0, exports.isOwnable)(address)) {
165
+ models.push(PermissionModel.OWNABLE);
166
+ }
167
+ if (await (0, exports.isAccessControl)(address)) {
168
+ models.push(PermissionModel.ROLE_BASED);
169
+ }
170
+ if (await (0, exports.isAccessManaged)(address)) {
171
+ models.push(PermissionModel.ACCESS_MANAGED);
172
+ }
173
+ return models;
174
+ };
175
+ exports.getPermissionModels = getPermissionModels;
176
+ //# sourceMappingURL=permission-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permission-utils.js","sourceRoot":"","sources":["../../../src/ownership-transfer/permission-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { AddressLike } from "ethers";
2
+ export declare enum Pattern {
3
+ TUPP = "TUPP",
4
+ BEACON = "BEACON",
5
+ REGULAR = "REGULAR"
6
+ }
7
+ export declare const isContractAddress: (address: string) => Promise<boolean>;
8
+ export declare const extractAddressFromSlot: (slotValue: string) => string;
9
+ export declare const getAdminAddress: (address: string) => Promise<string>;
10
+ export declare const getImplementationAddress: (address: string) => Promise<string>;
11
+ export declare const isTUPPPattern: (address: string) => Promise<boolean>;
12
+ export declare const isBeaconPattern: (address: string) => Promise<boolean>;
13
+ export declare const identifyProxyPattern: (address: string) => Promise<Pattern>;
14
+ export declare const promptUserConfirmation: () => Promise<boolean>;
15
+ export declare const detectPattern: (address: AddressLike) => Promise<Pattern>;
16
+ export declare const hasFunctionSelector: (address: string, signature: string) => Promise<boolean>;
@@ -0,0 +1,178 @@
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.hasFunctionSelector = exports.detectPattern = exports.promptUserConfirmation = exports.identifyProxyPattern = exports.isBeaconPattern = exports.isTUPPPattern = exports.getImplementationAddress = exports.getAdminAddress = exports.extractAddressFromSlot = exports.isContractAddress = exports.Pattern = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const hardhat_1 = require("hardhat");
9
+ const readline_1 = __importDefault(require("readline"));
10
+ const ERC1967_ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103";
11
+ const ERC1967_IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
12
+ const ERC1967_BEACON_SLOT = "0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50";
13
+ const basicBeaconAbi = [
14
+ "function owner() view returns (address)",
15
+ "function implementation() view returns (address)"
16
+ ];
17
+ /*
18
+ * Ethereum addresses are 20 bytes = 40 hex characters
19
+ * Used for extracting addresses from 32-byte storage slots
20
+ */
21
+ const ADDRESS_HEX_LENGTH = 40;
22
+ var Pattern;
23
+ (function (Pattern) {
24
+ Pattern["TUPP"] = "TUPP";
25
+ Pattern["BEACON"] = "BEACON";
26
+ Pattern["REGULAR"] = "REGULAR";
27
+ })(Pattern || (exports.Pattern = Pattern = {}));
28
+ const isContractAddress = async (address) => {
29
+ const code = await hardhat_1.ethers.provider.getCode(address);
30
+ return code !== "0x" && code !== "0x0";
31
+ };
32
+ exports.isContractAddress = isContractAddress;
33
+ const extractAddressFromSlot = (slotValue) => {
34
+ const addressHex = `0x${slotValue.slice(-ADDRESS_HEX_LENGTH)}`;
35
+ return hardhat_1.ethers.getAddress(addressHex);
36
+ };
37
+ exports.extractAddressFromSlot = extractAddressFromSlot;
38
+ const getAdminAddress = async (address) => {
39
+ const adminSlotValue = await hardhat_1.ethers.provider.getStorage(address, ERC1967_ADMIN_SLOT);
40
+ return (0, exports.extractAddressFromSlot)(adminSlotValue);
41
+ };
42
+ exports.getAdminAddress = getAdminAddress;
43
+ const getImplementationAddress = async (address) => {
44
+ const implementationSlotValue = await hardhat_1.ethers.provider.getStorage(address, ERC1967_IMPLEMENTATION_SLOT);
45
+ return (0, exports.extractAddressFromSlot)(implementationSlotValue);
46
+ };
47
+ exports.getImplementationAddress = getImplementationAddress;
48
+ const validateTUPPProxy = async (proxyAddress, adminAddress) => {
49
+ const isAdminContract = await (0, exports.isContractAddress)(adminAddress);
50
+ if (!isAdminContract) {
51
+ return false;
52
+ }
53
+ const implementationAddress = await (0, exports.getImplementationAddress)(proxyAddress);
54
+ return implementationAddress !== hardhat_1.ethers.ZeroAddress && await (0, exports.isContractAddress)(implementationAddress);
55
+ };
56
+ /*
57
+ * Checks if the contract follows the Transparent Upgradeable Proxy Pattern.
58
+ * A TUPP proxy has an admin address in the ERC1967 admin slot.
59
+ */
60
+ const isTUPPPattern = async (address) => {
61
+ try {
62
+ const adminAddress = await (0, exports.getAdminAddress)(address);
63
+ if (adminAddress === hardhat_1.ethers.ZeroAddress) {
64
+ return false;
65
+ }
66
+ return await validateTUPPProxy(address, adminAddress);
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ };
72
+ exports.isTUPPPattern = isTUPPPattern;
73
+ /*
74
+ * Checks if the contract follows the Beacon Proxy Pattern.
75
+ * A Beacon proxy has a beacon address in the ERC1967 beacon slot,
76
+ * or it might be a beacon contract itself with an owner() function.
77
+ */
78
+ const isBeaconPattern = async (address) => {
79
+ try {
80
+ // Check beacon slot
81
+ const beaconSlotValue = await hardhat_1.ethers.provider.getStorage(address, ERC1967_BEACON_SLOT);
82
+ const beaconAddress = (0, exports.extractAddressFromSlot)(beaconSlotValue);
83
+ if (beaconAddress === hardhat_1.ethers.ZeroAddress) {
84
+ return false;
85
+ }
86
+ const contract = new hardhat_1.ethers.Contract(address, basicBeaconAbi, hardhat_1.ethers.provider);
87
+ const [owner, implementation] = await Promise.all([
88
+ contract.owner(),
89
+ contract.implementation()
90
+ ]);
91
+ return owner !== hardhat_1.ethers.ZeroAddress &&
92
+ implementation === beaconAddress &&
93
+ await (0, exports.isContractAddress)(implementation);
94
+ }
95
+ catch {
96
+ return false;
97
+ }
98
+ };
99
+ exports.isBeaconPattern = isBeaconPattern;
100
+ /*
101
+ * Identifies the proxy pattern for a given address by checking:
102
+ * 1. TUPP (Transparent Upgradeable Proxy Pattern)
103
+ * 2. BEACON pattern
104
+ * 3. REGULAR (non-proxy contract)
105
+ */
106
+ const identifyProxyPattern = async (address) => {
107
+ const isTUPP = await (0, exports.isTUPPPattern)(address);
108
+ if (isTUPP) {
109
+ return Pattern.TUPP;
110
+ }
111
+ const isBeacon = await (0, exports.isBeaconPattern)(address);
112
+ if (isBeacon) {
113
+ return Pattern.BEACON;
114
+ }
115
+ return Pattern.REGULAR;
116
+ };
117
+ exports.identifyProxyPattern = identifyProxyPattern;
118
+ /*
119
+ * Prompts the user for confirmation via command line input.
120
+ * Accepts "yes" or "y" (case-insensitive) as confirmation.
121
+ * Returns a Promise that resolves to true if confirmed, false otherwise.
122
+ */
123
+ const promptUserConfirmation = () => {
124
+ const rl = readline_1.default.createInterface({
125
+ "input": process.stdin,
126
+ "output": process.stdout
127
+ });
128
+ return new Promise((resolve) => {
129
+ rl.question(chalk_1.default.yellow("Do you confirm these findings? (yes/y to confirm): "), (answer) => {
130
+ rl.close();
131
+ const normalizedAnswer = answer.trim().toLowerCase();
132
+ resolve(normalizedAnswer === "yes" || normalizedAnswer === "y");
133
+ });
134
+ });
135
+ };
136
+ exports.promptUserConfirmation = promptUserConfirmation;
137
+ /*
138
+ * Detects the proxy pattern used by a contract at the given address.
139
+ */
140
+ const detectPattern = async (address) => {
141
+ try {
142
+ const resolvedAddress = await hardhat_1.ethers.resolveAddress(address);
143
+ const isContract = await (0, exports.isContractAddress)(resolvedAddress);
144
+ if (!isContract) {
145
+ throw new Error(`Address ${address} is not a contract. Stopping...`);
146
+ }
147
+ return await (0, exports.identifyProxyPattern)(resolvedAddress);
148
+ }
149
+ catch (error) {
150
+ console.error(`Error detecting pattern for address ${address}:`, error);
151
+ return Pattern.REGULAR;
152
+ }
153
+ };
154
+ exports.detectPattern = detectPattern;
155
+ const hasFunctionSelector = async (address, signature) => {
156
+ const iface = new hardhat_1.ethers.Interface([`function ${signature}`]);
157
+ const { selector } = iface.getFunction(signature) || {};
158
+ if (!selector) {
159
+ throw new Error(`Invalid function signature: ${signature}`);
160
+ }
161
+ try {
162
+ // Empty arguments used — we just want to test if the selector is valid
163
+ const result = await hardhat_1.ethers.provider.call({
164
+ data: selector,
165
+ to: address
166
+ });
167
+ if (result === "0x") {
168
+ return false;
169
+ }
170
+ return true;
171
+ }
172
+ catch (err) {
173
+ // Reverted = function exists, but call params invalid
174
+ return true;
175
+ }
176
+ };
177
+ exports.hasFunctionSelector = hasFunctionSelector;
178
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/ownership-transfer/utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skalenetwork/upgrade-tools",
3
- "version": "4.0.0-develop.2",
3
+ "version": "4.0.0-ownership-helpers.0",
4
4
  "description": "Scripts to support upgrades of smart contracts",
5
5
  "files": [
6
6
  "dist/**/*"
@@ -45,7 +45,7 @@
45
45
  "@safe-global/api-kit": "^2.4.1",
46
46
  "@safe-global/protocol-kit": "^5.0.1",
47
47
  "@safe-global/safe-core-sdk-types": "^5.0.1",
48
- "@skalenetwork/skale-contracts-ethers-v6": "^2.0.0-develop.1",
48
+ "@skalenetwork/skale-contracts-ethers-v6": "^2.0.0-develop.6",
49
49
  "@types/mocha": "^9.1.0",
50
50
  "axios": "^1.4.0",
51
51
  "ethereumjs-util": "^7.1.4",