@chainlink/ace 0.5.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 (150) hide show
  1. package/.foundry-version +1 -0
  2. package/.github/CODEOWNERS +1 -0
  3. package/.github/workflows/auto-release-version.yml +107 -0
  4. package/.github/workflows/create-version-pr.yml +95 -0
  5. package/.github/workflows/forge-docs.yml +90 -0
  6. package/.github/workflows/forge-test.yml +59 -0
  7. package/.solhint-test.json +18 -0
  8. package/.solhint.json +16 -0
  9. package/.solhintignore +3 -0
  10. package/.solhintignore-test +2 -0
  11. package/Glossary.md +141 -0
  12. package/LICENSE +59 -0
  13. package/README.md +218 -0
  14. package/assets/chainlink-logo.svg +21 -0
  15. package/chainlink-ace-License-grants +2 -0
  16. package/foundry.toml +33 -0
  17. package/getting_started/GETTING_STARTED.md +477 -0
  18. package/getting_started/MyVault.sol +48 -0
  19. package/getting_started/advanced/.env.example +36 -0
  20. package/getting_started/advanced/GETTING_STARTED_ADVANCED.md +431 -0
  21. package/getting_started/advanced/SanctionsList.sol +25 -0
  22. package/getting_started/advanced/SanctionsPolicy.sol +58 -0
  23. package/package.json +41 -0
  24. package/packages/cross-chain-identity/README.md +148 -0
  25. package/packages/cross-chain-identity/docs/API_GUIDE.md +120 -0
  26. package/packages/cross-chain-identity/docs/API_REFERENCE.md +271 -0
  27. package/packages/cross-chain-identity/docs/CONCEPTS.md +253 -0
  28. package/packages/cross-chain-identity/docs/CREDENTIAL_FLOW.md +195 -0
  29. package/packages/cross-chain-identity/docs/SECURITY.md +70 -0
  30. package/packages/cross-chain-identity/src/CredentialRegistry.sol +245 -0
  31. package/packages/cross-chain-identity/src/CredentialRegistryIdentityValidator.sol +339 -0
  32. package/packages/cross-chain-identity/src/CredentialRegistryIdentityValidatorPolicy.sol +71 -0
  33. package/packages/cross-chain-identity/src/IdentityRegistry.sol +123 -0
  34. package/packages/cross-chain-identity/src/TrustedIssuerRegistry.sol +140 -0
  35. package/packages/cross-chain-identity/src/interfaces/ICredentialDataValidator.sol +30 -0
  36. package/packages/cross-chain-identity/src/interfaces/ICredentialRegistry.sol +170 -0
  37. package/packages/cross-chain-identity/src/interfaces/ICredentialRequirements.sol +192 -0
  38. package/packages/cross-chain-identity/src/interfaces/ICredentialValidator.sol +37 -0
  39. package/packages/cross-chain-identity/src/interfaces/IIdentityRegistry.sol +85 -0
  40. package/packages/cross-chain-identity/src/interfaces/IIdentityValidator.sol +18 -0
  41. package/packages/cross-chain-identity/src/interfaces/ITrustedIssuerRegistry.sol +61 -0
  42. package/packages/cross-chain-identity/test/CredentialRegistry.t.sol +220 -0
  43. package/packages/cross-chain-identity/test/CredentialRegistryIdentityValidator.t.sol +554 -0
  44. package/packages/cross-chain-identity/test/CredentialRegistryIdentityValidatorPolicy.t.sol +114 -0
  45. package/packages/cross-chain-identity/test/IdentityRegistry.t.sol +106 -0
  46. package/packages/cross-chain-identity/test/IdentityValidator.t.sol +969 -0
  47. package/packages/cross-chain-identity/test/TrustedIssuerRegistry.t.sol +123 -0
  48. package/packages/cross-chain-identity/test/helpers/BaseProxyTest.sol +112 -0
  49. package/packages/cross-chain-identity/test/helpers/MockCredentialDataValidator.sol +26 -0
  50. package/packages/cross-chain-identity/test/helpers/MockCredentialRegistryReverting.sol +131 -0
  51. package/packages/policy-management/README.md +197 -0
  52. package/packages/policy-management/docs/API_GUIDE.md +290 -0
  53. package/packages/policy-management/docs/API_REFERENCE.md +173 -0
  54. package/packages/policy-management/docs/CONCEPTS.md +156 -0
  55. package/packages/policy-management/docs/CUSTOM_POLICIES_TUTORIAL.md +195 -0
  56. package/packages/policy-management/docs/POLICY_ORDERING_GUIDE.md +91 -0
  57. package/packages/policy-management/docs/SECURITY.md +57 -0
  58. package/packages/policy-management/src/core/Policy.sol +124 -0
  59. package/packages/policy-management/src/core/PolicyEngine.sol +382 -0
  60. package/packages/policy-management/src/core/PolicyFactory.sol +92 -0
  61. package/packages/policy-management/src/core/PolicyProtected.sol +126 -0
  62. package/packages/policy-management/src/extractors/ComplianceTokenForceTransferExtractor.sol +57 -0
  63. package/packages/policy-management/src/extractors/ComplianceTokenFreezeUnfreezeExtractor.sol +54 -0
  64. package/packages/policy-management/src/extractors/ComplianceTokenMintBurnExtractor.sol +61 -0
  65. package/packages/policy-management/src/extractors/ERC20ApproveExtractor.sol +57 -0
  66. package/packages/policy-management/src/extractors/ERC20TransferExtractor.sol +62 -0
  67. package/packages/policy-management/src/extractors/ERC3643ForcedTransferExtractor.sol +56 -0
  68. package/packages/policy-management/src/extractors/ERC3643FreezeUnfreezeExtractor.sol +55 -0
  69. package/packages/policy-management/src/extractors/ERC3643MintBurnExtractor.sol +51 -0
  70. package/packages/policy-management/src/extractors/ERC3643SetAddressFrozenExtractor.sol +51 -0
  71. package/packages/policy-management/src/interfaces/IExtractor.sol +17 -0
  72. package/packages/policy-management/src/interfaces/IMapper.sol +17 -0
  73. package/packages/policy-management/src/interfaces/IPolicy.sol +61 -0
  74. package/packages/policy-management/src/interfaces/IPolicyEngine.sol +264 -0
  75. package/packages/policy-management/src/interfaces/IPolicyProtected.sol +48 -0
  76. package/packages/policy-management/src/policies/AllowPolicy.sol +104 -0
  77. package/packages/policy-management/src/policies/BypassPolicy.sol +90 -0
  78. package/packages/policy-management/src/policies/IntervalPolicy.sol +223 -0
  79. package/packages/policy-management/src/policies/MaxPolicy.sol +73 -0
  80. package/packages/policy-management/src/policies/OnlyAuthorizedSenderPolicy.sol +84 -0
  81. package/packages/policy-management/src/policies/OnlyOwnerPolicy.sol +35 -0
  82. package/packages/policy-management/src/policies/PausePolicy.sol +82 -0
  83. package/packages/policy-management/src/policies/README.md +632 -0
  84. package/packages/policy-management/src/policies/RejectPolicy.sol +89 -0
  85. package/packages/policy-management/src/policies/RoleBasedAccessControlPolicy.sol +162 -0
  86. package/packages/policy-management/src/policies/SecureMintPolicy.sol +271 -0
  87. package/packages/policy-management/src/policies/VolumePolicy.sol +133 -0
  88. package/packages/policy-management/src/policies/VolumeRatePolicy.sol +192 -0
  89. package/packages/policy-management/test/PolicyEngine.t.sol +368 -0
  90. package/packages/policy-management/test/PolicyFactory.t.sol +114 -0
  91. package/packages/policy-management/test/PolicyProtectedToken.t.sol +75 -0
  92. package/packages/policy-management/test/extractors/ComplianceTokenForceTransferExtractor.t.sol +59 -0
  93. package/packages/policy-management/test/extractors/ComplianceTokenFreezeUnfreezeExtractor.t.sol +74 -0
  94. package/packages/policy-management/test/extractors/ComplianceTokenMintBurnExtractor.t.sol +92 -0
  95. package/packages/policy-management/test/extractors/ERC20ApproveExtractor.t.sol +58 -0
  96. package/packages/policy-management/test/extractors/ERC3643ForcedTransferExtractor.t.sol +59 -0
  97. package/packages/policy-management/test/extractors/ERC3643FreezeUnfreezeExtractor.t.sol +74 -0
  98. package/packages/policy-management/test/extractors/ERC3643MintBurnExtractor.t.sol +73 -0
  99. package/packages/policy-management/test/extractors/ERC3643SetAddressFrozenExtractor.t.sol +56 -0
  100. package/packages/policy-management/test/helpers/BaseProxyTest.sol +75 -0
  101. package/packages/policy-management/test/helpers/CustomMapper.sol +26 -0
  102. package/packages/policy-management/test/helpers/DummyExtractor.sol +11 -0
  103. package/packages/policy-management/test/helpers/ExpectedParameterPolicy.sol +39 -0
  104. package/packages/policy-management/test/helpers/MockAggregatorV3.sol +51 -0
  105. package/packages/policy-management/test/helpers/MockToken.sol +66 -0
  106. package/packages/policy-management/test/helpers/MockTokenExtractor.sol +34 -0
  107. package/packages/policy-management/test/helpers/PolicyAlwaysAllowed.sol +45 -0
  108. package/packages/policy-management/test/helpers/PolicyAlwaysContinue.sol +23 -0
  109. package/packages/policy-management/test/helpers/PolicyAlwaysRejected.sol +23 -0
  110. package/packages/policy-management/test/helpers/PolicyFailingRun.sol +22 -0
  111. package/packages/policy-management/test/policies/AllowPolicy.t.sol +174 -0
  112. package/packages/policy-management/test/policies/BypassPolicy.t.sol +159 -0
  113. package/packages/policy-management/test/policies/IntervalPolicy.t.sol +307 -0
  114. package/packages/policy-management/test/policies/MaxPolicy.t.sol +54 -0
  115. package/packages/policy-management/test/policies/OnlyAuthorizedSenderPolicy.t.sol +95 -0
  116. package/packages/policy-management/test/policies/OnlyOwnerPolicy.t.sol +47 -0
  117. package/packages/policy-management/test/policies/PausePolicy.t.sol +75 -0
  118. package/packages/policy-management/test/policies/RejectPolicy.t.sol +182 -0
  119. package/packages/policy-management/test/policies/RoleBasedAccessControlPolicy.t.sol +223 -0
  120. package/packages/policy-management/test/policies/SecureMintPolicy.t.sol +442 -0
  121. package/packages/policy-management/test/policies/VolumePolicy.t.sol +158 -0
  122. package/packages/policy-management/test/policies/VolumeRatePolicy.t.sol +165 -0
  123. package/packages/tokens/erc-20/src/ComplianceTokenERC20.sol +345 -0
  124. package/packages/tokens/erc-20/src/ComplianceTokenStoreERC20.sol +29 -0
  125. package/packages/tokens/erc-20/test/ComplianceTokenERC20.t.sol +556 -0
  126. package/packages/tokens/erc-20/test/helpers/BaseProxyTest.sol +75 -0
  127. package/packages/tokens/erc-3643/README.md +24 -0
  128. package/packages/tokens/erc-3643/src/ComplianceTokenERC3643.sol +564 -0
  129. package/packages/tokens/erc-3643/src/ComplianceTokenStoreERC3643.sol +30 -0
  130. package/packages/tokens/erc-3643/test/ComplianceTokenERC3643.t.sol +815 -0
  131. package/packages/tokens/erc-3643/test/helpers/BaseProxyTest.sol +76 -0
  132. package/packages/tokens/erc-3643/test/helpers/ExpectedContextPolicy.sol +32 -0
  133. package/packages/vendor/erc-3643/compliance/modular/IModularCompliance.sol +220 -0
  134. package/packages/vendor/erc-3643/registry/interface/IClaimTopicsRegistry.sol +101 -0
  135. package/packages/vendor/erc-3643/registry/interface/IIdentityRegistry.sol +251 -0
  136. package/packages/vendor/erc-3643/registry/interface/IIdentityRegistryStorage.sol +191 -0
  137. package/packages/vendor/erc-3643/registry/interface/ITrustedIssuersRegistry.sol +161 -0
  138. package/packages/vendor/erc-3643/token/IToken.sol +457 -0
  139. package/packages/vendor/onchain-id/interface/IClaimIssuer.sol +53 -0
  140. package/packages/vendor/onchain-id/interface/IERC734.sol +110 -0
  141. package/packages/vendor/onchain-id/interface/IERC735.sol +105 -0
  142. package/packages/vendor/onchain-id/interface/IIdentity.sol +26 -0
  143. package/packages/vendor/onchain-id/interface/IImplementationAuthority.sol +21 -0
  144. package/remappings.txt +6 -0
  145. package/script/DeployComplianceTokenERC20.s.sol +191 -0
  146. package/script/DeployComplianceTokenERC3643.s.sol +208 -0
  147. package/script/DeploySimpleComplianceToken.s.sol +38 -0
  148. package/script/getting_started/DeployGettingStarted.s.sol +74 -0
  149. package/script/getting_started/advanced/DeployAdvancedGettingStarted.s.sol +332 -0
  150. package/script/getting_started/advanced/DeploySanctionsList.s.sol +26 -0
@@ -0,0 +1,75 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {IPolicyEngine, PolicyEngine} from "../src/core/PolicyEngine.sol";
5
+ import {MaxPolicy} from "../src/policies/MaxPolicy.sol";
6
+ import {MockTokenExtractor} from "./helpers/MockTokenExtractor.sol";
7
+ import {MockToken} from "./helpers/MockToken.sol";
8
+ import {BaseProxyTest} from "./helpers/BaseProxyTest.sol";
9
+
10
+ contract SecureToken_MaxPolicy is BaseProxyTest {
11
+ MockToken public token;
12
+ PolicyEngine public policyEngine;
13
+ MaxPolicy public policy;
14
+
15
+ function setUp() public {
16
+ policyEngine = _deployPolicyEngine(true, address(this));
17
+
18
+ token = MockToken(_deployMockToken(address(policyEngine)));
19
+
20
+ MaxPolicy policyImpl = new MaxPolicy();
21
+ policy = MaxPolicy(_deployPolicy(address(policyImpl), address(policyEngine), address(this), abi.encode(100)));
22
+ MockTokenExtractor extractor = new MockTokenExtractor();
23
+
24
+ bytes4[] memory selectors = new bytes4[](3);
25
+ selectors[0] = MockToken.transfer.selector;
26
+ selectors[1] = MockToken.transferWithContext.selector;
27
+ selectors[2] = MockToken.transferFrom.selector;
28
+
29
+ policyEngine.setExtractors(selectors, address(extractor));
30
+
31
+ bytes32[] memory parameterOutputFormat = new bytes32[](1);
32
+ parameterOutputFormat[0] = extractor.PARAM_AMOUNT();
33
+
34
+ policyEngine.addPolicy(address(token), MockToken.transfer.selector, address(policy), parameterOutputFormat);
35
+ policyEngine.addPolicy(
36
+ address(token), MockToken.transferWithContext.selector, address(policy), parameterOutputFormat
37
+ );
38
+ policyEngine.addPolicy(address(token), MockToken.transferFrom.selector, address(policy), parameterOutputFormat);
39
+ }
40
+
41
+ function test_transfer_success() public {
42
+ address recipient = makeAddr("recipient");
43
+ token.transfer(recipient, 100);
44
+ assert(token.balanceOf(recipient) == 100);
45
+ }
46
+
47
+ function test_transferWithContext_success() public {
48
+ address recipient = makeAddr("recipient");
49
+ token.transferWithContext(recipient, 100, "");
50
+ assert(token.balanceOf(recipient) == 100);
51
+ }
52
+
53
+ function test_transfer_defaultPolicyRejected_reverts() public {
54
+ policyEngine.setTargetDefaultPolicyAllow(address(token), false);
55
+
56
+ address recipient = makeAddr("recipient");
57
+
58
+ vm.expectRevert(_encodeRejectedRevert(0, address(0), "no policy allowed the action and default is reject"));
59
+ token.transfer(recipient, 100);
60
+ }
61
+
62
+ function test_transfer_overQuota_reverts() public {
63
+ address recipient = makeAddr("recipient");
64
+ vm.expectRevert(_encodeRejectedRevert(MockToken.transfer.selector, address(policy), "amount exceeds maximum limit"));
65
+ token.transfer(recipient, 200);
66
+ }
67
+
68
+ function test_transferWithContext_overQuota_reverts() public {
69
+ address recipient = makeAddr("recipient");
70
+ vm.expectRevert(
71
+ _encodeRejectedRevert(MockToken.transferWithContext.selector, address(policy), "amount exceeds maximum limit")
72
+ );
73
+ token.transferWithContext(recipient, 200, "");
74
+ }
75
+ }
@@ -0,0 +1,59 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {Test} from "forge-std/Test.sol";
5
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
7
+ import {ComplianceTokenForceTransferExtractor} from
8
+ "@chainlink/policy-management/extractors/ComplianceTokenForceTransferExtractor.sol";
9
+ import {ComplianceTokenERC20} from "../../../tokens/erc-20/src/ComplianceTokenERC20.sol";
10
+
11
+ contract ComplianceTokenForceTransferExtractorTest is Test {
12
+ ComplianceTokenForceTransferExtractor public extractor;
13
+ address public deployer;
14
+ address public recipient;
15
+
16
+ function setUp() public {
17
+ deployer = makeAddr("deployer");
18
+ recipient = makeAddr("recipient");
19
+
20
+ vm.startPrank(deployer, deployer);
21
+
22
+ extractor = new ComplianceTokenForceTransferExtractor();
23
+
24
+ vm.stopPrank();
25
+ }
26
+
27
+ function test_extract_forcedTransfer_succeeds() public {
28
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
29
+ selector: ComplianceTokenERC20.forceTransfer.selector,
30
+ data: abi.encode(deployer, recipient, 888),
31
+ sender: deployer,
32
+ context: ""
33
+ });
34
+
35
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
36
+ vm.assertEq(params.length, 3);
37
+ vm.assertEq(params[0].name, keccak256("from"));
38
+ vm.assertEq(params[1].name, keccak256("to"));
39
+ vm.assertEq(params[2].name, keccak256("amount"));
40
+ address from = abi.decode(params[0].value, (address));
41
+ vm.assertEq(from, deployer);
42
+ address to = abi.decode(params[1].value, (address));
43
+ vm.assertEq(to, recipient);
44
+ uint256 value = abi.decode(params[2].value, (uint256));
45
+ vm.assertEq(value, 888);
46
+ }
47
+
48
+ function test_extract_transfer_fails() public {
49
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
50
+ selector: ComplianceTokenERC20.transfer.selector,
51
+ data: abi.encode(recipient, 3643),
52
+ sender: deployer,
53
+ context: ""
54
+ });
55
+
56
+ vm.expectPartialRevert(IPolicyEngine.UnsupportedSelector.selector);
57
+ extractor.extract(payload);
58
+ }
59
+ }
@@ -0,0 +1,74 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {Test} from "forge-std/Test.sol";
5
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
7
+ import {ComplianceTokenFreezeUnfreezeExtractor} from
8
+ "@chainlink/policy-management/extractors/ComplianceTokenFreezeUnfreezeExtractor.sol";
9
+ import {ComplianceTokenERC20} from "../../../tokens/erc-20/src/ComplianceTokenERC20.sol";
10
+
11
+ contract ComplianceTokenFreezeUnfreezeExtractorTest is Test {
12
+ ComplianceTokenFreezeUnfreezeExtractor public extractor;
13
+ address public deployer;
14
+ address public holder;
15
+
16
+ function setUp() public {
17
+ deployer = makeAddr("deployer");
18
+ holder = makeAddr("holder");
19
+
20
+ vm.startPrank(deployer, deployer);
21
+
22
+ extractor = new ComplianceTokenFreezeUnfreezeExtractor();
23
+
24
+ vm.stopPrank();
25
+ }
26
+
27
+ function test_extract_freeze_succeeds() public {
28
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
29
+ selector: ComplianceTokenERC20.freeze.selector,
30
+ data: abi.encode(holder, 36),
31
+ sender: deployer,
32
+ context: ""
33
+ });
34
+
35
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
36
+ vm.assertEq(params.length, 2);
37
+ vm.assertEq(params[0].name, keccak256("account"));
38
+ vm.assertEq(params[1].name, keccak256("amount"));
39
+ address account = abi.decode(params[0].value, (address));
40
+ vm.assertEq(account, holder);
41
+ uint256 value = abi.decode(params[1].value, (uint256));
42
+ vm.assertEq(value, 36);
43
+ }
44
+
45
+ function test_extract_unfreeze_succeeds() public {
46
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
47
+ selector: ComplianceTokenERC20.unfreeze.selector,
48
+ data: abi.encode(holder, 43),
49
+ sender: deployer,
50
+ context: ""
51
+ });
52
+
53
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
54
+ vm.assertEq(params.length, 2);
55
+ vm.assertEq(params[0].name, keccak256("account"));
56
+ vm.assertEq(params[1].name, keccak256("amount"));
57
+ address account = abi.decode(params[0].value, (address));
58
+ vm.assertEq(account, holder);
59
+ uint256 value = abi.decode(params[1].value, (uint256));
60
+ vm.assertEq(value, 43);
61
+ }
62
+
63
+ function test_extract_transfer_fails() public {
64
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
65
+ selector: ComplianceTokenERC20.transfer.selector,
66
+ data: abi.encode(holder, 123),
67
+ sender: deployer,
68
+ context: ""
69
+ });
70
+
71
+ vm.expectPartialRevert(IPolicyEngine.UnsupportedSelector.selector);
72
+ extractor.extract(payload);
73
+ }
74
+ }
@@ -0,0 +1,92 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {Test} from "forge-std/Test.sol";
5
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
7
+ import {ComplianceTokenMintBurnExtractor} from
8
+ "@chainlink/policy-management/extractors/ComplianceTokenMintBurnExtractor.sol";
9
+ import {ComplianceTokenERC20} from "../../../tokens/erc-20/src/ComplianceTokenERC20.sol";
10
+
11
+ contract ComplianceTokenMintBurnExtractorTest is Test {
12
+ ComplianceTokenMintBurnExtractor public extractor;
13
+ address public deployer;
14
+ address public recipient;
15
+
16
+ function setUp() public {
17
+ deployer = makeAddr("deployer");
18
+ recipient = makeAddr("recipient");
19
+
20
+ vm.startPrank(deployer, deployer);
21
+
22
+ extractor = new ComplianceTokenMintBurnExtractor();
23
+
24
+ vm.stopPrank();
25
+ }
26
+
27
+ function test_extract_mint_succeeds() public {
28
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
29
+ selector: ComplianceTokenERC20.mint.selector,
30
+ data: abi.encode(recipient, 123),
31
+ sender: deployer,
32
+ context: ""
33
+ });
34
+
35
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
36
+ vm.assertEq(params.length, 2);
37
+ vm.assertEq(params[0].name, keccak256("account"));
38
+ vm.assertEq(params[1].name, keccak256("amount"));
39
+ address user = abi.decode(params[0].value, (address));
40
+ vm.assertEq(user, recipient);
41
+ uint256 value = abi.decode(params[1].value, (uint256));
42
+ vm.assertEq(value, 123);
43
+ }
44
+
45
+ function test_extract_burn_succeeds() public {
46
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
47
+ selector: ComplianceTokenERC20.burn.selector,
48
+ data: abi.encode(123),
49
+ sender: recipient,
50
+ context: ""
51
+ });
52
+
53
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
54
+ vm.assertEq(params.length, 2);
55
+ vm.assertEq(params[0].name, keccak256("account"));
56
+ vm.assertEq(params[1].name, keccak256("amount"));
57
+ address user = abi.decode(params[0].value, (address));
58
+ vm.assertEq(user, recipient);
59
+ uint256 value = abi.decode(params[1].value, (uint256));
60
+ vm.assertEq(value, 123);
61
+ }
62
+
63
+ function test_extract_burnFrom_succeeds() public {
64
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
65
+ selector: ComplianceTokenERC20.burnFrom.selector,
66
+ data: abi.encode(recipient, 123),
67
+ sender: deployer,
68
+ context: ""
69
+ });
70
+
71
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
72
+ vm.assertEq(params.length, 2);
73
+ vm.assertEq(params[0].name, keccak256("account"));
74
+ vm.assertEq(params[1].name, keccak256("amount"));
75
+ address user = abi.decode(params[0].value, (address));
76
+ vm.assertEq(user, recipient);
77
+ uint256 value = abi.decode(params[1].value, (uint256));
78
+ vm.assertEq(value, 123);
79
+ }
80
+
81
+ function test_extract_transfer_fails() public {
82
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
83
+ selector: ComplianceTokenERC20.transfer.selector,
84
+ data: abi.encode(recipient, 123),
85
+ sender: deployer,
86
+ context: ""
87
+ });
88
+
89
+ vm.expectPartialRevert(IPolicyEngine.UnsupportedSelector.selector);
90
+ extractor.extract(payload);
91
+ }
92
+ }
@@ -0,0 +1,58 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {Test} from "forge-std/Test.sol";
5
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
7
+ import {ERC20ApproveExtractor} from "@chainlink/policy-management/extractors/ERC20ApproveExtractor.sol";
8
+ import {IToken} from "../../../vendor/erc-3643/token/IToken.sol";
9
+
10
+ contract ERC20ApproveExtractorTest is Test {
11
+ ERC20ApproveExtractor public extractor;
12
+ address public deployer;
13
+ address public recipient;
14
+
15
+ function setUp() public {
16
+ deployer = makeAddr("deployer");
17
+ recipient = makeAddr("recipient");
18
+
19
+ vm.startPrank(deployer, deployer);
20
+
21
+ extractor = new ERC20ApproveExtractor();
22
+
23
+ vm.stopPrank();
24
+ }
25
+
26
+ function test_extract_approve_succeeds() public {
27
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
28
+ selector: IERC20.approve.selector,
29
+ data: abi.encode(recipient, 999),
30
+ sender: deployer,
31
+ context: ""
32
+ });
33
+
34
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
35
+ vm.assertEq(params.length, 3);
36
+ vm.assertEq(params[0].name, keccak256("account"));
37
+ vm.assertEq(params[1].name, keccak256("spender"));
38
+ vm.assertEq(params[2].name, keccak256("amount"));
39
+ address approver = abi.decode(params[0].value, (address));
40
+ vm.assertEq(approver, deployer);
41
+ address spender = abi.decode(params[1].value, (address));
42
+ vm.assertEq(spender, recipient);
43
+ uint256 value = abi.decode(params[2].value, (uint256));
44
+ vm.assertEq(value, 999);
45
+ }
46
+
47
+ function test_extract_transfer_fails() public {
48
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
49
+ selector: IERC20.transfer.selector,
50
+ data: abi.encode(recipient, 999),
51
+ sender: deployer,
52
+ context: ""
53
+ });
54
+
55
+ vm.expectPartialRevert(IPolicyEngine.UnsupportedSelector.selector);
56
+ extractor.extract(payload);
57
+ }
58
+ }
@@ -0,0 +1,59 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {Test} from "forge-std/Test.sol";
5
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
7
+ import {ERC3643ForcedTransferExtractor} from
8
+ "@chainlink/policy-management/extractors/ERC3643ForcedTransferExtractor.sol";
9
+ import {IToken} from "../../../vendor/erc-3643/token/IToken.sol";
10
+
11
+ contract ERC3643ForcedTransferExtractorTest is Test {
12
+ ERC3643ForcedTransferExtractor public extractor;
13
+ address public deployer;
14
+ address public recipient;
15
+
16
+ function setUp() public {
17
+ deployer = makeAddr("deployer");
18
+ recipient = makeAddr("recipient");
19
+
20
+ vm.startPrank(deployer, deployer);
21
+
22
+ extractor = new ERC3643ForcedTransferExtractor();
23
+
24
+ vm.stopPrank();
25
+ }
26
+
27
+ function test_extract_forcedTransfer_succeeds() public {
28
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
29
+ selector: IToken.forcedTransfer.selector,
30
+ data: abi.encode(deployer, recipient, 888),
31
+ sender: deployer,
32
+ context: ""
33
+ });
34
+
35
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
36
+ vm.assertEq(params.length, 3);
37
+ vm.assertEq(params[0].name, keccak256("from"));
38
+ vm.assertEq(params[1].name, keccak256("to"));
39
+ vm.assertEq(params[2].name, keccak256("amount"));
40
+ address from = abi.decode(params[0].value, (address));
41
+ vm.assertEq(from, deployer);
42
+ address to = abi.decode(params[1].value, (address));
43
+ vm.assertEq(to, recipient);
44
+ uint256 value = abi.decode(params[2].value, (uint256));
45
+ vm.assertEq(value, 888);
46
+ }
47
+
48
+ function test_extract_transfer_fails() public {
49
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
50
+ selector: IERC20.transfer.selector,
51
+ data: abi.encode(recipient, 3643),
52
+ sender: deployer,
53
+ context: ""
54
+ });
55
+
56
+ vm.expectPartialRevert(IPolicyEngine.UnsupportedSelector.selector);
57
+ extractor.extract(payload);
58
+ }
59
+ }
@@ -0,0 +1,74 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {Test} from "forge-std/Test.sol";
5
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
7
+ import {ERC3643FreezeUnfreezeExtractor} from
8
+ "@chainlink/policy-management/extractors/ERC3643FreezeUnfreezeExtractor.sol";
9
+ import {IToken} from "../../../vendor/erc-3643/token/IToken.sol";
10
+
11
+ contract ERC3643FreezeUnfreezeExtractorTest is Test {
12
+ ERC3643FreezeUnfreezeExtractor public extractor;
13
+ address public deployer;
14
+ address public holder;
15
+
16
+ function setUp() public {
17
+ deployer = makeAddr("deployer");
18
+ holder = makeAddr("holder");
19
+
20
+ vm.startPrank(deployer, deployer);
21
+
22
+ extractor = new ERC3643FreezeUnfreezeExtractor();
23
+
24
+ vm.stopPrank();
25
+ }
26
+
27
+ function test_extract_freeze_succeeds() public {
28
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
29
+ selector: IToken.freezePartialTokens.selector,
30
+ data: abi.encode(holder, 36),
31
+ sender: deployer,
32
+ context: ""
33
+ });
34
+
35
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
36
+ vm.assertEq(params.length, 2);
37
+ vm.assertEq(params[0].name, keccak256("account"));
38
+ vm.assertEq(params[1].name, keccak256("amount"));
39
+ address account = abi.decode(params[0].value, (address));
40
+ vm.assertEq(account, holder);
41
+ uint256 value = abi.decode(params[1].value, (uint256));
42
+ vm.assertEq(value, 36);
43
+ }
44
+
45
+ function test_extract_unfreeze_succeeds() public {
46
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
47
+ selector: IToken.unfreezePartialTokens.selector,
48
+ data: abi.encode(holder, 43),
49
+ sender: deployer,
50
+ context: ""
51
+ });
52
+
53
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
54
+ vm.assertEq(params.length, 2);
55
+ vm.assertEq(params[0].name, keccak256("account"));
56
+ vm.assertEq(params[1].name, keccak256("amount"));
57
+ address account = abi.decode(params[0].value, (address));
58
+ vm.assertEq(account, holder);
59
+ uint256 value = abi.decode(params[1].value, (uint256));
60
+ vm.assertEq(value, 43);
61
+ }
62
+
63
+ function test_extract_transfer_fails() public {
64
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
65
+ selector: IERC20.transfer.selector,
66
+ data: abi.encode(holder, 123),
67
+ sender: deployer,
68
+ context: ""
69
+ });
70
+
71
+ vm.expectPartialRevert(IPolicyEngine.UnsupportedSelector.selector);
72
+ extractor.extract(payload);
73
+ }
74
+ }
@@ -0,0 +1,73 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {Test} from "forge-std/Test.sol";
5
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
7
+ import {ERC3643MintBurnExtractor} from "@chainlink/policy-management/extractors/ERC3643MintBurnExtractor.sol";
8
+ import {IToken} from "../../../vendor/erc-3643/token/IToken.sol";
9
+
10
+ contract ERC3643MintBurnExtractorTest is Test {
11
+ ERC3643MintBurnExtractor public extractor;
12
+ address public deployer;
13
+ address public recipient;
14
+
15
+ function setUp() public {
16
+ deployer = makeAddr("deployer");
17
+ recipient = makeAddr("recipient");
18
+
19
+ vm.startPrank(deployer, deployer);
20
+
21
+ extractor = new ERC3643MintBurnExtractor();
22
+
23
+ vm.stopPrank();
24
+ }
25
+
26
+ function test_extract_mint_succeeds() public {
27
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
28
+ selector: IToken.mint.selector,
29
+ data: abi.encode(recipient, 123),
30
+ sender: deployer,
31
+ context: ""
32
+ });
33
+
34
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
35
+ vm.assertEq(params.length, 2);
36
+ vm.assertEq(params[0].name, keccak256("account"));
37
+ vm.assertEq(params[1].name, keccak256("amount"));
38
+ address user = abi.decode(params[0].value, (address));
39
+ vm.assertEq(user, recipient);
40
+ uint256 value = abi.decode(params[1].value, (uint256));
41
+ vm.assertEq(value, 123);
42
+ }
43
+
44
+ function test_extract_burn_succeeds() public {
45
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
46
+ selector: IToken.burn.selector,
47
+ data: abi.encode(recipient, 123),
48
+ sender: deployer,
49
+ context: ""
50
+ });
51
+
52
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
53
+ vm.assertEq(params.length, 2);
54
+ vm.assertEq(params[0].name, keccak256("account"));
55
+ vm.assertEq(params[1].name, keccak256("amount"));
56
+ address user = abi.decode(params[0].value, (address));
57
+ vm.assertEq(user, recipient);
58
+ uint256 value = abi.decode(params[1].value, (uint256));
59
+ vm.assertEq(value, 123);
60
+ }
61
+
62
+ function test_extract_transfer_fails() public {
63
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
64
+ selector: IERC20.transfer.selector,
65
+ data: abi.encode(recipient, 123),
66
+ sender: deployer,
67
+ context: ""
68
+ });
69
+
70
+ vm.expectPartialRevert(IPolicyEngine.UnsupportedSelector.selector);
71
+ extractor.extract(payload);
72
+ }
73
+ }
@@ -0,0 +1,56 @@
1
+ // SPDX-License-Identifier: BUSL-1.1
2
+ pragma solidity 0.8.26;
3
+
4
+ import {Test} from "forge-std/Test.sol";
5
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6
+ import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
7
+ import {ERC3643SetAddressFrozenExtractor} from
8
+ "@chainlink/policy-management/extractors/ERC3643SetAddressFrozenExtractor.sol";
9
+ import {IToken} from "../../../vendor/erc-3643/token/IToken.sol";
10
+
11
+ contract ERC3643SetAddressFrozenExtractorTest is Test {
12
+ ERC3643SetAddressFrozenExtractor public extractor;
13
+ address public deployer;
14
+ address public holder;
15
+
16
+ function setUp() public {
17
+ deployer = makeAddr("deployer");
18
+ holder = makeAddr("holder");
19
+
20
+ vm.startPrank(deployer, deployer);
21
+
22
+ extractor = new ERC3643SetAddressFrozenExtractor();
23
+
24
+ vm.stopPrank();
25
+ }
26
+
27
+ function test_extract_setAddressFrozen_succeeds() public {
28
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
29
+ selector: IToken.setAddressFrozen.selector,
30
+ data: abi.encode(holder, true),
31
+ sender: deployer,
32
+ context: ""
33
+ });
34
+
35
+ IPolicyEngine.Parameter[] memory params = extractor.extract(payload);
36
+ vm.assertEq(params.length, 2);
37
+ vm.assertEq(params[0].name, keccak256("account"));
38
+ vm.assertEq(params[1].name, keccak256("value"));
39
+ address account = abi.decode(params[0].value, (address));
40
+ vm.assertEq(account, holder);
41
+ bool value = abi.decode(params[1].value, (bool));
42
+ vm.assertTrue(value);
43
+ }
44
+
45
+ function test_extract_transfer_fails() public {
46
+ IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
47
+ selector: IERC20.transfer.selector,
48
+ data: abi.encode(holder, 123),
49
+ sender: deployer,
50
+ context: ""
51
+ });
52
+
53
+ vm.expectPartialRevert(IPolicyEngine.UnsupportedSelector.selector);
54
+ extractor.extract(payload);
55
+ }
56
+ }