@chainlink/ace 0.5.0 → 1.0.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.
Files changed (126) hide show
  1. package/.github/workflows/npm-publish.yml +28 -0
  2. package/README.md +9 -1
  3. package/UPGRADE_GUIDE.md +754 -0
  4. package/getting_started/GETTING_STARTED.md +6 -0
  5. package/getting_started/MyVault.sol +2 -2
  6. package/getting_started/advanced/SanctionsPolicy.sol +6 -2
  7. package/package.json +3 -3
  8. package/packages/cross-chain-identity/docs/API_REFERENCE.md +2 -0
  9. package/packages/cross-chain-identity/src/CredentialRegistry.sol +9 -7
  10. package/packages/cross-chain-identity/src/CredentialRegistryFactory.sol +96 -0
  11. package/packages/cross-chain-identity/src/CredentialRegistryIdentityValidator.sol +15 -4
  12. package/packages/cross-chain-identity/src/CredentialRegistryIdentityValidatorPolicy.sol +10 -7
  13. package/packages/cross-chain-identity/src/IdentityRegistry.sol +33 -17
  14. package/packages/cross-chain-identity/src/IdentityRegistryFactory.sol +96 -0
  15. package/packages/cross-chain-identity/src/TrustedIssuerRegistry.sol +8 -6
  16. package/packages/cross-chain-identity/src/TrustedIssuerRegistryFactory.sol +96 -0
  17. package/packages/cross-chain-identity/src/interfaces/ICredentialRegistry.sol +6 -0
  18. package/packages/cross-chain-identity/src/interfaces/ICredentialRequirements.sol +2 -1
  19. package/packages/cross-chain-identity/src/interfaces/IIdentityRegistry.sol +7 -1
  20. package/packages/cross-chain-identity/src/interfaces/ITrustedIssuerRegistry.sol +6 -0
  21. package/packages/cross-chain-identity/test/CredentialRegistry.t.sol +1 -1
  22. package/packages/cross-chain-identity/test/CredentialRegistryFactory.t.sol +105 -0
  23. package/packages/cross-chain-identity/test/CredentialRegistryIdentityValidator.t.sol +16 -1
  24. package/packages/cross-chain-identity/test/CredentialRegistryIdentityValidatorPolicy.t.sol +58 -1
  25. package/packages/cross-chain-identity/test/IdentityRegistry.t.sol +140 -1
  26. package/packages/cross-chain-identity/test/IdentityRegistryFactory.t.sol +103 -0
  27. package/packages/cross-chain-identity/test/IdentityValidator.t.sol +1 -1
  28. package/packages/cross-chain-identity/test/TrustedIssuerRegistry.t.sol +1 -1
  29. package/packages/cross-chain-identity/test/TrustedIssuerRegistryFactory.t.sol +107 -0
  30. package/packages/cross-chain-identity/test/helpers/BaseProxyTest.sol +1 -1
  31. package/packages/cross-chain-identity/test/helpers/MockCredentialDataValidator.sol +1 -1
  32. package/packages/cross-chain-identity/test/helpers/MockCredentialRegistryReverting.sol +3 -1
  33. package/packages/policy-management/README.md +1 -0
  34. package/packages/policy-management/docs/API_GUIDE.md +2 -0
  35. package/packages/policy-management/docs/API_REFERENCE.md +3 -1
  36. package/packages/policy-management/docs/CUSTOM_POLICIES_TUTORIAL.md +10 -4
  37. package/packages/policy-management/src/core/Policy.sol +5 -4
  38. package/packages/policy-management/src/core/PolicyEngine.sol +113 -57
  39. package/packages/policy-management/src/core/PolicyEngineFactory.sol +102 -0
  40. package/packages/policy-management/src/core/PolicyFactory.sol +1 -1
  41. package/packages/policy-management/src/core/PolicyProtected.sol +28 -55
  42. package/packages/policy-management/src/core/PolicyProtectedUpgradeable.sol +134 -0
  43. package/packages/policy-management/src/extractors/ComplianceTokenForceTransferExtractor.sol +4 -1
  44. package/packages/policy-management/src/extractors/ComplianceTokenFreezeUnfreezeExtractor.sol +4 -1
  45. package/packages/policy-management/src/extractors/ComplianceTokenMintBurnExtractor.sol +4 -1
  46. package/packages/policy-management/src/extractors/ERC20ApproveExtractor.sol +4 -1
  47. package/packages/policy-management/src/extractors/ERC20TransferExtractor.sol +4 -1
  48. package/packages/policy-management/src/extractors/ERC3643ForcedTransferExtractor.sol +4 -1
  49. package/packages/policy-management/src/extractors/ERC3643FreezeUnfreezeExtractor.sol +4 -1
  50. package/packages/policy-management/src/extractors/ERC3643MintBurnExtractor.sol +4 -1
  51. package/packages/policy-management/src/extractors/ERC3643SetAddressFrozenExtractor.sol +4 -1
  52. package/packages/policy-management/src/interfaces/ICertifiedActionValidator.sol +110 -0
  53. package/packages/policy-management/src/interfaces/IExtractor.sol +6 -0
  54. package/packages/policy-management/src/interfaces/IMapper.sol +6 -0
  55. package/packages/policy-management/src/interfaces/IPolicy.sol +6 -0
  56. package/packages/policy-management/src/interfaces/IPolicyEngine.sol +90 -10
  57. package/packages/policy-management/src/interfaces/IPolicyProtected.sol +6 -0
  58. package/packages/policy-management/src/libraries/CertifiedActionLib.sol +47 -0
  59. package/packages/policy-management/src/policies/AllowPolicy.sol +12 -7
  60. package/packages/policy-management/src/policies/BypassPolicy.sol +23 -5
  61. package/packages/policy-management/src/policies/CertifiedActionDONValidatorPolicy.sol +156 -0
  62. package/packages/policy-management/src/policies/CertifiedActionERC20TransferValidatorPolicy.sol +202 -0
  63. package/packages/policy-management/src/policies/CertifiedActionValidatorPolicy.sol +365 -0
  64. package/packages/policy-management/src/policies/IntervalPolicy.sol +64 -48
  65. package/packages/policy-management/src/policies/MaxPolicy.sol +7 -5
  66. package/packages/policy-management/src/policies/OnlyAuthorizedSenderPolicy.sol +20 -4
  67. package/packages/policy-management/src/policies/OnlyOwnerPolicy.sol +4 -2
  68. package/packages/policy-management/src/policies/PausePolicy.sol +16 -15
  69. package/packages/policy-management/src/policies/RejectPolicy.sol +23 -5
  70. package/packages/policy-management/src/policies/RoleBasedAccessControlPolicy.sol +7 -5
  71. package/packages/policy-management/src/policies/SecureMintPolicy.sol +136 -48
  72. package/packages/policy-management/src/policies/VolumePolicy.sol +9 -5
  73. package/packages/policy-management/src/policies/VolumeRatePolicy.sol +11 -7
  74. package/packages/policy-management/test/PolicyEngine.t.sol +131 -23
  75. package/packages/policy-management/test/PolicyEngineFactory.t.sol +95 -0
  76. package/packages/policy-management/test/PolicyFactory.t.sol +1 -1
  77. package/packages/policy-management/test/{PolicyProtectedToken.t.sol → PolicyProtected.t.sol} +54 -8
  78. package/packages/policy-management/test/PolicyProtectedUpgradeable.t.sol +126 -0
  79. package/packages/policy-management/test/extractors/ComplianceTokenForceTransferExtractor.t.sol +1 -1
  80. package/packages/policy-management/test/extractors/ComplianceTokenFreezeUnfreezeExtractor.t.sol +1 -1
  81. package/packages/policy-management/test/extractors/ComplianceTokenMintBurnExtractor.t.sol +1 -1
  82. package/packages/policy-management/test/extractors/ERC20ApproveExtractor.t.sol +1 -1
  83. package/packages/policy-management/test/extractors/ERC3643ForcedTransferExtractor.t.sol +1 -1
  84. package/packages/policy-management/test/extractors/ERC3643FreezeUnfreezeExtractor.t.sol +1 -1
  85. package/packages/policy-management/test/extractors/ERC3643MintBurnExtractor.t.sol +1 -1
  86. package/packages/policy-management/test/extractors/ERC3643SetAddressFrozenExtractor.t.sol +1 -1
  87. package/packages/policy-management/test/helpers/BaseCertifiedActionTest.sol +44 -0
  88. package/packages/policy-management/test/helpers/BaseProxyTest.sol +88 -7
  89. package/packages/policy-management/test/helpers/CustomMapper.sol +3 -1
  90. package/packages/policy-management/test/helpers/DummyExtractor.sol +3 -1
  91. package/packages/policy-management/test/helpers/ExpectedParameterPolicy.sol +3 -1
  92. package/packages/policy-management/test/helpers/FaultyPolicyEngine.sol +54 -0
  93. package/packages/policy-management/test/helpers/MockCertifiedActionValidatorPolicyExtension.sol +46 -0
  94. package/packages/policy-management/test/helpers/MockToken.sol +2 -5
  95. package/packages/policy-management/test/helpers/MockTokenExtractor.sol +9 -4
  96. package/packages/policy-management/test/helpers/MockTokenUpgradeable.sol +66 -0
  97. package/packages/policy-management/test/helpers/PolicyAlwaysAllowed.sol +3 -1
  98. package/packages/policy-management/test/helpers/PolicyAlwaysContinue.sol +3 -1
  99. package/packages/policy-management/test/helpers/PolicyAlwaysRejected.sol +10 -1
  100. package/packages/policy-management/test/helpers/PolicyFailingRun.sol +3 -1
  101. package/packages/policy-management/test/policies/AllowPolicy.t.sol +39 -23
  102. package/packages/policy-management/test/policies/BypassPolicy.t.sol +48 -20
  103. package/packages/policy-management/test/policies/CertifiedActionDONValidatorPolicy.t.sol +172 -0
  104. package/packages/policy-management/test/policies/CertifiedActionERC20TransferValidatorPolicy.t.sol +217 -0
  105. package/packages/policy-management/test/policies/CertifiedActionValidatorPolicy.t.sol +1083 -0
  106. package/packages/policy-management/test/policies/IntervalPolicy.t.sol +105 -55
  107. package/packages/policy-management/test/policies/MaxPolicy.t.sol +15 -7
  108. package/packages/policy-management/test/policies/OnlyAuthorizedSenderPolicy.t.sol +91 -16
  109. package/packages/policy-management/test/policies/OnlyOwnerPolicy.t.sol +11 -7
  110. package/packages/policy-management/test/policies/PausePolicy.t.sol +46 -16
  111. package/packages/policy-management/test/policies/RejectPolicy.t.sol +52 -24
  112. package/packages/policy-management/test/policies/RoleBasedAccessControlPolicy.t.sol +50 -30
  113. package/packages/policy-management/test/policies/SecureMintPolicy.t.sol +211 -32
  114. package/packages/policy-management/test/policies/VolumePolicy.t.sol +20 -10
  115. package/packages/policy-management/test/policies/VolumeRatePolicy.t.sol +24 -18
  116. package/packages/tokens/erc-20/src/ComplianceTokenERC20.sol +4 -7
  117. package/packages/tokens/erc-20/src/ComplianceTokenStoreERC20.sol +4 -4
  118. package/packages/tokens/erc-20/test/ComplianceTokenERC20.t.sol +92 -82
  119. package/packages/tokens/erc-20/test/helpers/BaseProxyTest.sol +74 -1
  120. package/packages/tokens/erc-3643/src/ComplianceTokenERC3643.sol +12 -7
  121. package/packages/tokens/erc-3643/src/ComplianceTokenStoreERC3643.sol +4 -4
  122. package/packages/tokens/erc-3643/test/ComplianceTokenERC3643.t.sol +108 -119
  123. package/packages/tokens/erc-3643/test/helpers/BaseProxyTest.sol +74 -1
  124. package/packages/tokens/erc-3643/test/helpers/ExpectedContextPolicy.sol +3 -1
  125. package/remappings.txt +1 -0
  126. package/script/DeployCertifiedActionsComplianceTokenERC3643.s.sol +125 -0
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: BUSL-1.1
2
- pragma solidity 0.8.26;
2
+ pragma solidity ^0.8.20;
3
3
 
4
4
  import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5
5
  import {IToken} from "../../../vendor/erc-3643/token/IToken.sol";
@@ -60,17 +60,25 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
60
60
  // to protect mint/burn with admin list
61
61
  OnlyAuthorizedSenderPolicy minterBurnerListImpl = new OnlyAuthorizedSenderPolicy();
62
62
  minterBurnerList = OnlyAuthorizedSenderPolicy(
63
- _deployPolicy(address(minterBurnerListImpl), address(s_policyEngine), s_owner, new bytes(0))
63
+ _deployPolicy(address(minterBurnerListImpl), address(s_policyEngine), address(s_policyEngine), new bytes(0))
64
+ );
65
+ s_policyEngine.setPolicyConfiguration(
66
+ address(minterBurnerList), 0, OnlyAuthorizedSenderPolicy.authorizeSender.selector, abi.encode(s_owner)
67
+ );
68
+ s_policyEngine.setPolicyConfiguration(
69
+ address(minterBurnerList), 1, OnlyAuthorizedSenderPolicy.authorizeSender.selector, abi.encode(s_bridge)
64
70
  );
65
- minterBurnerList.authorizeSender(s_owner);
66
- minterBurnerList.authorizeSender(s_bridge);
67
71
  // to protect freezing features with admin list
68
72
  OnlyAuthorizedSenderPolicy freezingListImpl = new OnlyAuthorizedSenderPolicy();
69
73
  freezingList = OnlyAuthorizedSenderPolicy(
70
- _deployPolicy(address(freezingListImpl), address(s_policyEngine), s_owner, new bytes(0))
74
+ _deployPolicy(address(freezingListImpl), address(s_policyEngine), address(s_policyEngine), new bytes(0))
75
+ );
76
+ s_policyEngine.setPolicyConfiguration(
77
+ address(freezingList), 0, OnlyAuthorizedSenderPolicy.authorizeSender.selector, abi.encode(s_owner)
78
+ );
79
+ s_policyEngine.setPolicyConfiguration(
80
+ address(freezingList), 1, OnlyAuthorizedSenderPolicy.authorizeSender.selector, abi.encode(s_enforcer)
71
81
  );
72
- freezingList.authorizeSender(s_owner);
73
- freezingList.authorizeSender(s_enforcer);
74
82
  // to enforce transaction limits
75
83
  VolumePolicy volumePolicyImpl = new VolumePolicy();
76
84
  volumePolicy =
@@ -126,13 +134,12 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
126
134
  function test_token_name_notOwner_failure() public {
127
135
  vm.startPrank(s_bridge);
128
136
 
129
- vm.expectRevert(
130
- abi.encodeWithSelector(
131
- IPolicyEngine.PolicyRunRejected.selector,
132
- IToken.setName.selector,
133
- address(onlyOwnerPolicy),
134
- "caller is not the policy owner"
135
- )
137
+ _expectRejectedRevert(
138
+ address(onlyOwnerPolicy),
139
+ "caller is not the policy owner",
140
+ IToken.setName.selector,
141
+ s_bridge,
142
+ abi.encode("New Name")
136
143
  );
137
144
  s_token.setName("New Name");
138
145
  }
@@ -140,13 +147,8 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
140
147
  function test_token_symbol_notOwner_failure() public {
141
148
  vm.startPrank(s_bridge);
142
149
 
143
- vm.expectRevert(
144
- abi.encodeWithSelector(
145
- IPolicyEngine.PolicyRunRejected.selector,
146
- IToken.setSymbol.selector,
147
- address(onlyOwnerPolicy),
148
- "caller is not the policy owner"
149
- )
150
+ _expectRejectedRevert(
151
+ address(onlyOwnerPolicy), "caller is not the policy owner", IToken.setSymbol.selector, s_bridge, abi.encode("NME")
150
152
  );
151
153
  s_token.setSymbol("NME");
152
154
  }
@@ -179,13 +181,12 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
179
181
  assertEq(s_token.totalSupply(), 110);
180
182
 
181
183
  // second mint fails because context was cleared after the last mint
182
- vm.expectRevert(
183
- abi.encodeWithSelector(
184
- IPolicyEngine.PolicyRunRejected.selector,
185
- IToken.mint.selector,
186
- address(expectedContextPolicy),
187
- "context does not match expected value"
188
- )
184
+ _expectRejectedRevert(
185
+ address(expectedContextPolicy),
186
+ "context does not match expected value",
187
+ IToken.mint.selector,
188
+ s_owner,
189
+ abi.encode(alice, 110)
189
190
  );
190
191
  s_token.mint(alice, 110);
191
192
  }
@@ -204,13 +205,12 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
204
205
  function test_mint_over_failure() public {
205
206
  address alice = makeAddr("alice");
206
207
 
207
- vm.expectRevert(
208
- abi.encodeWithSelector(
209
- IPolicyEngine.PolicyRunRejected.selector,
210
- IToken.mint.selector,
211
- address(volumePolicy),
212
- "amount outside allowed volume limits"
213
- )
208
+ _expectRejectedRevert(
209
+ address(volumePolicy),
210
+ "amount outside allowed volume limits",
211
+ IToken.mint.selector,
212
+ s_owner,
213
+ abi.encode(alice, 220)
214
214
  );
215
215
  s_token.mint(alice, 220);
216
216
  }
@@ -218,14 +218,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
218
218
  function test_mint_under_failure() public {
219
219
  address alice = makeAddr("alice");
220
220
 
221
- vm.expectRevert(
222
- abi.encodeWithSelector(
223
- IPolicyEngine.PolicyRunRejected.selector,
224
- IToken.mint.selector,
225
- address(volumePolicy),
226
- "amount outside allowed volume limits"
227
- )
228
- );
221
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
222
+ selector: IToken.mint.selector,
223
+ sender: s_owner,
224
+ data: abi.encode(alice, 50),
225
+ context: new bytes(0)
226
+ });
227
+ _expectRejectedRevert(address(volumePolicy), "amount outside allowed volume limits", payload);
229
228
  s_token.mint(alice, 50);
230
229
  }
231
230
 
@@ -235,14 +234,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
235
234
  vm.stopPrank();
236
235
  vm.startPrank(alice);
237
236
 
238
- vm.expectRevert(
239
- abi.encodeWithSelector(
240
- IPolicyEngine.PolicyRunRejected.selector,
241
- IToken.mint.selector,
242
- address(minterBurnerList),
243
- "sender is not authorized"
244
- )
245
- );
237
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
238
+ selector: IToken.mint.selector,
239
+ sender: alice,
240
+ data: abi.encode(alice, 10),
241
+ context: new bytes(0)
242
+ });
243
+ _expectRejectedRevert(address(minterBurnerList), "sender is not authorized", payload);
246
244
  s_token.mint(alice, 10);
247
245
  }
248
246
 
@@ -280,14 +278,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
280
278
  vm.stopPrank();
281
279
  vm.startPrank(alice);
282
280
 
283
- vm.expectRevert(
284
- abi.encodeWithSelector(
285
- IPolicyEngine.PolicyRunRejected.selector,
286
- IToken.burn.selector,
287
- address(minterBurnerList),
288
- "sender is not authorized"
289
- )
290
- );
281
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
282
+ selector: IToken.burn.selector,
283
+ sender: alice,
284
+ data: abi.encode(alice, 70),
285
+ context: new bytes(0)
286
+ });
287
+ _expectRejectedRevert(address(minterBurnerList), "sender is not authorized", payload);
291
288
  s_token.burn(alice, 70);
292
289
  }
293
290
 
@@ -317,14 +314,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
317
314
  vm.stopPrank();
318
315
  vm.startPrank(alice);
319
316
 
320
- vm.expectRevert(
321
- abi.encodeWithSelector(
322
- IPolicyEngine.PolicyRunRejected.selector,
323
- IERC20.transfer.selector,
324
- address(volumePolicy),
325
- "amount outside allowed volume limits"
326
- )
327
- );
317
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
318
+ selector: IERC20.transfer.selector,
319
+ sender: alice,
320
+ data: abi.encode(bob, 210),
321
+ context: new bytes(0)
322
+ });
323
+ _expectRejectedRevert(address(volumePolicy), "amount outside allowed volume limits", payload);
328
324
  s_token.transfer(bob, 210);
329
325
  }
330
326
 
@@ -337,14 +333,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
337
333
  vm.stopPrank();
338
334
  vm.startPrank(alice);
339
335
 
340
- vm.expectRevert(
341
- abi.encodeWithSelector(
342
- IPolicyEngine.PolicyRunRejected.selector,
343
- IERC20.transfer.selector,
344
- address(volumePolicy),
345
- "amount outside allowed volume limits"
346
- )
347
- );
336
+ IPolicyEngine.Payload memory payload2 = IPolicyEngine.Payload({
337
+ selector: IERC20.transfer.selector,
338
+ sender: alice,
339
+ data: abi.encode(bob, 50),
340
+ context: new bytes(0)
341
+ });
342
+ _expectRejectedRevert(address(volumePolicy), "amount outside allowed volume limits", payload2);
348
343
  s_token.transfer(bob, 50);
349
344
  }
350
345
 
@@ -368,12 +363,11 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
368
363
  address alice = makeAddr("alice");
369
364
  vm.startPrank(alice);
370
365
 
366
+ IPolicyEngine.Payload memory payload =
367
+ IPolicyEngine.Payload({selector: IToken.pause.selector, sender: alice, data: new bytes(0), context: new bytes(0)});
371
368
  vm.expectRevert(
372
369
  abi.encodeWithSelector(
373
- IPolicyEngine.PolicyRunRejected.selector,
374
- IToken.pause.selector,
375
- address(onlyOwnerPolicy),
376
- "caller is not the policy owner"
370
+ IPolicyEngine.PolicyRunRejected.selector, address(onlyOwnerPolicy), "caller is not the policy owner", payload
377
371
  )
378
372
  );
379
373
  s_token.pause();
@@ -407,14 +401,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
407
401
  vm.stopPrank();
408
402
  vm.startPrank(alice);
409
403
 
410
- vm.expectRevert(
411
- abi.encodeWithSelector(
412
- IPolicyEngine.PolicyRunRejected.selector,
413
- IToken.unpause.selector,
414
- address(onlyOwnerPolicy),
415
- "caller is not the policy owner"
416
- )
417
- );
404
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
405
+ selector: IToken.unpause.selector,
406
+ sender: alice,
407
+ data: new bytes(0),
408
+ context: new bytes(0)
409
+ });
410
+ _expectRejectedRevert(address(onlyOwnerPolicy), "caller is not the policy owner", payload);
418
411
  s_token.unpause();
419
412
  }
420
413
 
@@ -483,14 +476,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
483
476
  s_token.mint(alice, 120);
484
477
 
485
478
  vm.startPrank(alice);
486
- vm.expectRevert(
487
- abi.encodeWithSelector(
488
- IPolicyEngine.PolicyRunRejected.selector,
489
- IToken.setAddressFrozen.selector,
490
- address(freezingList),
491
- "sender is not authorized"
492
- )
493
- );
479
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
480
+ selector: IToken.setAddressFrozen.selector,
481
+ sender: alice,
482
+ data: abi.encode(alice, true),
483
+ context: new bytes(0)
484
+ });
485
+ _expectRejectedRevert(address(freezingList), "sender is not authorized", payload);
494
486
  s_token.setAddressFrozen(alice, true);
495
487
  }
496
488
 
@@ -687,14 +679,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
687
679
 
688
680
  s_token.mint(alice, 120);
689
681
  vm.startPrank(alice);
690
- vm.expectRevert(
691
- abi.encodeWithSelector(
692
- IPolicyEngine.PolicyRunRejected.selector,
693
- IToken.freezePartialTokens.selector,
694
- address(freezingList),
695
- "sender is not authorized"
696
- )
697
- );
682
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
683
+ selector: IToken.freezePartialTokens.selector,
684
+ sender: alice,
685
+ data: abi.encode(alice, 10),
686
+ context: new bytes(0)
687
+ });
688
+ _expectRejectedRevert(address(freezingList), "sender is not authorized", payload);
698
689
  s_token.freezePartialTokens(alice, 10);
699
690
  }
700
691
 
@@ -734,14 +725,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
734
725
  s_token.freezePartialTokens(alice, 50);
735
726
 
736
727
  vm.startPrank(alice);
737
- vm.expectRevert(
738
- abi.encodeWithSelector(
739
- IPolicyEngine.PolicyRunRejected.selector,
740
- IToken.unfreezePartialTokens.selector,
741
- address(freezingList),
742
- "sender is not authorized"
743
- )
744
- );
728
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
729
+ selector: IToken.unfreezePartialTokens.selector,
730
+ sender: alice,
731
+ data: abi.encode(alice, 10),
732
+ context: new bytes(0)
733
+ });
734
+ _expectRejectedRevert(address(freezingList), "sender is not authorized", payload);
745
735
  s_token.unfreezePartialTokens(alice, 10);
746
736
  }
747
737
 
@@ -780,14 +770,13 @@ contract ComplianceTokenERC3643Test is BaseProxyTest {
780
770
  vm.stopPrank();
781
771
  vm.startPrank(bob);
782
772
 
783
- vm.expectRevert(
784
- abi.encodeWithSelector(
785
- IPolicyEngine.PolicyRunRejected.selector,
786
- IToken.forcedTransfer.selector,
787
- address(onlyOwnerPolicy),
788
- "caller is not the policy owner"
789
- )
790
- );
773
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
774
+ selector: IToken.forcedTransfer.selector,
775
+ sender: bob,
776
+ data: abi.encode(alice, bob, 60),
777
+ context: new bytes(0)
778
+ });
779
+ _expectRejectedRevert(address(onlyOwnerPolicy), "caller is not the policy owner", payload);
791
780
  s_token.forcedTransfer(alice, bob, 60);
792
781
  }
793
782
 
@@ -1,5 +1,5 @@
1
1
  // SPDX-License-Identifier: BUSL-1.1
2
- pragma solidity 0.8.26;
2
+ pragma solidity ^0.8.20;
3
3
 
4
4
  import {Test} from "forge-std/Test.sol";
5
5
  import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
@@ -73,4 +73,77 @@ abstract contract BaseProxyTest is Test {
73
73
  ERC1967Proxy tokenProxy = new ERC1967Proxy(address(tokenImpl), tokenData);
74
74
  return ComplianceTokenERC3643(address(tokenProxy));
75
75
  }
76
+
77
+ /**
78
+ * @notice Expect a PolicyRunRejected revert with a payload created from parameters
79
+ * @param policy The address of the policy that rejected the action
80
+ * @param reason The reason for rejection
81
+ * @param selector The function selector
82
+ * @param sender The sender address
83
+ * @param data The encoded function parameters
84
+ * @param context The context bytes (defaults to empty if not provided)
85
+ */
86
+ function _expectRejectedRevert(
87
+ address policy,
88
+ string memory reason,
89
+ bytes4 selector,
90
+ address sender,
91
+ bytes memory data,
92
+ bytes memory context
93
+ )
94
+ internal
95
+ {
96
+ IPolicyEngine.Payload memory payload =
97
+ IPolicyEngine.Payload({selector: selector, sender: sender, data: data, context: context});
98
+ vm.expectRevert(abi.encodeWithSelector(IPolicyEngine.PolicyRunRejected.selector, policy, reason, payload));
99
+ }
100
+
101
+ /**
102
+ * @notice Expect a PolicyRunRejected revert with a payload created from parameters (empty context)
103
+ * @param policy The address of the policy that rejected the action
104
+ * @param reason The reason for rejection
105
+ * @param selector The function selector
106
+ * @param sender The sender address
107
+ * @param data The encoded function parameters
108
+ */
109
+ function _expectRejectedRevert(
110
+ address policy,
111
+ string memory reason,
112
+ bytes4 selector,
113
+ address sender,
114
+ bytes memory data
115
+ )
116
+ internal
117
+ {
118
+ _expectRejectedRevert(policy, reason, selector, sender, data, "");
119
+ }
120
+
121
+ /**
122
+ * @notice Encode PolicyRunRejected error for use with vm.expectRevert
123
+ * @param policy The address of the policy that rejected the action
124
+ * @param reason The reason for rejection
125
+ * @param payload The payload that was rejected
126
+ * @return The encoded error data
127
+ */
128
+ function _encodeRejectedRevert(
129
+ address policy,
130
+ string memory reason,
131
+ IPolicyEngine.Payload memory payload
132
+ )
133
+ internal
134
+ pure
135
+ returns (bytes memory)
136
+ {
137
+ return abi.encodeWithSelector(IPolicyEngine.PolicyRunRejected.selector, policy, reason, payload);
138
+ }
139
+
140
+ /**
141
+ * @notice Expect a PolicyRunRejected revert with a payload
142
+ * @param policy The address of the policy that rejected the action
143
+ * @param reason The reason for rejection
144
+ * @param payload The payload that was rejected
145
+ */
146
+ function _expectRejectedRevert(address policy, string memory reason, IPolicyEngine.Payload memory payload) internal {
147
+ vm.expectRevert(_encodeRejectedRevert(policy, reason, payload));
148
+ }
76
149
  }
@@ -1,10 +1,12 @@
1
1
  // SPDX-License-Identifier: BUSL-1.1
2
- pragma solidity 0.8.26;
2
+ pragma solidity ^0.8.20;
3
3
 
4
4
  import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
5
5
  import {Policy} from "@chainlink/policy-management/core/Policy.sol";
6
6
 
7
7
  contract ExpectedContextPolicy is Policy {
8
+ string public constant override typeAndVersion = "ExpectedContextPolicy 1.0.0";
9
+
8
10
  bytes private s_expectedContext;
9
11
 
10
12
  function configure(bytes calldata parameters) internal override onlyInitializing {
package/remappings.txt CHANGED
@@ -1,4 +1,5 @@
1
1
  @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/
2
+ @openzeppelin/contracts@5.0.2=node_modules/@openzeppelin/contracts/
2
3
  @openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/
3
4
  @chainlink/policy-management/=packages/policy-management/src/
4
5
  @chainlink/cross-chain-identity/=packages/cross-chain-identity/src/
@@ -0,0 +1,125 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
5
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
6
+ import {ComplianceTokenERC3643} from "../packages/tokens/erc-3643/src/ComplianceTokenERC3643.sol";
7
+ import {PolicyEngine} from "@chainlink/policy-management/core/PolicyEngine.sol";
8
+ import {Policy} from "@chainlink/policy-management/core/Policy.sol";
9
+ import {OnlyOwnerPolicy} from "@chainlink/policy-management/policies/OnlyOwnerPolicy.sol";
10
+ import {CertifiedActionDONValidatorPolicy} from
11
+ "@chainlink/policy-management/policies/CertifiedActionDONValidatorPolicy.sol";
12
+ import {ICredentialRequirements} from "@chainlink/cross-chain-identity/interfaces/ICredentialRequirements.sol";
13
+ import {ERC20TransferExtractor} from "@chainlink/policy-management/extractors/ERC20TransferExtractor.sol";
14
+ import {Script} from "forge-std/Script.sol";
15
+ import {console} from "forge-std/console.sol";
16
+
17
+ contract DeployCertifiedActionsComplianceTokenERC3643 is Script {
18
+ function run() external {
19
+ uint256 tokenOwnerPK = vm.envUint("PRIVATE_KEY");
20
+ address tokenOwner = vm.addr(tokenOwnerPK);
21
+
22
+ vm.startBroadcast(tokenOwnerPK);
23
+
24
+ // Deploy a PolicyEngine through proxy for identity registries and attach OnlyOwnerPolicy to administrative methods
25
+ PolicyEngine policyEngineImpl = new PolicyEngine();
26
+ bytes memory policyEngineData =
27
+ abi.encodeWithSelector(PolicyEngine.initialize.selector, IPolicyEngine.PolicyResult.Allowed, tokenOwner);
28
+ ERC1967Proxy policyEngineProxy = new ERC1967Proxy(address(policyEngineImpl), policyEngineData);
29
+ PolicyEngine policyEngine = PolicyEngine(address(policyEngineProxy));
30
+
31
+ // Deploy the ComplianceTokenERC3643 through proxy
32
+ ComplianceTokenERC3643 tokenImpl = new ComplianceTokenERC3643();
33
+ bytes memory tokenData = abi.encodeWithSelector(
34
+ ComplianceTokenERC3643.initialize.selector,
35
+ vm.envOr("TOKEN_NAME", string("Token")),
36
+ vm.envOr("TOKEN_SYMBOL", string("TOKEN")),
37
+ 18,
38
+ address(policyEngine)
39
+ );
40
+ ERC1967Proxy tokenProxy = new ERC1967Proxy(address(tokenImpl), tokenData);
41
+ ComplianceTokenERC3643 token = ComplianceTokenERC3643(address(tokenProxy));
42
+
43
+ OnlyOwnerPolicy tokenOnlyOwnerPolicyImpl = new OnlyOwnerPolicy();
44
+ bytes memory tokenOnlyOwnerPolicyData =
45
+ abi.encodeWithSelector(Policy.initialize.selector, address(policyEngine), tokenOwner, new bytes(0));
46
+ ERC1967Proxy tokenOnlyOwnerPolicyProxy =
47
+ new ERC1967Proxy(address(tokenOnlyOwnerPolicyImpl), tokenOnlyOwnerPolicyData);
48
+ OnlyOwnerPolicy tokenOnlyOwnerPolicy = OnlyOwnerPolicy(address(tokenOnlyOwnerPolicyProxy));
49
+ policyEngine.addPolicy(
50
+ address(token), ComplianceTokenERC3643.mint.selector, address(tokenOnlyOwnerPolicy), new bytes32[](0)
51
+ );
52
+ policyEngine.addPolicy(
53
+ address(token), ComplianceTokenERC3643.pause.selector, address(tokenOnlyOwnerPolicy), new bytes32[](0)
54
+ );
55
+ policyEngine.addPolicy(
56
+ address(token), ComplianceTokenERC3643.unpause.selector, address(tokenOnlyOwnerPolicy), new bytes32[](0)
57
+ );
58
+ policyEngine.addPolicy(
59
+ address(token), ComplianceTokenERC3643.setAddressFrozen.selector, address(tokenOnlyOwnerPolicy), new bytes32[](0)
60
+ );
61
+ policyEngine.addPolicy(
62
+ address(token), ComplianceTokenERC3643.forcedTransfer.selector, address(tokenOnlyOwnerPolicy), new bytes32[](0)
63
+ );
64
+ policyEngine.addPolicy(
65
+ address(token),
66
+ ComplianceTokenERC3643.freezePartialTokens.selector,
67
+ address(tokenOnlyOwnerPolicy),
68
+ new bytes32[](0)
69
+ );
70
+ policyEngine.addPolicy(
71
+ address(token),
72
+ ComplianceTokenERC3643.unfreezePartialTokens.selector,
73
+ address(tokenOnlyOwnerPolicy),
74
+ new bytes32[](0)
75
+ );
76
+ policyEngine.addPolicy(
77
+ address(token), ComplianceTokenERC3643.setName.selector, address(tokenOnlyOwnerPolicy), new bytes32[](0)
78
+ );
79
+ policyEngine.addPolicy(
80
+ address(token), ComplianceTokenERC3643.setSymbol.selector, address(tokenOnlyOwnerPolicy), new bytes32[](0)
81
+ );
82
+
83
+ // Attach an CredentialRegistryIdentityValidatorPolicy to validate the 'to' address of ERC20 transfers
84
+ ERC20TransferExtractor erc20TransferExtractor = new ERC20TransferExtractor();
85
+ policyEngine.setExtractor(ComplianceTokenERC3643.transfer.selector, address(erc20TransferExtractor));
86
+ policyEngine.setExtractor(ComplianceTokenERC3643.transferFrom.selector, address(erc20TransferExtractor));
87
+
88
+ CertifiedActionDONValidatorPolicy certifiedActionDONValidatorPolicyImpl = new CertifiedActionDONValidatorPolicy();
89
+ bytes memory certifiedActionDONValidatorPolicyData = abi.encodeWithSelector(
90
+ Policy.initialize.selector,
91
+ address(policyEngine),
92
+ address(tokenOwner),
93
+ abi.encode(vm.envAddress("KEYSTONE_FORWARDER_ADDRESS"))
94
+ );
95
+ ERC1967Proxy certifiedActionDONValidatorPolicyProxy =
96
+ new ERC1967Proxy(address(certifiedActionDONValidatorPolicyImpl), certifiedActionDONValidatorPolicyData);
97
+ CertifiedActionDONValidatorPolicy certifiedActionDONValidatorPolicy =
98
+ CertifiedActionDONValidatorPolicy(address(certifiedActionDONValidatorPolicyProxy));
99
+ bytes32[] memory certifiedActionDONValidatorPolicyParameters = new bytes32[](3);
100
+ certifiedActionDONValidatorPolicyParameters[0] = erc20TransferExtractor.PARAM_FROM();
101
+ certifiedActionDONValidatorPolicyParameters[1] = erc20TransferExtractor.PARAM_TO();
102
+ certifiedActionDONValidatorPolicyParameters[2] = erc20TransferExtractor.PARAM_AMOUNT();
103
+
104
+ policyEngine.addPolicy(
105
+ address(token),
106
+ ComplianceTokenERC3643.transfer.selector,
107
+ address(certifiedActionDONValidatorPolicy),
108
+ certifiedActionDONValidatorPolicyParameters
109
+ );
110
+ policyEngine.addPolicy(
111
+ address(token),
112
+ ComplianceTokenERC3643.transferFrom.selector,
113
+ address(certifiedActionDONValidatorPolicy),
114
+ certifiedActionDONValidatorPolicyParameters
115
+ );
116
+
117
+ vm.stopBroadcast();
118
+
119
+ console.log("Deployed ComplianceTokenERC3643 at:", address(token));
120
+ console.log("Deployed PolicyEngine at:", address(policyEngine));
121
+ console.log("Deployed Token OnlyOwnerPolicy at:", address(tokenOnlyOwnerPolicy));
122
+ console.log("Deployed ERC20TransferExtractor at:", address(erc20TransferExtractor));
123
+ console.log("Deployed CertifiedActionDONValidatorPolicy at:", address(certifiedActionDONValidatorPolicy));
124
+ }
125
+ }