@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.
- package/.github/workflows/npm-publish.yml +28 -0
- package/README.md +9 -1
- package/UPGRADE_GUIDE.md +754 -0
- package/getting_started/GETTING_STARTED.md +6 -0
- package/getting_started/MyVault.sol +2 -2
- package/getting_started/advanced/SanctionsPolicy.sol +6 -2
- package/package.json +3 -3
- package/packages/cross-chain-identity/docs/API_REFERENCE.md +2 -0
- package/packages/cross-chain-identity/src/CredentialRegistry.sol +9 -7
- package/packages/cross-chain-identity/src/CredentialRegistryFactory.sol +96 -0
- package/packages/cross-chain-identity/src/CredentialRegistryIdentityValidator.sol +15 -4
- package/packages/cross-chain-identity/src/CredentialRegistryIdentityValidatorPolicy.sol +10 -7
- package/packages/cross-chain-identity/src/IdentityRegistry.sol +33 -17
- package/packages/cross-chain-identity/src/IdentityRegistryFactory.sol +96 -0
- package/packages/cross-chain-identity/src/TrustedIssuerRegistry.sol +8 -6
- package/packages/cross-chain-identity/src/TrustedIssuerRegistryFactory.sol +96 -0
- package/packages/cross-chain-identity/src/interfaces/ICredentialRegistry.sol +6 -0
- package/packages/cross-chain-identity/src/interfaces/ICredentialRequirements.sol +2 -1
- package/packages/cross-chain-identity/src/interfaces/IIdentityRegistry.sol +7 -1
- package/packages/cross-chain-identity/src/interfaces/ITrustedIssuerRegistry.sol +6 -0
- package/packages/cross-chain-identity/test/CredentialRegistry.t.sol +1 -1
- package/packages/cross-chain-identity/test/CredentialRegistryFactory.t.sol +105 -0
- package/packages/cross-chain-identity/test/CredentialRegistryIdentityValidator.t.sol +16 -1
- package/packages/cross-chain-identity/test/CredentialRegistryIdentityValidatorPolicy.t.sol +58 -1
- package/packages/cross-chain-identity/test/IdentityRegistry.t.sol +140 -1
- package/packages/cross-chain-identity/test/IdentityRegistryFactory.t.sol +103 -0
- package/packages/cross-chain-identity/test/IdentityValidator.t.sol +1 -1
- package/packages/cross-chain-identity/test/TrustedIssuerRegistry.t.sol +1 -1
- package/packages/cross-chain-identity/test/TrustedIssuerRegistryFactory.t.sol +107 -0
- package/packages/cross-chain-identity/test/helpers/BaseProxyTest.sol +1 -1
- package/packages/cross-chain-identity/test/helpers/MockCredentialDataValidator.sol +1 -1
- package/packages/cross-chain-identity/test/helpers/MockCredentialRegistryReverting.sol +3 -1
- package/packages/policy-management/README.md +1 -0
- package/packages/policy-management/docs/API_GUIDE.md +2 -0
- package/packages/policy-management/docs/API_REFERENCE.md +3 -1
- package/packages/policy-management/docs/CUSTOM_POLICIES_TUTORIAL.md +10 -4
- package/packages/policy-management/src/core/Policy.sol +5 -4
- package/packages/policy-management/src/core/PolicyEngine.sol +113 -57
- package/packages/policy-management/src/core/PolicyEngineFactory.sol +102 -0
- package/packages/policy-management/src/core/PolicyFactory.sol +1 -1
- package/packages/policy-management/src/core/PolicyProtected.sol +28 -55
- package/packages/policy-management/src/core/PolicyProtectedUpgradeable.sol +134 -0
- package/packages/policy-management/src/extractors/ComplianceTokenForceTransferExtractor.sol +4 -1
- package/packages/policy-management/src/extractors/ComplianceTokenFreezeUnfreezeExtractor.sol +4 -1
- package/packages/policy-management/src/extractors/ComplianceTokenMintBurnExtractor.sol +4 -1
- package/packages/policy-management/src/extractors/ERC20ApproveExtractor.sol +4 -1
- package/packages/policy-management/src/extractors/ERC20TransferExtractor.sol +4 -1
- package/packages/policy-management/src/extractors/ERC3643ForcedTransferExtractor.sol +4 -1
- package/packages/policy-management/src/extractors/ERC3643FreezeUnfreezeExtractor.sol +4 -1
- package/packages/policy-management/src/extractors/ERC3643MintBurnExtractor.sol +4 -1
- package/packages/policy-management/src/extractors/ERC3643SetAddressFrozenExtractor.sol +4 -1
- package/packages/policy-management/src/interfaces/ICertifiedActionValidator.sol +110 -0
- package/packages/policy-management/src/interfaces/IExtractor.sol +6 -0
- package/packages/policy-management/src/interfaces/IMapper.sol +6 -0
- package/packages/policy-management/src/interfaces/IPolicy.sol +6 -0
- package/packages/policy-management/src/interfaces/IPolicyEngine.sol +90 -10
- package/packages/policy-management/src/interfaces/IPolicyProtected.sol +6 -0
- package/packages/policy-management/src/libraries/CertifiedActionLib.sol +47 -0
- package/packages/policy-management/src/policies/AllowPolicy.sol +12 -7
- package/packages/policy-management/src/policies/BypassPolicy.sol +23 -5
- package/packages/policy-management/src/policies/CertifiedActionDONValidatorPolicy.sol +156 -0
- package/packages/policy-management/src/policies/CertifiedActionERC20TransferValidatorPolicy.sol +202 -0
- package/packages/policy-management/src/policies/CertifiedActionValidatorPolicy.sol +365 -0
- package/packages/policy-management/src/policies/IntervalPolicy.sol +64 -48
- package/packages/policy-management/src/policies/MaxPolicy.sol +7 -5
- package/packages/policy-management/src/policies/OnlyAuthorizedSenderPolicy.sol +20 -4
- package/packages/policy-management/src/policies/OnlyOwnerPolicy.sol +4 -2
- package/packages/policy-management/src/policies/PausePolicy.sol +16 -15
- package/packages/policy-management/src/policies/RejectPolicy.sol +23 -5
- package/packages/policy-management/src/policies/RoleBasedAccessControlPolicy.sol +7 -5
- package/packages/policy-management/src/policies/SecureMintPolicy.sol +136 -48
- package/packages/policy-management/src/policies/VolumePolicy.sol +9 -5
- package/packages/policy-management/src/policies/VolumeRatePolicy.sol +11 -7
- package/packages/policy-management/test/PolicyEngine.t.sol +131 -23
- package/packages/policy-management/test/PolicyEngineFactory.t.sol +95 -0
- package/packages/policy-management/test/PolicyFactory.t.sol +1 -1
- package/packages/policy-management/test/{PolicyProtectedToken.t.sol → PolicyProtected.t.sol} +54 -8
- package/packages/policy-management/test/PolicyProtectedUpgradeable.t.sol +126 -0
- package/packages/policy-management/test/extractors/ComplianceTokenForceTransferExtractor.t.sol +1 -1
- package/packages/policy-management/test/extractors/ComplianceTokenFreezeUnfreezeExtractor.t.sol +1 -1
- package/packages/policy-management/test/extractors/ComplianceTokenMintBurnExtractor.t.sol +1 -1
- package/packages/policy-management/test/extractors/ERC20ApproveExtractor.t.sol +1 -1
- package/packages/policy-management/test/extractors/ERC3643ForcedTransferExtractor.t.sol +1 -1
- package/packages/policy-management/test/extractors/ERC3643FreezeUnfreezeExtractor.t.sol +1 -1
- package/packages/policy-management/test/extractors/ERC3643MintBurnExtractor.t.sol +1 -1
- package/packages/policy-management/test/extractors/ERC3643SetAddressFrozenExtractor.t.sol +1 -1
- package/packages/policy-management/test/helpers/BaseCertifiedActionTest.sol +44 -0
- package/packages/policy-management/test/helpers/BaseProxyTest.sol +88 -7
- package/packages/policy-management/test/helpers/CustomMapper.sol +3 -1
- package/packages/policy-management/test/helpers/DummyExtractor.sol +3 -1
- package/packages/policy-management/test/helpers/ExpectedParameterPolicy.sol +3 -1
- package/packages/policy-management/test/helpers/FaultyPolicyEngine.sol +54 -0
- package/packages/policy-management/test/helpers/MockCertifiedActionValidatorPolicyExtension.sol +46 -0
- package/packages/policy-management/test/helpers/MockToken.sol +2 -5
- package/packages/policy-management/test/helpers/MockTokenExtractor.sol +9 -4
- package/packages/policy-management/test/helpers/MockTokenUpgradeable.sol +66 -0
- package/packages/policy-management/test/helpers/PolicyAlwaysAllowed.sol +3 -1
- package/packages/policy-management/test/helpers/PolicyAlwaysContinue.sol +3 -1
- package/packages/policy-management/test/helpers/PolicyAlwaysRejected.sol +10 -1
- package/packages/policy-management/test/helpers/PolicyFailingRun.sol +3 -1
- package/packages/policy-management/test/policies/AllowPolicy.t.sol +39 -23
- package/packages/policy-management/test/policies/BypassPolicy.t.sol +48 -20
- package/packages/policy-management/test/policies/CertifiedActionDONValidatorPolicy.t.sol +172 -0
- package/packages/policy-management/test/policies/CertifiedActionERC20TransferValidatorPolicy.t.sol +217 -0
- package/packages/policy-management/test/policies/CertifiedActionValidatorPolicy.t.sol +1083 -0
- package/packages/policy-management/test/policies/IntervalPolicy.t.sol +105 -55
- package/packages/policy-management/test/policies/MaxPolicy.t.sol +15 -7
- package/packages/policy-management/test/policies/OnlyAuthorizedSenderPolicy.t.sol +91 -16
- package/packages/policy-management/test/policies/OnlyOwnerPolicy.t.sol +11 -7
- package/packages/policy-management/test/policies/PausePolicy.t.sol +46 -16
- package/packages/policy-management/test/policies/RejectPolicy.t.sol +52 -24
- package/packages/policy-management/test/policies/RoleBasedAccessControlPolicy.t.sol +50 -30
- package/packages/policy-management/test/policies/SecureMintPolicy.t.sol +211 -32
- package/packages/policy-management/test/policies/VolumePolicy.t.sol +20 -10
- package/packages/policy-management/test/policies/VolumeRatePolicy.t.sol +24 -18
- package/packages/tokens/erc-20/src/ComplianceTokenERC20.sol +4 -7
- package/packages/tokens/erc-20/src/ComplianceTokenStoreERC20.sol +4 -4
- package/packages/tokens/erc-20/test/ComplianceTokenERC20.t.sol +92 -82
- package/packages/tokens/erc-20/test/helpers/BaseProxyTest.sol +74 -1
- package/packages/tokens/erc-3643/src/ComplianceTokenERC3643.sol +12 -7
- package/packages/tokens/erc-3643/src/ComplianceTokenStoreERC3643.sol +4 -4
- package/packages/tokens/erc-3643/test/ComplianceTokenERC3643.t.sol +108 -119
- package/packages/tokens/erc-3643/test/helpers/BaseProxyTest.sol +74 -1
- package/packages/tokens/erc-3643/test/helpers/ExpectedContextPolicy.sol +3 -1
- package/remappings.txt +1 -0
- package/script/DeployCertifiedActionsComplianceTokenERC3643.s.sol +125 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
-
pragma solidity 0.8.
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
3
|
|
|
4
4
|
import {IPolicyEngine, PolicyEngine} from "@chainlink/policy-management/core/PolicyEngine.sol";
|
|
5
5
|
import {ERC20TransferExtractor} from "@chainlink/policy-management/extractors/ERC20TransferExtractor.sol";
|
|
6
6
|
import {BypassPolicy} from "@chainlink/policy-management/policies/BypassPolicy.sol";
|
|
7
|
-
import {
|
|
7
|
+
import {MockTokenUpgradeable} from "../helpers/MockTokenUpgradeable.sol";
|
|
8
8
|
import {ERC3643MintBurnExtractor} from "@chainlink/policy-management/extractors/ERC3643MintBurnExtractor.sol";
|
|
9
9
|
import {BaseProxyTest} from "../helpers/BaseProxyTest.sol";
|
|
10
10
|
|
|
11
11
|
contract BypassPolicyTest is BaseProxyTest {
|
|
12
12
|
PolicyEngine public policyEngine;
|
|
13
|
-
|
|
13
|
+
MockTokenUpgradeable public token;
|
|
14
14
|
BypassPolicy public bypassPolicy;
|
|
15
15
|
address public deployer;
|
|
16
16
|
address public account;
|
|
@@ -30,26 +30,31 @@ contract BypassPolicyTest is BaseProxyTest {
|
|
|
30
30
|
// add account by default
|
|
31
31
|
bypassPolicy.allowAddress(account);
|
|
32
32
|
|
|
33
|
-
token =
|
|
33
|
+
token = MockTokenUpgradeable(_deployMockToken(address(policyEngine)));
|
|
34
34
|
|
|
35
35
|
// set up the bypassPolicy to check the recipient and origin address of token transfers
|
|
36
36
|
ERC20TransferExtractor transferExtractor = new ERC20TransferExtractor();
|
|
37
37
|
bytes32[] memory transferPolicyParams = new bytes32[](2);
|
|
38
38
|
transferPolicyParams[0] = transferExtractor.PARAM_TO();
|
|
39
39
|
transferPolicyParams[1] = transferExtractor.PARAM_FROM();
|
|
40
|
-
policyEngine.setExtractor(
|
|
41
|
-
policyEngine.addPolicy(
|
|
40
|
+
policyEngine.setExtractor(MockTokenUpgradeable.transfer.selector, address(transferExtractor));
|
|
41
|
+
policyEngine.addPolicy(
|
|
42
|
+
address(token), MockTokenUpgradeable.transfer.selector, address(bypassPolicy), transferPolicyParams
|
|
43
|
+
);
|
|
42
44
|
// set up the bypassPolicy to check the mint account (single account)
|
|
43
45
|
ERC3643MintBurnExtractor mintBurnExtractor = new ERC3643MintBurnExtractor();
|
|
44
46
|
bytes32[] memory mintPolicyParams = new bytes32[](1);
|
|
45
47
|
mintPolicyParams[0] = mintBurnExtractor.PARAM_ACCOUNT();
|
|
46
|
-
policyEngine.setExtractor(
|
|
47
|
-
policyEngine.addPolicy(address(token),
|
|
48
|
+
policyEngine.setExtractor(MockTokenUpgradeable.mint.selector, address(mintBurnExtractor));
|
|
49
|
+
policyEngine.addPolicy(address(token), MockTokenUpgradeable.mint.selector, address(bypassPolicy), mintPolicyParams);
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
function test_allowAddress_succeeds() public {
|
|
51
53
|
vm.startPrank(deployer, deployer);
|
|
52
54
|
|
|
55
|
+
vm.expectEmit(true, true, true, true);
|
|
56
|
+
emit BypassPolicy.AddressAllowed(recipient);
|
|
57
|
+
|
|
53
58
|
// add the address to the allow list
|
|
54
59
|
bypassPolicy.allowAddress(recipient);
|
|
55
60
|
vm.assertEq(bypassPolicy.addressAllowed(recipient), true);
|
|
@@ -74,6 +79,9 @@ contract BypassPolicyTest is BaseProxyTest {
|
|
|
74
79
|
bypassPolicy.allowAddress(recipient);
|
|
75
80
|
vm.assertEq(bypassPolicy.addressAllowed(recipient), true);
|
|
76
81
|
|
|
82
|
+
vm.expectEmit(true, true, true, true);
|
|
83
|
+
emit BypassPolicy.AddressDisallowed(recipient);
|
|
84
|
+
|
|
77
85
|
// remove the address from the bypass list
|
|
78
86
|
bypassPolicy.disallowAddress(recipient);
|
|
79
87
|
vm.assertEq(bypassPolicy.addressAllowed(recipient), false);
|
|
@@ -105,7 +113,13 @@ contract BypassPolicyTest is BaseProxyTest {
|
|
|
105
113
|
vm.startPrank(account, account);
|
|
106
114
|
|
|
107
115
|
// transfer from address to recipient (reverts)
|
|
108
|
-
|
|
116
|
+
_expectRejectedRevert(
|
|
117
|
+
address(0),
|
|
118
|
+
"no policy allowed the action and default is reject",
|
|
119
|
+
MockTokenUpgradeable.transfer.selector,
|
|
120
|
+
account,
|
|
121
|
+
abi.encode(recipient, 100)
|
|
122
|
+
);
|
|
109
123
|
token.transfer(recipient, 100);
|
|
110
124
|
}
|
|
111
125
|
|
|
@@ -125,7 +139,13 @@ contract BypassPolicyTest is BaseProxyTest {
|
|
|
125
139
|
|
|
126
140
|
// transfer from address to recipient (should revert after removal)
|
|
127
141
|
vm.startPrank(account, account);
|
|
128
|
-
|
|
142
|
+
_expectRejectedRevert(
|
|
143
|
+
address(0),
|
|
144
|
+
"no policy allowed the action and default is reject",
|
|
145
|
+
MockTokenUpgradeable.transfer.selector,
|
|
146
|
+
account,
|
|
147
|
+
abi.encode(recipient, 100)
|
|
148
|
+
);
|
|
129
149
|
token.transfer(recipient, 100);
|
|
130
150
|
}
|
|
131
151
|
|
|
@@ -137,7 +157,13 @@ contract BypassPolicyTest is BaseProxyTest {
|
|
|
137
157
|
|
|
138
158
|
function test_mint_notInList_defaultReject_failure() public {
|
|
139
159
|
vm.startPrank(deployer, deployer);
|
|
140
|
-
|
|
160
|
+
_expectRejectedRevert(
|
|
161
|
+
address(0),
|
|
162
|
+
"no policy allowed the action and default is reject",
|
|
163
|
+
MockTokenUpgradeable.mint.selector,
|
|
164
|
+
deployer,
|
|
165
|
+
abi.encode(recipient, 100)
|
|
166
|
+
);
|
|
141
167
|
token.mint(recipient, 100);
|
|
142
168
|
}
|
|
143
169
|
|
|
@@ -145,15 +171,17 @@ contract BypassPolicyTest is BaseProxyTest {
|
|
|
145
171
|
vm.startPrank(deployer);
|
|
146
172
|
// misconfigure the bypassPolicy to check burn operations (no accounts)
|
|
147
173
|
ERC3643MintBurnExtractor mintBurnExtractor = new ERC3643MintBurnExtractor();
|
|
148
|
-
policyEngine.setExtractor(
|
|
149
|
-
policyEngine.addPolicy(address(token),
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
)
|
|
156
|
-
);
|
|
174
|
+
policyEngine.setExtractor(MockTokenUpgradeable.burn.selector, address(mintBurnExtractor));
|
|
175
|
+
policyEngine.addPolicy(address(token), MockTokenUpgradeable.burn.selector, address(bypassPolicy), new bytes32[](0));
|
|
176
|
+
|
|
177
|
+
IPolicyEngine.Payload memory payload = IPolicyEngine.Payload({
|
|
178
|
+
selector: MockTokenUpgradeable.burn.selector,
|
|
179
|
+
sender: deployer,
|
|
180
|
+
data: abi.encode(account, 100),
|
|
181
|
+
context: new bytes(0)
|
|
182
|
+
});
|
|
183
|
+
bytes memory error = abi.encodeWithSignature("InvalidParameters(string)", "expected at least 1 parameter");
|
|
184
|
+
_expectRunError(address(bypassPolicy), error, payload);
|
|
157
185
|
token.burn(account, 100);
|
|
158
186
|
}
|
|
159
187
|
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import {IPolicyEngine, PolicyEngine} from "@chainlink/policy-management/core/PolicyEngine.sol";
|
|
5
|
+
import {ICertifiedActionValidator} from "@chainlink/policy-management/interfaces/ICertifiedActionValidator.sol";
|
|
6
|
+
import {CertifiedActionValidatorPolicy} from "@chainlink/policy-management/policies/CertifiedActionValidatorPolicy.sol";
|
|
7
|
+
import {CertifiedActionDONValidatorPolicy} from
|
|
8
|
+
"@chainlink/policy-management/policies/CertifiedActionDONValidatorPolicy.sol";
|
|
9
|
+
import {MockTokenUpgradeable} from "../helpers/MockTokenUpgradeable.sol";
|
|
10
|
+
import {MockTokenExtractor} from "../helpers/MockTokenExtractor.sol";
|
|
11
|
+
import {BaseCertifiedActionTest} from "../helpers/BaseCertifiedActionTest.sol";
|
|
12
|
+
|
|
13
|
+
contract CertifiedActionDONValidatorPolicyTest is BaseCertifiedActionTest {
|
|
14
|
+
PolicyEngine public policyEngine;
|
|
15
|
+
MockTokenUpgradeable public token;
|
|
16
|
+
CertifiedActionDONValidatorPolicy public policy;
|
|
17
|
+
address public deployer;
|
|
18
|
+
address public recipient;
|
|
19
|
+
address public signer;
|
|
20
|
+
uint256 public signerKey;
|
|
21
|
+
address public mockKeystoneForwarder;
|
|
22
|
+
|
|
23
|
+
function setUp() public {
|
|
24
|
+
deployer = makeAddr("deployer");
|
|
25
|
+
recipient = makeAddr("recipient");
|
|
26
|
+
(signer, signerKey) = makeAddrAndKey("signer");
|
|
27
|
+
mockKeystoneForwarder = makeAddr("mockKeystoneForwarder");
|
|
28
|
+
|
|
29
|
+
vm.startPrank(deployer);
|
|
30
|
+
|
|
31
|
+
policyEngine = _deployPolicyEngine(true, deployer);
|
|
32
|
+
|
|
33
|
+
CertifiedActionDONValidatorPolicy policyImpl = new CertifiedActionDONValidatorPolicy();
|
|
34
|
+
policy = CertifiedActionDONValidatorPolicy(
|
|
35
|
+
_deployPolicy(address(policyImpl), address(policyEngine), deployer, abi.encode(mockKeystoneForwarder))
|
|
36
|
+
);
|
|
37
|
+
policy.allowIssuer(abi.encode(signer));
|
|
38
|
+
MockTokenExtractor extractor = new MockTokenExtractor();
|
|
39
|
+
bytes32[] memory parameterOutputFormat = new bytes32[](3);
|
|
40
|
+
parameterOutputFormat[0] = extractor.PARAM_FROM();
|
|
41
|
+
parameterOutputFormat[1] = extractor.PARAM_TO();
|
|
42
|
+
parameterOutputFormat[2] = extractor.PARAM_AMOUNT();
|
|
43
|
+
|
|
44
|
+
token = MockTokenUpgradeable(_deployMockToken(address(policyEngine)));
|
|
45
|
+
|
|
46
|
+
policyEngine.setExtractor(MockTokenUpgradeable.transfer.selector, address(extractor));
|
|
47
|
+
policyEngine.setExtractor(MockTokenUpgradeable.transferFrom.selector, address(extractor));
|
|
48
|
+
|
|
49
|
+
policyEngine.addPolicy(
|
|
50
|
+
address(token), MockTokenUpgradeable.transfer.selector, address(policy), parameterOutputFormat
|
|
51
|
+
);
|
|
52
|
+
policyEngine.addPolicy(
|
|
53
|
+
address(token), MockTokenUpgradeable.transferFrom.selector, address(policy), parameterOutputFormat
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function test_DONPreActionPermit_validPermit_succeeds() public {
|
|
58
|
+
vm.startPrank(mockKeystoneForwarder);
|
|
59
|
+
|
|
60
|
+
bytes[] memory params = new bytes[](3);
|
|
61
|
+
params[0] = abi.encode(deployer);
|
|
62
|
+
params[1] = abi.encode(recipient);
|
|
63
|
+
params[2] = abi.encode(uint256(100));
|
|
64
|
+
|
|
65
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
66
|
+
_generatePermit(deployer, address(token), MockTokenUpgradeable.transfer.selector, params);
|
|
67
|
+
|
|
68
|
+
policy.onReport(_ocrMetadata(), abi.encode(permit));
|
|
69
|
+
uint256 usage = policy.getUsage(permit.permitId);
|
|
70
|
+
|
|
71
|
+
vm.stopPrank();
|
|
72
|
+
vm.startPrank(deployer);
|
|
73
|
+
|
|
74
|
+
vm.assertEq(token.balanceOf(recipient), 0);
|
|
75
|
+
token.transfer(recipient, 100);
|
|
76
|
+
vm.assertEq(token.balanceOf(recipient), 100);
|
|
77
|
+
vm.assertEq(policy.getUsage(permit.permitId), usage + 1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function test_InvalidDONPreActionPermit_validPermit_succeeds() public {
|
|
81
|
+
address bogus = makeAddr("bogus");
|
|
82
|
+
vm.startPrank(bogus);
|
|
83
|
+
|
|
84
|
+
bytes[] memory params = new bytes[](3);
|
|
85
|
+
params[0] = abi.encode(deployer);
|
|
86
|
+
params[1] = abi.encode(recipient);
|
|
87
|
+
params[2] = abi.encode(uint256(100));
|
|
88
|
+
|
|
89
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
90
|
+
_generatePermit(deployer, address(token), MockTokenUpgradeable.transfer.selector, params);
|
|
91
|
+
|
|
92
|
+
vm.expectRevert(
|
|
93
|
+
abi.encodeWithSelector(CertifiedActionDONValidatorPolicy.UnauthorizedKeystoneForwarder.selector, bogus)
|
|
94
|
+
);
|
|
95
|
+
policy.onReport(_ocrMetadata(), abi.encode(permit));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function test_check_fromKeystoneForwarder_returnsTrue() public {
|
|
99
|
+
vm.startPrank(mockKeystoneForwarder);
|
|
100
|
+
|
|
101
|
+
bytes[] memory params = new bytes[](3);
|
|
102
|
+
params[0] = abi.encode(deployer);
|
|
103
|
+
params[1] = abi.encode(recipient);
|
|
104
|
+
params[2] = abi.encode(uint256(100));
|
|
105
|
+
|
|
106
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
107
|
+
_generatePermit(deployer, address(token), MockTokenUpgradeable.transfer.selector, params);
|
|
108
|
+
|
|
109
|
+
policy.onReport(_ocrMetadata(), abi.encode(permit));
|
|
110
|
+
|
|
111
|
+
vm.assertEq(policy.check(permit, abi.encode(signer)), true);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function test_check_invalidAddress_fromKeystoneForwarder_returnsFalse() public {
|
|
115
|
+
vm.startPrank(mockKeystoneForwarder);
|
|
116
|
+
|
|
117
|
+
bytes[] memory params = new bytes[](3);
|
|
118
|
+
params[0] = abi.encode(deployer);
|
|
119
|
+
params[1] = abi.encode(recipient);
|
|
120
|
+
params[2] = abi.encode(uint256(100));
|
|
121
|
+
|
|
122
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
123
|
+
_generatePermit(deployer, address(token), MockTokenUpgradeable.transfer.selector, params);
|
|
124
|
+
|
|
125
|
+
policy.onReport(_ocrMetadata(), abi.encode(permit));
|
|
126
|
+
|
|
127
|
+
vm.assertEq(policy.check(permit, abi.encode(makeAddr("randomAddress"))), false);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function test_contextualPermit_reverts() public {
|
|
131
|
+
vm.startPrank(deployer);
|
|
132
|
+
|
|
133
|
+
MockTokenExtractor extractor = new MockTokenExtractor();
|
|
134
|
+
bytes32[] memory parameterOutputFormat = new bytes32[](3);
|
|
135
|
+
parameterOutputFormat[0] = extractor.PARAM_FROM();
|
|
136
|
+
parameterOutputFormat[1] = extractor.PARAM_TO();
|
|
137
|
+
parameterOutputFormat[2] = extractor.PARAM_AMOUNT();
|
|
138
|
+
|
|
139
|
+
policyEngine.setExtractor(MockTokenUpgradeable.transferWithContext.selector, address(extractor));
|
|
140
|
+
policyEngine.addPolicy(
|
|
141
|
+
address(token), MockTokenUpgradeable.transferWithContext.selector, address(policy), parameterOutputFormat
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
bytes[] memory params = new bytes[](3);
|
|
145
|
+
params[0] = abi.encode(deployer);
|
|
146
|
+
params[1] = abi.encode(recipient);
|
|
147
|
+
params[2] = abi.encode(uint256(100));
|
|
148
|
+
|
|
149
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
150
|
+
_generatePermit(deployer, address(token), MockTokenUpgradeable.transferWithContext.selector, params);
|
|
151
|
+
|
|
152
|
+
bytes memory context = abi.encode(ICertifiedActionValidator.SignedPermit(permit, abi.encode(signer)));
|
|
153
|
+
_expectRejectedRevert(
|
|
154
|
+
address(policy),
|
|
155
|
+
"invalid signed permit in context",
|
|
156
|
+
MockTokenUpgradeable.transferWithContext.selector,
|
|
157
|
+
deployer,
|
|
158
|
+
abi.encode(recipient, 100, context),
|
|
159
|
+
context
|
|
160
|
+
);
|
|
161
|
+
token.transferWithContext(recipient, 100, context);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function _ocrMetadata() internal returns (bytes memory) {
|
|
165
|
+
return abi.encodePacked(
|
|
166
|
+
uint256(1234), // workflow_cid (32 bytes)
|
|
167
|
+
"AAAAAAAAAA", // workflow_name (10 bytes)
|
|
168
|
+
signer, // workflow_owner (20 bytes)
|
|
169
|
+
"BB" // report_name (2 bytes)
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
package/packages/policy-management/test/policies/CertifiedActionERC20TransferValidatorPolicy.t.sol
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import {IPolicyEngine, PolicyEngine} from "@chainlink/policy-management/core/PolicyEngine.sol";
|
|
5
|
+
import {ICertifiedActionValidator} from "@chainlink/policy-management/interfaces/ICertifiedActionValidator.sol";
|
|
6
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
7
|
+
import {Policy} from "@chainlink/policy-management/core/Policy.sol";
|
|
8
|
+
import {CertifiedActionValidatorPolicy} from "@chainlink/policy-management/policies/CertifiedActionValidatorPolicy.sol";
|
|
9
|
+
import {CertifiedActionERC20TransferValidatorPolicy} from
|
|
10
|
+
"@chainlink/policy-management/policies/CertifiedActionERC20TransferValidatorPolicy.sol";
|
|
11
|
+
import {MockTokenUpgradeable} from "../helpers/MockTokenUpgradeable.sol";
|
|
12
|
+
import {MockTokenExtractor} from "../helpers/MockTokenExtractor.sol";
|
|
13
|
+
import {BaseCertifiedActionTest} from "../helpers/BaseCertifiedActionTest.sol";
|
|
14
|
+
|
|
15
|
+
contract CertifiedActionERC20TransferValidatorPolicyTest is BaseCertifiedActionTest {
|
|
16
|
+
PolicyEngine public policyEngine;
|
|
17
|
+
MockTokenUpgradeable public token;
|
|
18
|
+
CertifiedActionValidatorPolicy public policy;
|
|
19
|
+
address public deployer;
|
|
20
|
+
address public recipient;
|
|
21
|
+
address public signer;
|
|
22
|
+
uint256 public signerKey;
|
|
23
|
+
|
|
24
|
+
function setUp() public {
|
|
25
|
+
deployer = makeAddr("deployer");
|
|
26
|
+
recipient = makeAddr("recipient");
|
|
27
|
+
(signer, signerKey) = makeAddrAndKey("signer");
|
|
28
|
+
|
|
29
|
+
vm.startPrank(deployer);
|
|
30
|
+
|
|
31
|
+
policyEngine = _deployPolicyEngine(true, deployer);
|
|
32
|
+
|
|
33
|
+
CertifiedActionERC20TransferValidatorPolicy policyImpl = new CertifiedActionERC20TransferValidatorPolicy();
|
|
34
|
+
policy = CertifiedActionERC20TransferValidatorPolicy(
|
|
35
|
+
_deployPolicy(address(policyImpl), address(policyEngine), deployer, "")
|
|
36
|
+
);
|
|
37
|
+
policy.allowIssuer(abi.encode(signer));
|
|
38
|
+
MockTokenExtractor extractor = new MockTokenExtractor();
|
|
39
|
+
bytes32[] memory parameterOutputFormat = new bytes32[](3);
|
|
40
|
+
parameterOutputFormat[0] = extractor.PARAM_FROM();
|
|
41
|
+
parameterOutputFormat[1] = extractor.PARAM_TO();
|
|
42
|
+
parameterOutputFormat[2] = extractor.PARAM_AMOUNT();
|
|
43
|
+
|
|
44
|
+
token = MockTokenUpgradeable(_deployMockToken(address(policyEngine)));
|
|
45
|
+
|
|
46
|
+
policyEngine.setExtractor(MockTokenUpgradeable.transfer.selector, address(extractor));
|
|
47
|
+
policyEngine.setExtractor(MockTokenUpgradeable.transferWithContext.selector, address(extractor));
|
|
48
|
+
policyEngine.setExtractor(MockTokenUpgradeable.transferFrom.selector, address(extractor));
|
|
49
|
+
|
|
50
|
+
policyEngine.addPolicy(
|
|
51
|
+
address(token), MockTokenUpgradeable.transfer.selector, address(policy), parameterOutputFormat
|
|
52
|
+
);
|
|
53
|
+
policyEngine.addPolicy(
|
|
54
|
+
address(token), MockTokenUpgradeable.transferWithContext.selector, address(policy), parameterOutputFormat
|
|
55
|
+
);
|
|
56
|
+
policyEngine.addPolicy(
|
|
57
|
+
address(token), MockTokenUpgradeable.transferFrom.selector, address(policy), parameterOutputFormat
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function test_preActionPermit_validPermitExact_succeeds() public {
|
|
62
|
+
vm.startPrank(deployer);
|
|
63
|
+
|
|
64
|
+
bytes[] memory params = new bytes[](3);
|
|
65
|
+
params[0] = abi.encode(deployer);
|
|
66
|
+
params[1] = abi.encode(recipient);
|
|
67
|
+
params[2] = abi.encode(uint256(100));
|
|
68
|
+
|
|
69
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
70
|
+
_generatePermit(deployer, address(token), IERC20.transfer.selector, params);
|
|
71
|
+
|
|
72
|
+
bytes memory signature = _signPermit(policy, permit, signerKey);
|
|
73
|
+
|
|
74
|
+
policy.present(permit, signature);
|
|
75
|
+
uint256 usage = policy.getUsage(permit.permitId);
|
|
76
|
+
|
|
77
|
+
vm.assertEq(token.balanceOf(recipient), 0);
|
|
78
|
+
token.transfer(recipient, 100);
|
|
79
|
+
vm.assertEq(token.balanceOf(recipient), 100);
|
|
80
|
+
vm.assertEq(policy.getUsage(permit.permitId), usage + 1);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function test_preActionPermit_validPermitUnderMax_succeeds() public {
|
|
84
|
+
vm.startPrank(deployer);
|
|
85
|
+
|
|
86
|
+
bytes[] memory params = new bytes[](3);
|
|
87
|
+
params[0] = abi.encode(deployer);
|
|
88
|
+
params[1] = abi.encode(recipient);
|
|
89
|
+
params[2] = abi.encode(uint256(100));
|
|
90
|
+
|
|
91
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
92
|
+
_generatePermit(deployer, address(token), IERC20.transfer.selector, params);
|
|
93
|
+
|
|
94
|
+
bytes memory signature = _signPermit(policy, permit, signerKey);
|
|
95
|
+
|
|
96
|
+
policy.present(permit, signature);
|
|
97
|
+
uint256 usage = policy.getUsage(permit.permitId);
|
|
98
|
+
|
|
99
|
+
vm.assertEq(token.balanceOf(recipient), 0);
|
|
100
|
+
token.transfer(recipient, 99);
|
|
101
|
+
vm.assertEq(token.balanceOf(recipient), 99);
|
|
102
|
+
vm.assertEq(policy.getUsage(permit.permitId), usage + 1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function test_preActionPermit_validPermitOverMaxAmount_reverts() public {
|
|
106
|
+
vm.startPrank(deployer);
|
|
107
|
+
|
|
108
|
+
bytes[] memory params = new bytes[](3);
|
|
109
|
+
params[0] = abi.encode(deployer);
|
|
110
|
+
params[1] = abi.encode(recipient);
|
|
111
|
+
params[2] = abi.encode(uint256(100));
|
|
112
|
+
|
|
113
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
114
|
+
_generatePermit(deployer, address(token), IERC20.transfer.selector, params);
|
|
115
|
+
|
|
116
|
+
bytes memory signature = _signPermit(policy, permit, signerKey);
|
|
117
|
+
|
|
118
|
+
policy.present(permit, signature);
|
|
119
|
+
|
|
120
|
+
_expectRejectedRevert(
|
|
121
|
+
address(policy),
|
|
122
|
+
"no valid pre-presented permit found",
|
|
123
|
+
MockTokenUpgradeable.transfer.selector,
|
|
124
|
+
deployer,
|
|
125
|
+
abi.encode(recipient, 101)
|
|
126
|
+
);
|
|
127
|
+
token.transfer(recipient, 101);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function test_preActionPermit_invalidSelector_reverts() public {
|
|
131
|
+
vm.startPrank(deployer);
|
|
132
|
+
|
|
133
|
+
bytes[] memory params = new bytes[](3);
|
|
134
|
+
params[0] = abi.encode(deployer);
|
|
135
|
+
params[1] = abi.encode(recipient);
|
|
136
|
+
params[2] = abi.encode(uint256(100));
|
|
137
|
+
|
|
138
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
139
|
+
_generatePermit(deployer, address(token), IERC20.approve.selector, params);
|
|
140
|
+
|
|
141
|
+
bytes memory signature = _signPermit(policy, permit, signerKey);
|
|
142
|
+
|
|
143
|
+
vm.expectRevert(abi.encodeWithSelector(Policy.InvalidParameters.selector, "unsupported selector"));
|
|
144
|
+
policy.present(permit, signature);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function test_no_permit_reverts() public {
|
|
148
|
+
vm.startPrank(deployer);
|
|
149
|
+
|
|
150
|
+
_expectRejectedRevert(
|
|
151
|
+
address(policy),
|
|
152
|
+
"no valid permit found",
|
|
153
|
+
MockTokenUpgradeable.transfer.selector,
|
|
154
|
+
deployer,
|
|
155
|
+
abi.encode(recipient, 100)
|
|
156
|
+
);
|
|
157
|
+
token.transfer(recipient, 100);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function test_check_validPermit_returnsTrue() public {
|
|
161
|
+
vm.startPrank(deployer);
|
|
162
|
+
|
|
163
|
+
bytes[] memory params = new bytes[](3);
|
|
164
|
+
params[0] = abi.encode(deployer);
|
|
165
|
+
params[1] = abi.encode(recipient);
|
|
166
|
+
params[2] = abi.encode(uint256(100));
|
|
167
|
+
|
|
168
|
+
// permit for transfer
|
|
169
|
+
ICertifiedActionValidator.Permit memory permit1 =
|
|
170
|
+
_generatePermit(deployer, address(token), IERC20.transfer.selector, params);
|
|
171
|
+
|
|
172
|
+
bytes memory signature1 = _signPermit(policy, permit1, signerKey);
|
|
173
|
+
|
|
174
|
+
policy.present(permit1, signature1);
|
|
175
|
+
vm.assertEq(policy.check(permit1, signature1), true);
|
|
176
|
+
|
|
177
|
+
// permit for transferFrom
|
|
178
|
+
ICertifiedActionValidator.Permit memory permit2 =
|
|
179
|
+
_generatePermit(deployer, address(token), IERC20.transferFrom.selector, params);
|
|
180
|
+
|
|
181
|
+
bytes memory signature2 = _signPermit(policy, permit2, signerKey);
|
|
182
|
+
|
|
183
|
+
policy.present(permit2, signature2);
|
|
184
|
+
vm.assertEq(policy.check(permit2, signature2), true);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function test_check_invalidSelector_returnsFalse() public {
|
|
188
|
+
vm.startPrank(deployer);
|
|
189
|
+
|
|
190
|
+
bytes[] memory params = new bytes[](3);
|
|
191
|
+
params[0] = abi.encode(deployer);
|
|
192
|
+
params[1] = abi.encode(recipient);
|
|
193
|
+
params[2] = abi.encode(uint256(100));
|
|
194
|
+
|
|
195
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
196
|
+
_generatePermit(deployer, address(token), IERC20.approve.selector, params);
|
|
197
|
+
|
|
198
|
+
bytes memory signature = _signPermit(policy, permit, signerKey);
|
|
199
|
+
|
|
200
|
+
vm.assertEq(policy.check(permit, signature), false);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function test_check_invalidParameters_returnsFalse() public {
|
|
204
|
+
vm.startPrank(deployer);
|
|
205
|
+
|
|
206
|
+
bytes[] memory params = new bytes[](2); // missing amount parameter
|
|
207
|
+
params[0] = abi.encode(deployer);
|
|
208
|
+
params[1] = abi.encode(recipient);
|
|
209
|
+
|
|
210
|
+
ICertifiedActionValidator.Permit memory permit =
|
|
211
|
+
_generatePermit(deployer, address(token), IERC20.transfer.selector, params);
|
|
212
|
+
|
|
213
|
+
bytes memory signature = _signPermit(policy, permit, signerKey);
|
|
214
|
+
|
|
215
|
+
vm.assertEq(policy.check(permit, signature), false);
|
|
216
|
+
}
|
|
217
|
+
}
|