UNPKG

dop-stick

Version:

Source control tooling for versionable-upgradeable smart contracts

147 lines 7.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConstructorVerifier = void 0; const ethers_1 = require("ethers"); const logger_1 = require("./logsAndMetrics/core/logger"); class ConstructorVerifier { static async verifyConstructorArgs(factory, args, standardType) { try { // Get constructor fragment from factory const constructorFragment = factory.interface.fragments.find((f) => f.type === 'constructor'); if (!constructorFragment) { throw new Error('No constructor found in contract ABI'); } // Verify based on standard type switch (standardType) { case 'standard-type-1': return this.verifyType1Constructor(constructorFragment, args); case 'standard-type-2': return this.verifyType2Constructor(constructorFragment, args); case 'standard-type-3': return this.verifyType3Constructor(constructorFragment, args); case 'custom': logger_1.Logger.warning('Custom standard type: skipping constructor verification'); return true; default: throw new Error(`Unknown standard type: ${standardType}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger_1.Logger.error(`Constructor verification failed: ${errorMessage}`); throw error; } } static verifyType1Constructor(constructorFragment, args) { // Type 1: constructor(IDiamondCut.FacetCut[] memory _diamondCut, DiamondArgs memory _args) // where DiamondArgs = { address owner; address init; bytes initCalldata; } const expectedParams = [ { name: '_diamondCut', type: 'tuple[]' }, { name: 'diamondArgs', type: 'tuple', components: [ { name: 'owner', type: 'address' }, { name: 'init', type: 'address' }, { name: 'initCalldata', type: 'bytes' } ] } ]; return this.verifyParameters(constructorFragment, expectedParams, args); } static verifyType2Constructor(constructorFragment, args) { // Type 2: constructor(IDiamondCut.FacetCut[] memory _diamondCut, DiamondArgs memory _args) // where DiamondArgs = { address owner; } const expectedParams = [ { name: '_diamondCut', type: 'tuple[]' }, { name: 'diamondArgs', type: 'tuple', components: [ { name: 'owner', type: 'address' } ] } ]; return this.verifyParameters(constructorFragment, expectedParams, args); } static verifyType3Constructor(constructorFragment, args) { // Type 3: constructor(address _contractOwner, address _diamondCutFacet) const expectedParams = [ { name: '_contractOwner', type: 'address' }, { name: '_diamondCutFacet', type: 'address' } ]; return this.verifyParameters(constructorFragment, expectedParams, args); } static verifyParameters(constructorFragment, expectedParams, args) { const constructorParams = constructorFragment.inputs; // Check parameter count if (constructorParams.length !== expectedParams.length) { throw new Error(`Constructor parameter count mismatch. Expected ${expectedParams.length}, got ${constructorParams.length}`); } // Check each parameter for (let i = 0; i < expectedParams.length; i++) { const expected = expectedParams[i]; const actual = constructorParams[i]; // Check parameter type if (!this.isTypeCompatible(expected.type, actual.type)) { throw new Error(`Parameter type mismatch for ${expected.name}. Expected ${expected.type}, got ${actual.type}`); } // For tuple types, verify components if they exist if (expected.type === 'tuple' && expected.components) { const actualComponents = actual.components; if (!actualComponents) { throw new Error(`Expected tuple components for ${expected.name} but none found`); } if (actualComponents.length !== expected.components.length) { throw new Error(`Tuple component count mismatch for ${expected.name}. Expected ${expected.components.length}, got ${actualComponents.length}`); } // Verify each component for (let j = 0; j < expected.components.length; j++) { const expectedComp = expected.components[j]; const actualComp = actualComponents[j]; if (!this.isTypeCompatible(expectedComp.type, actualComp.type)) { throw new Error(`Tuple component type mismatch for ${expected.name}.${expectedComp.name}. Expected ${expectedComp.type}, got ${actualComp.type}`); } } } // Check if required argument is provided if (!(expected.name in args)) { throw new Error(`Missing required constructor argument: ${expected.name}`); } } return true; } static isTypeCompatible(expectedType, actualType) { // Handle array types if (expectedType.includes('[]') && actualType.includes('[]')) { return this.isTypeCompatible(expectedType.replace('[]', ''), actualType.replace('[]', '')); } // Handle tuple types if (expectedType.startsWith('tuple') && actualType.startsWith('tuple')) { return true; // We handle tuple verification separately in verifyParameters } return expectedType === actualType; } static verify(args) { // Verify all addresses in args args.forEach((arg, index) => { if (typeof arg === 'string' && arg.startsWith('0x')) { if (!ethers_1.ethers.utils.isAddress(arg)) { throw new Error(`Invalid address at position ${index}: ${arg}`); } } else if (typeof arg === 'object') { // Recursively check objects for addresses Object.entries(arg).forEach(([key, value]) => { if (typeof value === 'string' && value.startsWith('0x')) { if (!ethers_1.ethers.utils.isAddress(value)) { throw new Error(`Invalid address in ${key}: ${value}`); } } }); } }); } } exports.ConstructorVerifier = ConstructorVerifier; //# sourceMappingURL=constructorVerifier.js.map