@0xsequence/catapult 1.3.3 → 1.3.5
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 +16 -0
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +4 -2
- package/dist/commands/run.js.map +1 -1
- package/dist/lib/__tests__/deployer.spec.js +71 -1
- package/dist/lib/__tests__/deployer.spec.js.map +1 -1
- package/dist/lib/core/__tests__/engine.spec.js +270 -0
- package/dist/lib/core/__tests__/engine.spec.js.map +1 -1
- package/dist/lib/core/__tests__/resolver.spec.js +199 -2
- package/dist/lib/core/__tests__/resolver.spec.js.map +1 -1
- package/dist/lib/core/engine.d.ts +13 -0
- package/dist/lib/core/engine.d.ts.map +1 -1
- package/dist/lib/core/engine.js +59 -5
- package/dist/lib/core/engine.js.map +1 -1
- package/dist/lib/core/resolver.d.ts +1 -0
- package/dist/lib/core/resolver.d.ts.map +1 -1
- package/dist/lib/core/resolver.js +38 -8
- package/dist/lib/core/resolver.js.map +1 -1
- package/dist/lib/deployer.d.ts +2 -0
- package/dist/lib/deployer.d.ts.map +1 -1
- package/dist/lib/deployer.js +18 -1
- package/dist/lib/deployer.js.map +1 -1
- package/dist/lib/events/cli-adapter.d.ts.map +1 -1
- package/dist/lib/events/cli-adapter.js +20 -0
- package/dist/lib/events/cli-adapter.js.map +1 -1
- package/dist/lib/events/types.d.ts +25 -1
- package/dist/lib/events/types.d.ts.map +1 -1
- package/dist/lib/types/values.d.ts +8 -1
- package/dist/lib/types/values.d.ts.map +1 -1
- package/dist/lib/utils/assertion.d.ts +4 -0
- package/dist/lib/utils/assertion.d.ts.map +1 -0
- package/dist/lib/utils/assertion.js +27 -0
- package/dist/lib/utils/assertion.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/run.ts +4 -1
- package/src/lib/__tests__/deployer.spec.ts +108 -1
- package/src/lib/core/__tests__/engine.spec.ts +321 -0
- package/src/lib/core/__tests__/resolver.spec.ts +231 -3
- package/src/lib/core/engine.ts +92 -6
- package/src/lib/core/resolver.ts +46 -9
- package/src/lib/deployer.ts +28 -1
- package/src/lib/events/cli-adapter.ts +24 -0
- package/src/lib/events/types.ts +29 -1
- package/src/lib/types/values.ts +10 -1
- package/src/lib/utils/assertion.ts +24 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertion.js","sourceRoot":"","sources":["../../../src/lib/utils/assertion.ts"],"names":[],"mappings":";;AAEA,8BAEC;AAED,kCAEC;AAED,wCAaC;AAvBD,mCAAgC;AAEhC,SAAgB,SAAS,CAAC,KAAc;IACtC,OAAO,eAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;AAChC,CAAC;AAED,SAAgB,WAAW,CAAC,KAAc;IACxC,OAAO,eAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;AAClC,CAAC;AAED,SAAgB,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC;QACH,QAAQ,OAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,KAAK,QAAQ,CAAC;YACd,KAAK,QAAQ,CAAC;YACd,KAAK,QAAQ;gBACX,eAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;gBACtB,OAAO,IAAI,CAAA;QACf,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;IAEjB,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
package/package.json
CHANGED
package/src/commands/run.ts
CHANGED
|
@@ -21,6 +21,7 @@ interface RunOptions {
|
|
|
21
21
|
noPostCheckConditions: boolean
|
|
22
22
|
flatOutput: boolean
|
|
23
23
|
summary: boolean
|
|
24
|
+
ignoreVerifyErrors: boolean
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export function makeRunCommand(): Command {
|
|
@@ -36,6 +37,7 @@ export function makeRunCommand(): Command {
|
|
|
36
37
|
.option('--flat-output', 'Write output files in a single flat directory instead of mirroring the jobs directory structure. Default: false', false)
|
|
37
38
|
.option('--no-summary', 'Hide final summary at the end of the run. Default: show', false)
|
|
38
39
|
.option('--run-deprecated', 'Allow running jobs marked as deprecated. By default deprecated jobs are skipped unless explicitly targeted.', false)
|
|
40
|
+
.option('--ignore-verify-errors', 'Convert verification errors to warnings instead of exiting with error code. Shows complete warning report at the end.', false)
|
|
39
41
|
|
|
40
42
|
projectOption(run)
|
|
41
43
|
dotenvOption(run)
|
|
@@ -113,7 +115,8 @@ export function makeRunCommand(): Command {
|
|
|
113
115
|
loadStdTemplates: options.std !== false
|
|
114
116
|
},
|
|
115
117
|
flatOutput: options.flatOutput === true,
|
|
116
|
-
runDeprecated: (options as { runDeprecated?: boolean }).runDeprecated === true
|
|
118
|
+
runDeprecated: (options as { runDeprecated?: boolean }).runDeprecated === true,
|
|
119
|
+
ignoreVerifyErrors: options.ignoreVerifyErrors === true
|
|
117
120
|
} as DeployerOptions
|
|
118
121
|
|
|
119
122
|
const deployer = new Deployer(deployerOptions)
|
|
@@ -117,7 +117,8 @@ describe('Deployer', () => {
|
|
|
117
117
|
} as any
|
|
118
118
|
|
|
119
119
|
mockEngine = {
|
|
120
|
-
executeJob: jest.fn().mockResolvedValue(undefined)
|
|
120
|
+
executeJob: jest.fn().mockResolvedValue(undefined),
|
|
121
|
+
getVerificationWarnings: jest.fn().mockReturnValue([])
|
|
121
122
|
} as any
|
|
122
123
|
|
|
123
124
|
mockContext = {
|
|
@@ -1199,4 +1200,110 @@ describe('Deployer', () => {
|
|
|
1199
1200
|
expect(mockEngine.executeJob).toHaveBeenCalledTimes(2)
|
|
1200
1201
|
})
|
|
1201
1202
|
})
|
|
1203
|
+
|
|
1204
|
+
describe('ignore verify errors feature', () => {
|
|
1205
|
+
it('should pass ignoreVerifyErrors option to ExecutionEngine', async () => {
|
|
1206
|
+
const optionsWithIgnoreVerifyErrors = {
|
|
1207
|
+
...deployerOptions,
|
|
1208
|
+
ignoreVerifyErrors: true
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
const deployer = new Deployer(optionsWithIgnoreVerifyErrors)
|
|
1212
|
+
await deployer.run()
|
|
1213
|
+
|
|
1214
|
+
// Verify that ExecutionEngine was created with ignoreVerifyErrors option
|
|
1215
|
+
expect(MockExecutionEngine).toHaveBeenCalledWith(
|
|
1216
|
+
expect.anything(),
|
|
1217
|
+
expect.objectContaining({
|
|
1218
|
+
ignoreVerifyErrors: true
|
|
1219
|
+
})
|
|
1220
|
+
)
|
|
1221
|
+
})
|
|
1222
|
+
|
|
1223
|
+
it('should emit verification warnings report when ignoreVerifyErrors is enabled', async () => {
|
|
1224
|
+
const mockWarnings = [
|
|
1225
|
+
{
|
|
1226
|
+
actionName: 'verify-test',
|
|
1227
|
+
address: '0x1234567890123456789012345678901234567890',
|
|
1228
|
+
contractName: 'TestContract',
|
|
1229
|
+
platform: 'etherscan_v2',
|
|
1230
|
+
error: 'Failed to verify contract',
|
|
1231
|
+
networkName: 'mainnet'
|
|
1232
|
+
}
|
|
1233
|
+
]
|
|
1234
|
+
|
|
1235
|
+
// Mock engine to return warnings
|
|
1236
|
+
mockEngine.getVerificationWarnings = jest.fn().mockReturnValue(mockWarnings)
|
|
1237
|
+
|
|
1238
|
+
const optionsWithIgnoreVerifyErrors = {
|
|
1239
|
+
...deployerOptions,
|
|
1240
|
+
ignoreVerifyErrors: true
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
const deployer = new Deployer(optionsWithIgnoreVerifyErrors)
|
|
1244
|
+
|
|
1245
|
+
// Mock event emitter to track events
|
|
1246
|
+
const mockEmitEvent = jest.fn()
|
|
1247
|
+
;(deployer as any).events = { emitEvent: mockEmitEvent }
|
|
1248
|
+
|
|
1249
|
+
await deployer.run()
|
|
1250
|
+
|
|
1251
|
+
// Verify that verification warnings report was emitted
|
|
1252
|
+
expect(mockEmitEvent).toHaveBeenCalledWith({
|
|
1253
|
+
type: 'verification_warnings_report',
|
|
1254
|
+
level: 'warn',
|
|
1255
|
+
data: {
|
|
1256
|
+
totalWarnings: 1,
|
|
1257
|
+
warnings: mockWarnings
|
|
1258
|
+
}
|
|
1259
|
+
})
|
|
1260
|
+
})
|
|
1261
|
+
|
|
1262
|
+
it('should not emit verification warnings report when ignoreVerifyErrors is disabled', async () => {
|
|
1263
|
+
const optionsWithoutIgnoreVerifyErrors = {
|
|
1264
|
+
...deployerOptions,
|
|
1265
|
+
ignoreVerifyErrors: false
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
const deployer = new Deployer(optionsWithoutIgnoreVerifyErrors)
|
|
1269
|
+
|
|
1270
|
+
// Mock event emitter to track events
|
|
1271
|
+
const mockEmitEvent = jest.fn()
|
|
1272
|
+
;(deployer as any).events = { emitEvent: mockEmitEvent }
|
|
1273
|
+
|
|
1274
|
+
await deployer.run()
|
|
1275
|
+
|
|
1276
|
+
// Verify that verification warnings report was NOT emitted
|
|
1277
|
+
expect(mockEmitEvent).not.toHaveBeenCalledWith(
|
|
1278
|
+
expect.objectContaining({
|
|
1279
|
+
type: 'verification_warnings_report'
|
|
1280
|
+
})
|
|
1281
|
+
)
|
|
1282
|
+
})
|
|
1283
|
+
|
|
1284
|
+
it('should not emit verification warnings report when there are no warnings', async () => {
|
|
1285
|
+
// Mock engine to return no warnings
|
|
1286
|
+
mockEngine.getVerificationWarnings = jest.fn().mockReturnValue([])
|
|
1287
|
+
|
|
1288
|
+
const optionsWithIgnoreVerifyErrors = {
|
|
1289
|
+
...deployerOptions,
|
|
1290
|
+
ignoreVerifyErrors: true
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
const deployer = new Deployer(optionsWithIgnoreVerifyErrors)
|
|
1294
|
+
|
|
1295
|
+
// Mock event emitter to track events
|
|
1296
|
+
const mockEmitEvent = jest.fn()
|
|
1297
|
+
;(deployer as any).events = { emitEvent: mockEmitEvent }
|
|
1298
|
+
|
|
1299
|
+
await deployer.run()
|
|
1300
|
+
|
|
1301
|
+
// Verify that verification warnings report was NOT emitted when no warnings
|
|
1302
|
+
expect(mockEmitEvent).not.toHaveBeenCalledWith(
|
|
1303
|
+
expect.objectContaining({
|
|
1304
|
+
type: 'verification_warnings_report'
|
|
1305
|
+
})
|
|
1306
|
+
)
|
|
1307
|
+
})
|
|
1308
|
+
})
|
|
1202
1309
|
})
|
|
@@ -1542,4 +1542,325 @@ describe('ExecutionEngine', () => {
|
|
|
1542
1542
|
expect(context.getOutput('nick-test-default-bytecode.success')).toBe(true)
|
|
1543
1543
|
})
|
|
1544
1544
|
})
|
|
1545
|
+
|
|
1546
|
+
describe('ignore verify errors feature', () => {
|
|
1547
|
+
beforeEach(() => {
|
|
1548
|
+
// Mock fs.readFile to return valid build info
|
|
1549
|
+
jest.doMock('fs/promises', () => ({
|
|
1550
|
+
readFile: jest.fn().mockResolvedValue(JSON.stringify({
|
|
1551
|
+
_format: 'hh-sol-build-info-1',
|
|
1552
|
+
id: 'test-id',
|
|
1553
|
+
solcVersion: '0.8.0',
|
|
1554
|
+
input: {
|
|
1555
|
+
language: 'Solidity',
|
|
1556
|
+
sources: {
|
|
1557
|
+
'TestContract.sol': {
|
|
1558
|
+
content: 'contract TestContract { }'
|
|
1559
|
+
}
|
|
1560
|
+
},
|
|
1561
|
+
settings: {
|
|
1562
|
+
optimizer: { enabled: true, runs: 200 },
|
|
1563
|
+
outputSelection: { '*': { '*': ['*'] } }
|
|
1564
|
+
}
|
|
1565
|
+
},
|
|
1566
|
+
output: {
|
|
1567
|
+
contracts: {},
|
|
1568
|
+
sources: {}
|
|
1569
|
+
}
|
|
1570
|
+
}))
|
|
1571
|
+
}))
|
|
1572
|
+
|
|
1573
|
+
// Create a mock verification registry with a failing platform
|
|
1574
|
+
const mockVerificationRegistry = new VerificationPlatformRegistry()
|
|
1575
|
+
const mockPlatform = {
|
|
1576
|
+
name: 'mock-platform',
|
|
1577
|
+
supportsNetwork: jest.fn().mockReturnValue(true),
|
|
1578
|
+
isConfigured: jest.fn().mockReturnValue(true),
|
|
1579
|
+
getConfigurationRequirements: jest.fn().mockReturnValue(''),
|
|
1580
|
+
isContractAlreadyVerified: jest.fn().mockResolvedValue(false),
|
|
1581
|
+
verifyContract: jest.fn().mockRejectedValue(new Error('Verification failed'))
|
|
1582
|
+
}
|
|
1583
|
+
mockVerificationRegistry.register(mockPlatform)
|
|
1584
|
+
|
|
1585
|
+
engine = new ExecutionEngine(templates, {
|
|
1586
|
+
verificationRegistry: mockVerificationRegistry,
|
|
1587
|
+
ignoreVerifyErrors: true
|
|
1588
|
+
})
|
|
1589
|
+
})
|
|
1590
|
+
|
|
1591
|
+
it('should collect verification warnings when ignoreVerifyErrors is enabled', async () => {
|
|
1592
|
+
const mockContract = {
|
|
1593
|
+
sourceName: 'TestContract.sol',
|
|
1594
|
+
contractName: 'TestContract',
|
|
1595
|
+
compiler: { version: '0.8.0' },
|
|
1596
|
+
buildInfoId: 'test-build-id',
|
|
1597
|
+
source: 'contract TestContract { }',
|
|
1598
|
+
creationCode: '0x608060405234801561000f575f5ffd5b50602a5f526020601ff3',
|
|
1599
|
+
abi: [],
|
|
1600
|
+
_sources: new Set(['TestContract.sol', '/path/to/build-info/test.json'])
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
context.contractRepository.addForTesting({
|
|
1604
|
+
contractName: mockContract.contractName,
|
|
1605
|
+
abi: mockContract.abi,
|
|
1606
|
+
bytecode: mockContract.creationCode,
|
|
1607
|
+
sourceName: mockContract.sourceName,
|
|
1608
|
+
source: mockContract.source,
|
|
1609
|
+
compiler: mockContract.compiler,
|
|
1610
|
+
buildInfoId: mockContract.buildInfoId,
|
|
1611
|
+
_path: '/test/path',
|
|
1612
|
+
_hash: 'test-hash'
|
|
1613
|
+
})
|
|
1614
|
+
|
|
1615
|
+
const action: Action = {
|
|
1616
|
+
type: 'verify-contract',
|
|
1617
|
+
name: 'test-verify',
|
|
1618
|
+
arguments: {
|
|
1619
|
+
address: TEST_ADDRESSES.RECIPIENT_1,
|
|
1620
|
+
contract: '{{Contract(TestContract)}}',
|
|
1621
|
+
platform: 'mock-platform'
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
// Should not throw even though verification fails
|
|
1626
|
+
await expect((engine as any).executePrimitive(action, context, new Map()))
|
|
1627
|
+
.resolves.not.toThrow()
|
|
1628
|
+
|
|
1629
|
+
// Should have collected the warning
|
|
1630
|
+
const warnings = engine.getVerificationWarnings()
|
|
1631
|
+
expect(warnings).toHaveLength(1)
|
|
1632
|
+
expect(warnings[0]).toMatchObject({
|
|
1633
|
+
actionName: 'test-verify',
|
|
1634
|
+
address: TEST_ADDRESSES.RECIPIENT_1,
|
|
1635
|
+
contractName: 'TestContract.sol:TestContract',
|
|
1636
|
+
platform: 'mock-platform',
|
|
1637
|
+
error: 'Action "test-verify": No build-info file found in contract sources'
|
|
1638
|
+
})
|
|
1639
|
+
})
|
|
1640
|
+
|
|
1641
|
+
it('should throw verification errors when ignoreVerifyErrors is disabled', async () => {
|
|
1642
|
+
// Create engine with ignoreVerifyErrors disabled
|
|
1643
|
+
const mockVerificationRegistry = new VerificationPlatformRegistry()
|
|
1644
|
+
const mockPlatform = {
|
|
1645
|
+
name: 'mock-platform',
|
|
1646
|
+
supportsNetwork: jest.fn().mockReturnValue(true),
|
|
1647
|
+
isConfigured: jest.fn().mockReturnValue(true),
|
|
1648
|
+
getConfigurationRequirements: jest.fn().mockReturnValue(''),
|
|
1649
|
+
isContractAlreadyVerified: jest.fn().mockResolvedValue(false),
|
|
1650
|
+
verifyContract: jest.fn().mockRejectedValue(new Error('Verification failed'))
|
|
1651
|
+
}
|
|
1652
|
+
mockVerificationRegistry.register(mockPlatform)
|
|
1653
|
+
|
|
1654
|
+
const engineWithoutIgnore = new ExecutionEngine(templates, {
|
|
1655
|
+
verificationRegistry: mockVerificationRegistry,
|
|
1656
|
+
ignoreVerifyErrors: false
|
|
1657
|
+
})
|
|
1658
|
+
|
|
1659
|
+
const mockContract = {
|
|
1660
|
+
sourceName: 'TestContract.sol',
|
|
1661
|
+
contractName: 'TestContract',
|
|
1662
|
+
compiler: { version: '0.8.0' },
|
|
1663
|
+
buildInfoId: 'test-build-id',
|
|
1664
|
+
source: 'contract TestContract { }',
|
|
1665
|
+
creationCode: '0x608060405234801561000f575f5ffd5b50602a5f526020601ff3',
|
|
1666
|
+
abi: [],
|
|
1667
|
+
_sources: new Set(['TestContract.sol', '/path/to/build-info/test.json'])
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
context.contractRepository.addForTesting({
|
|
1671
|
+
contractName: mockContract.contractName,
|
|
1672
|
+
abi: mockContract.abi,
|
|
1673
|
+
bytecode: mockContract.creationCode,
|
|
1674
|
+
sourceName: mockContract.sourceName,
|
|
1675
|
+
source: mockContract.source,
|
|
1676
|
+
compiler: mockContract.compiler,
|
|
1677
|
+
buildInfoId: mockContract.buildInfoId,
|
|
1678
|
+
_path: '/test/path',
|
|
1679
|
+
_hash: 'test-hash'
|
|
1680
|
+
})
|
|
1681
|
+
|
|
1682
|
+
const action: Action = {
|
|
1683
|
+
type: 'verify-contract',
|
|
1684
|
+
name: 'test-verify',
|
|
1685
|
+
arguments: {
|
|
1686
|
+
address: TEST_ADDRESSES.RECIPIENT_1,
|
|
1687
|
+
contract: '{{Contract(TestContract)}}',
|
|
1688
|
+
platform: 'mock-platform'
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
// Should throw when ignoreVerifyErrors is disabled
|
|
1693
|
+
await expect((engineWithoutIgnore as any).executePrimitive(action, context, new Map()))
|
|
1694
|
+
.rejects.toThrow('Action "test-verify": No build-info file found in contract sources')
|
|
1695
|
+
})
|
|
1696
|
+
|
|
1697
|
+
it('should handle multiple platform verification failures with ignoreVerifyErrors', async () => {
|
|
1698
|
+
const mockVerificationRegistry = new VerificationPlatformRegistry()
|
|
1699
|
+
|
|
1700
|
+
// Create multiple failing platforms
|
|
1701
|
+
const platforms = ['platform1', 'platform2', 'platform3']
|
|
1702
|
+
platforms.forEach(name => {
|
|
1703
|
+
const mockPlatform = {
|
|
1704
|
+
name,
|
|
1705
|
+
supportsNetwork: jest.fn().mockReturnValue(true),
|
|
1706
|
+
isConfigured: jest.fn().mockReturnValue(true),
|
|
1707
|
+
getConfigurationRequirements: jest.fn().mockReturnValue(''),
|
|
1708
|
+
isContractAlreadyVerified: jest.fn().mockResolvedValue(false),
|
|
1709
|
+
verifyContract: jest.fn().mockRejectedValue(new Error(`${name} verification failed`))
|
|
1710
|
+
}
|
|
1711
|
+
mockVerificationRegistry.register(mockPlatform)
|
|
1712
|
+
})
|
|
1713
|
+
|
|
1714
|
+
engine = new ExecutionEngine(templates, {
|
|
1715
|
+
verificationRegistry: mockVerificationRegistry,
|
|
1716
|
+
ignoreVerifyErrors: true
|
|
1717
|
+
})
|
|
1718
|
+
|
|
1719
|
+
const mockContract = {
|
|
1720
|
+
sourceName: 'TestContract.sol',
|
|
1721
|
+
contractName: 'TestContract',
|
|
1722
|
+
compiler: { version: '0.8.0' },
|
|
1723
|
+
buildInfoId: 'test-build-id',
|
|
1724
|
+
source: 'contract TestContract { }',
|
|
1725
|
+
creationCode: '0x608060405234801561000f575f5ffd5b50602a5f526020601ff3',
|
|
1726
|
+
abi: [],
|
|
1727
|
+
_sources: new Set(['TestContract.sol', '/path/to/build-info/test.json'])
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
context.contractRepository.addForTesting({
|
|
1731
|
+
contractName: mockContract.contractName,
|
|
1732
|
+
abi: mockContract.abi,
|
|
1733
|
+
bytecode: mockContract.creationCode,
|
|
1734
|
+
sourceName: mockContract.sourceName,
|
|
1735
|
+
source: mockContract.source,
|
|
1736
|
+
compiler: mockContract.compiler,
|
|
1737
|
+
buildInfoId: mockContract.buildInfoId,
|
|
1738
|
+
_path: '/test/path',
|
|
1739
|
+
_hash: 'test-hash'
|
|
1740
|
+
})
|
|
1741
|
+
|
|
1742
|
+
const action: Action = {
|
|
1743
|
+
type: 'verify-contract',
|
|
1744
|
+
name: 'test-verify',
|
|
1745
|
+
arguments: {
|
|
1746
|
+
address: TEST_ADDRESSES.RECIPIENT_1,
|
|
1747
|
+
contract: '{{Contract(TestContract)}}',
|
|
1748
|
+
platform: platforms
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
// Should not throw even with multiple platform failures
|
|
1753
|
+
await expect((engine as any).executePrimitive(action, context, new Map()))
|
|
1754
|
+
.resolves.not.toThrow()
|
|
1755
|
+
|
|
1756
|
+
// Should have collected warnings for all platforms
|
|
1757
|
+
const warnings = engine.getVerificationWarnings()
|
|
1758
|
+
expect(warnings).toHaveLength(3)
|
|
1759
|
+
|
|
1760
|
+
platforms.forEach((platform, index) => {
|
|
1761
|
+
expect(warnings[index]).toMatchObject({
|
|
1762
|
+
actionName: 'test-verify',
|
|
1763
|
+
platform,
|
|
1764
|
+
error: 'Action "test-verify": No build-info file found in contract sources'
|
|
1765
|
+
})
|
|
1766
|
+
})
|
|
1767
|
+
})
|
|
1768
|
+
|
|
1769
|
+
it('should provide methods to get and clear verification warnings', () => {
|
|
1770
|
+
// Initially empty
|
|
1771
|
+
expect(engine.getVerificationWarnings()).toEqual([])
|
|
1772
|
+
|
|
1773
|
+
// Manually add a warning (simulating what happens during verification)
|
|
1774
|
+
;(engine as any).verificationWarnings.push({
|
|
1775
|
+
actionName: 'test',
|
|
1776
|
+
address: '0x123',
|
|
1777
|
+
contractName: 'Test',
|
|
1778
|
+
platform: 'test-platform',
|
|
1779
|
+
error: 'test error'
|
|
1780
|
+
})
|
|
1781
|
+
|
|
1782
|
+
// Should return the warning
|
|
1783
|
+
const warnings = engine.getVerificationWarnings()
|
|
1784
|
+
expect(warnings).toHaveLength(1)
|
|
1785
|
+
expect(warnings[0]).toMatchObject({
|
|
1786
|
+
actionName: 'test',
|
|
1787
|
+
error: 'test error'
|
|
1788
|
+
})
|
|
1789
|
+
|
|
1790
|
+
// Clear warnings
|
|
1791
|
+
engine.clearVerificationWarnings()
|
|
1792
|
+
expect(engine.getVerificationWarnings()).toEqual([])
|
|
1793
|
+
})
|
|
1794
|
+
|
|
1795
|
+
it('should emit verification_skipped events when all platforms fail and ignoreVerifyErrors is enabled', async () => {
|
|
1796
|
+
const mockVerificationRegistry = new VerificationPlatformRegistry()
|
|
1797
|
+
const mockPlatform = {
|
|
1798
|
+
name: 'mock-platform',
|
|
1799
|
+
supportsNetwork: jest.fn().mockReturnValue(true),
|
|
1800
|
+
isConfigured: jest.fn().mockReturnValue(true),
|
|
1801
|
+
getConfigurationRequirements: jest.fn().mockReturnValue(''),
|
|
1802
|
+
isContractAlreadyVerified: jest.fn().mockResolvedValue(false),
|
|
1803
|
+
verifyContract: jest.fn().mockRejectedValue(new Error('Verification failed'))
|
|
1804
|
+
}
|
|
1805
|
+
mockVerificationRegistry.register(mockPlatform)
|
|
1806
|
+
mockVerificationRegistry.getConfiguredPlatforms = jest.fn().mockReturnValue([mockPlatform])
|
|
1807
|
+
|
|
1808
|
+
const mockEventEmitter = {
|
|
1809
|
+
emitEvent: jest.fn()
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
engine = new ExecutionEngine(templates, {
|
|
1813
|
+
verificationRegistry: mockVerificationRegistry,
|
|
1814
|
+
ignoreVerifyErrors: true,
|
|
1815
|
+
eventEmitter: mockEventEmitter as any
|
|
1816
|
+
})
|
|
1817
|
+
|
|
1818
|
+
const mockContract = {
|
|
1819
|
+
sourceName: 'TestContract.sol',
|
|
1820
|
+
contractName: 'TestContract',
|
|
1821
|
+
compiler: { version: '0.8.0' },
|
|
1822
|
+
buildInfoId: 'test-build-id',
|
|
1823
|
+
source: 'contract TestContract { }',
|
|
1824
|
+
creationCode: '0x608060405234801561000f575f5ffd5b50602a5f526020601ff3',
|
|
1825
|
+
abi: [],
|
|
1826
|
+
_sources: new Set(['TestContract.sol', '/path/to/build-info/test.json'])
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
context.contractRepository.addForTesting({
|
|
1830
|
+
contractName: mockContract.contractName,
|
|
1831
|
+
abi: mockContract.abi,
|
|
1832
|
+
bytecode: mockContract.creationCode,
|
|
1833
|
+
sourceName: mockContract.sourceName,
|
|
1834
|
+
source: mockContract.source,
|
|
1835
|
+
compiler: mockContract.compiler,
|
|
1836
|
+
buildInfoId: mockContract.buildInfoId,
|
|
1837
|
+
_path: '/test/path',
|
|
1838
|
+
_hash: 'test-hash'
|
|
1839
|
+
})
|
|
1840
|
+
|
|
1841
|
+
const action: Action = {
|
|
1842
|
+
type: 'verify-contract',
|
|
1843
|
+
name: 'test-verify',
|
|
1844
|
+
arguments: {
|
|
1845
|
+
address: TEST_ADDRESSES.RECIPIENT_1,
|
|
1846
|
+
contract: '{{Contract(TestContract)}}',
|
|
1847
|
+
platform: 'all'
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1851
|
+
await (engine as any).executePrimitive(action, context, new Map())
|
|
1852
|
+
|
|
1853
|
+
// Should emit verification_skipped event
|
|
1854
|
+
expect(mockEventEmitter.emitEvent).toHaveBeenCalledWith(
|
|
1855
|
+
expect.objectContaining({
|
|
1856
|
+
type: 'verification_skipped',
|
|
1857
|
+
level: 'warn',
|
|
1858
|
+
data: expect.objectContaining({
|
|
1859
|
+
actionName: 'test-verify',
|
|
1860
|
+
reason: expect.stringContaining('continuing due to --ignore-verify-errors')
|
|
1861
|
+
})
|
|
1862
|
+
})
|
|
1863
|
+
)
|
|
1864
|
+
})
|
|
1865
|
+
})
|
|
1545
1866
|
})
|