@@ -338,7 +338,7 @@ export default class ContractsManager {
338
338
339
339
if ( contract . address && typeof contract . address === 'function' ) {
340
340
contract . addressHandler = contract . address ;
341
- delete contract . addres ;
341
+ delete contract . address ;
342
342
} else if ( contract . address && typeof contract . address === 'string' ) {
343
343
contract . deployedAddress = contract . address ;
344
344
}
@@ -385,64 +385,63 @@ export default class ContractsManager {
385
385
}
386
386
callback ( ) ;
387
387
} ,
388
- /* eslint complexity: ["error", 11]*/
388
+ // eslint-disable-next-line complexity
389
389
function dealWithSpecialConfigs ( callback ) {
390
390
let className , contract , parentContractName , parentContract ;
391
391
let dictionary = Object . keys ( self . contracts ) ;
392
392
393
393
for ( className in self . contracts ) {
394
394
contract = self . contracts [ className ] ;
395
395
396
- if ( contract . instanceOf === undefined ) {
396
+ if ( ! contract . instanceOf && ! contract . proxyFor ) {
397
397
continue ;
398
398
}
399
399
400
- parentContractName = contract . instanceOf ;
401
- parentContract = self . contracts [ parentContractName ] ;
402
-
403
- if ( parentContract === className ) {
404
- self . logger . error ( __ ( "%s : instanceOf is set to itself" , className ) ) ;
405
- continue ;
406
- }
400
+ if ( contract . instanceOf ) {
401
+ parentContractName = contract . instanceOf ;
402
+ parentContract = self . contracts [ parentContractName ] ;
403
+ if ( ! self . _isParentContractDependencyCorrect ( className , parentContract , 'instanceOf' , dictionary ) ) {
404
+ continue ;
405
+ }
407
406
408
- if ( parentContract === undefined ) {
409
- self . logger . error ( __ ( "{{className}}: couldn't find instanceOf contract {{parentContractName}}" , {
410
- className : className ,
411
- parentContractName : parentContractName
412
- } ) ) ;
413
- let suggestion = proposeAlternative ( parentContractName , dictionary , [ className , parentContractName ] ) ;
414
- if ( suggestion ) {
415
- self . logger . warn ( __ ( 'did you mean "%s"?' , suggestion ) ) ;
407
+ // If the contract has no args and the parent has them, use the parent's args in its place
408
+ if ( parentContract . args ?. length > 0 && contract . args ?. length === 0 ) {
409
+ contract . args = parentContract . args ;
416
410
}
417
- continue ;
418
- }
419
411
420
- if ( parentContract . args && parentContract . args . length > 0 && ( ( contract . args && contract . args . length === 0 ) || contract . args === undefined ) ) {
421
- contract . args = parentContract . args ;
422
- }
412
+ if ( ! contract . code ) {
413
+ self . logger . error ( __ ( "{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}" , {
414
+ className,
415
+ parentContractName
416
+ } ) ) ;
417
+ }
423
418
424
- if ( contract . code !== undefined ) {
425
- self . logger . error ( __ ( "{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}" , {
426
- className : className ,
427
- parentContractName : parentContractName
428
- } ) ) ;
419
+ contract . path = parentContract . path ;
420
+ contract . originalFilename = parentContract . originalFilename ;
421
+ contract . filename = parentContract . filename ;
422
+ contract . code = parentContract . code ;
423
+ contract . runtimeBytecode = parentContract . runtimeBytecode ;
424
+ contract . realRuntimeBytecode = ( parentContract . realRuntimeBytecode || parentContract . runtimeBytecode ) ;
425
+ contract . gasEstimates = parentContract . gasEstimates ;
426
+ contract . functionHashes = parentContract . functionHashes ;
427
+ contract . abiDefinition = parentContract . abiDefinition ;
428
+ contract . linkReferences = parentContract . linkReferences ;
429
+
430
+ contract . gas = contract . gas || parentContract . gas ;
431
+ contract . gasPrice = contract . gasPrice || parentContract . gasPrice ;
432
+ contract . type = 'instance' ;
429
433
}
430
434
431
- contract . path = parentContract . path ;
432
- contract . originalFilename = parentContract . originalFilename ;
433
- contract . filename = parentContract . filename ;
434
- contract . code = parentContract . code ;
435
- contract . runtimeBytecode = parentContract . runtimeBytecode ;
436
- contract . realRuntimeBytecode = ( parentContract . realRuntimeBytecode || parentContract . runtimeBytecode ) ;
437
- contract . gasEstimates = parentContract . gasEstimates ;
438
- contract . functionHashes = parentContract . functionHashes ;
439
- contract . abiDefinition = parentContract . abiDefinition ;
440
- contract . linkReferences = parentContract . linkReferences ;
441
-
442
- contract . gas = contract . gas || parentContract . gas ;
443
- contract . gasPrice = contract . gasPrice || parentContract . gasPrice ;
444
- contract . type = 'instance' ;
435
+ if ( contract . proxyFor ) {
436
+ parentContractName = contract . proxyFor ;
437
+ parentContract = self . contracts [ parentContractName ] ;
438
+ if ( ! self . _isParentContractDependencyCorrect ( className , parentContract , 'proxyFor' , dictionary ) ) {
439
+ continue ;
440
+ }
445
441
442
+ // Merge ABI of contract and proxy so that the contract shares both ABIs, but remove the constructor
443
+ contract . abiDefinition = contract . abiDefinition . concat ( parentContract . abiDefinition . filter ( def => def . type !== 'constructor' ) ) ;
444
+ }
446
445
}
447
446
callback ( ) ;
448
447
} ,
@@ -552,6 +551,28 @@ export default class ContractsManager {
552
551
} ) ;
553
552
}
554
553
554
+ _isParentContractDependencyCorrect ( className , parentContract , typeOfInheritance , dictionary ) {
555
+ const parentContractName = parentContract . className ;
556
+ if ( parentContract === className ) {
557
+ this . logger . error ( __ ( "{{className}} : {{typeOfInheritance}} is set to itself" , { className, typeOfInheritance} ) ) ;
558
+ return false ;
559
+ }
560
+
561
+ if ( parentContract === undefined ) {
562
+ this . logger . error ( __ ( "{{className}}: couldn't find {{typeOfInheritance}} contract {{parentContractName}}" , {
563
+ className,
564
+ parentContractName,
565
+ typeOfInheritance
566
+ } ) ) ;
567
+ let suggestion = proposeAlternative ( parentContractName , dictionary , [ className , parentContractName ] ) ;
568
+ if ( suggestion ) {
569
+ this . logger . warn ( __ ( 'did you mean "%s"?' , suggestion ) ) ;
570
+ }
571
+ return false ;
572
+ }
573
+ return true ;
574
+ }
575
+
555
576
_contractsForApi ( ) {
556
577
const contracts = this . formatContracts ( ) ;
557
578
contracts . forEach ( ( contract ) => {
0 commit comments