@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.
- package/.foundry-version +1 -0
- package/.github/CODEOWNERS +1 -0
- package/.github/workflows/auto-release-version.yml +107 -0
- package/.github/workflows/create-version-pr.yml +95 -0
- package/.github/workflows/forge-docs.yml +90 -0
- package/.github/workflows/forge-test.yml +59 -0
- package/.solhint-test.json +18 -0
- package/.solhint.json +16 -0
- package/.solhintignore +3 -0
- package/.solhintignore-test +2 -0
- package/Glossary.md +141 -0
- package/LICENSE +59 -0
- package/README.md +218 -0
- package/assets/chainlink-logo.svg +21 -0
- package/chainlink-ace-License-grants +2 -0
- package/foundry.toml +33 -0
- package/getting_started/GETTING_STARTED.md +477 -0
- package/getting_started/MyVault.sol +48 -0
- package/getting_started/advanced/.env.example +36 -0
- package/getting_started/advanced/GETTING_STARTED_ADVANCED.md +431 -0
- package/getting_started/advanced/SanctionsList.sol +25 -0
- package/getting_started/advanced/SanctionsPolicy.sol +58 -0
- package/package.json +41 -0
- package/packages/cross-chain-identity/README.md +148 -0
- package/packages/cross-chain-identity/docs/API_GUIDE.md +120 -0
- package/packages/cross-chain-identity/docs/API_REFERENCE.md +271 -0
- package/packages/cross-chain-identity/docs/CONCEPTS.md +253 -0
- package/packages/cross-chain-identity/docs/CREDENTIAL_FLOW.md +195 -0
- package/packages/cross-chain-identity/docs/SECURITY.md +70 -0
- package/packages/cross-chain-identity/src/CredentialRegistry.sol +245 -0
- package/packages/cross-chain-identity/src/CredentialRegistryIdentityValidator.sol +339 -0
- package/packages/cross-chain-identity/src/CredentialRegistryIdentityValidatorPolicy.sol +71 -0
- package/packages/cross-chain-identity/src/IdentityRegistry.sol +123 -0
- package/packages/cross-chain-identity/src/TrustedIssuerRegistry.sol +140 -0
- package/packages/cross-chain-identity/src/interfaces/ICredentialDataValidator.sol +30 -0
- package/packages/cross-chain-identity/src/interfaces/ICredentialRegistry.sol +170 -0
- package/packages/cross-chain-identity/src/interfaces/ICredentialRequirements.sol +192 -0
- package/packages/cross-chain-identity/src/interfaces/ICredentialValidator.sol +37 -0
- package/packages/cross-chain-identity/src/interfaces/IIdentityRegistry.sol +85 -0
- package/packages/cross-chain-identity/src/interfaces/IIdentityValidator.sol +18 -0
- package/packages/cross-chain-identity/src/interfaces/ITrustedIssuerRegistry.sol +61 -0
- package/packages/cross-chain-identity/test/CredentialRegistry.t.sol +220 -0
- package/packages/cross-chain-identity/test/CredentialRegistryIdentityValidator.t.sol +554 -0
- package/packages/cross-chain-identity/test/CredentialRegistryIdentityValidatorPolicy.t.sol +114 -0
- package/packages/cross-chain-identity/test/IdentityRegistry.t.sol +106 -0
- package/packages/cross-chain-identity/test/IdentityValidator.t.sol +969 -0
- package/packages/cross-chain-identity/test/TrustedIssuerRegistry.t.sol +123 -0
- package/packages/cross-chain-identity/test/helpers/BaseProxyTest.sol +112 -0
- package/packages/cross-chain-identity/test/helpers/MockCredentialDataValidator.sol +26 -0
- package/packages/cross-chain-identity/test/helpers/MockCredentialRegistryReverting.sol +131 -0
- package/packages/policy-management/README.md +197 -0
- package/packages/policy-management/docs/API_GUIDE.md +290 -0
- package/packages/policy-management/docs/API_REFERENCE.md +173 -0
- package/packages/policy-management/docs/CONCEPTS.md +156 -0
- package/packages/policy-management/docs/CUSTOM_POLICIES_TUTORIAL.md +195 -0
- package/packages/policy-management/docs/POLICY_ORDERING_GUIDE.md +91 -0
- package/packages/policy-management/docs/SECURITY.md +57 -0
- package/packages/policy-management/src/core/Policy.sol +124 -0
- package/packages/policy-management/src/core/PolicyEngine.sol +382 -0
- package/packages/policy-management/src/core/PolicyFactory.sol +92 -0
- package/packages/policy-management/src/core/PolicyProtected.sol +126 -0
- package/packages/policy-management/src/extractors/ComplianceTokenForceTransferExtractor.sol +57 -0
- package/packages/policy-management/src/extractors/ComplianceTokenFreezeUnfreezeExtractor.sol +54 -0
- package/packages/policy-management/src/extractors/ComplianceTokenMintBurnExtractor.sol +61 -0
- package/packages/policy-management/src/extractors/ERC20ApproveExtractor.sol +57 -0
- package/packages/policy-management/src/extractors/ERC20TransferExtractor.sol +62 -0
- package/packages/policy-management/src/extractors/ERC3643ForcedTransferExtractor.sol +56 -0
- package/packages/policy-management/src/extractors/ERC3643FreezeUnfreezeExtractor.sol +55 -0
- package/packages/policy-management/src/extractors/ERC3643MintBurnExtractor.sol +51 -0
- package/packages/policy-management/src/extractors/ERC3643SetAddressFrozenExtractor.sol +51 -0
- package/packages/policy-management/src/interfaces/IExtractor.sol +17 -0
- package/packages/policy-management/src/interfaces/IMapper.sol +17 -0
- package/packages/policy-management/src/interfaces/IPolicy.sol +61 -0
- package/packages/policy-management/src/interfaces/IPolicyEngine.sol +264 -0
- package/packages/policy-management/src/interfaces/IPolicyProtected.sol +48 -0
- package/packages/policy-management/src/policies/AllowPolicy.sol +104 -0
- package/packages/policy-management/src/policies/BypassPolicy.sol +90 -0
- package/packages/policy-management/src/policies/IntervalPolicy.sol +223 -0
- package/packages/policy-management/src/policies/MaxPolicy.sol +73 -0
- package/packages/policy-management/src/policies/OnlyAuthorizedSenderPolicy.sol +84 -0
- package/packages/policy-management/src/policies/OnlyOwnerPolicy.sol +35 -0
- package/packages/policy-management/src/policies/PausePolicy.sol +82 -0
- package/packages/policy-management/src/policies/README.md +632 -0
- package/packages/policy-management/src/policies/RejectPolicy.sol +89 -0
- package/packages/policy-management/src/policies/RoleBasedAccessControlPolicy.sol +162 -0
- package/packages/policy-management/src/policies/SecureMintPolicy.sol +271 -0
- package/packages/policy-management/src/policies/VolumePolicy.sol +133 -0
- package/packages/policy-management/src/policies/VolumeRatePolicy.sol +192 -0
- package/packages/policy-management/test/PolicyEngine.t.sol +368 -0
- package/packages/policy-management/test/PolicyFactory.t.sol +114 -0
- package/packages/policy-management/test/PolicyProtectedToken.t.sol +75 -0
- package/packages/policy-management/test/extractors/ComplianceTokenForceTransferExtractor.t.sol +59 -0
- package/packages/policy-management/test/extractors/ComplianceTokenFreezeUnfreezeExtractor.t.sol +74 -0
- package/packages/policy-management/test/extractors/ComplianceTokenMintBurnExtractor.t.sol +92 -0
- package/packages/policy-management/test/extractors/ERC20ApproveExtractor.t.sol +58 -0
- package/packages/policy-management/test/extractors/ERC3643ForcedTransferExtractor.t.sol +59 -0
- package/packages/policy-management/test/extractors/ERC3643FreezeUnfreezeExtractor.t.sol +74 -0
- package/packages/policy-management/test/extractors/ERC3643MintBurnExtractor.t.sol +73 -0
- package/packages/policy-management/test/extractors/ERC3643SetAddressFrozenExtractor.t.sol +56 -0
- package/packages/policy-management/test/helpers/BaseProxyTest.sol +75 -0
- package/packages/policy-management/test/helpers/CustomMapper.sol +26 -0
- package/packages/policy-management/test/helpers/DummyExtractor.sol +11 -0
- package/packages/policy-management/test/helpers/ExpectedParameterPolicy.sol +39 -0
- package/packages/policy-management/test/helpers/MockAggregatorV3.sol +51 -0
- package/packages/policy-management/test/helpers/MockToken.sol +66 -0
- package/packages/policy-management/test/helpers/MockTokenExtractor.sol +34 -0
- package/packages/policy-management/test/helpers/PolicyAlwaysAllowed.sol +45 -0
- package/packages/policy-management/test/helpers/PolicyAlwaysContinue.sol +23 -0
- package/packages/policy-management/test/helpers/PolicyAlwaysRejected.sol +23 -0
- package/packages/policy-management/test/helpers/PolicyFailingRun.sol +22 -0
- package/packages/policy-management/test/policies/AllowPolicy.t.sol +174 -0
- package/packages/policy-management/test/policies/BypassPolicy.t.sol +159 -0
- package/packages/policy-management/test/policies/IntervalPolicy.t.sol +307 -0
- package/packages/policy-management/test/policies/MaxPolicy.t.sol +54 -0
- package/packages/policy-management/test/policies/OnlyAuthorizedSenderPolicy.t.sol +95 -0
- package/packages/policy-management/test/policies/OnlyOwnerPolicy.t.sol +47 -0
- package/packages/policy-management/test/policies/PausePolicy.t.sol +75 -0
- package/packages/policy-management/test/policies/RejectPolicy.t.sol +182 -0
- package/packages/policy-management/test/policies/RoleBasedAccessControlPolicy.t.sol +223 -0
- package/packages/policy-management/test/policies/SecureMintPolicy.t.sol +442 -0
- package/packages/policy-management/test/policies/VolumePolicy.t.sol +158 -0
- package/packages/policy-management/test/policies/VolumeRatePolicy.t.sol +165 -0
- package/packages/tokens/erc-20/src/ComplianceTokenERC20.sol +345 -0
- package/packages/tokens/erc-20/src/ComplianceTokenStoreERC20.sol +29 -0
- package/packages/tokens/erc-20/test/ComplianceTokenERC20.t.sol +556 -0
- package/packages/tokens/erc-20/test/helpers/BaseProxyTest.sol +75 -0
- package/packages/tokens/erc-3643/README.md +24 -0
- package/packages/tokens/erc-3643/src/ComplianceTokenERC3643.sol +564 -0
- package/packages/tokens/erc-3643/src/ComplianceTokenStoreERC3643.sol +30 -0
- package/packages/tokens/erc-3643/test/ComplianceTokenERC3643.t.sol +815 -0
- package/packages/tokens/erc-3643/test/helpers/BaseProxyTest.sol +76 -0
- package/packages/tokens/erc-3643/test/helpers/ExpectedContextPolicy.sol +32 -0
- package/packages/vendor/erc-3643/compliance/modular/IModularCompliance.sol +220 -0
- package/packages/vendor/erc-3643/registry/interface/IClaimTopicsRegistry.sol +101 -0
- package/packages/vendor/erc-3643/registry/interface/IIdentityRegistry.sol +251 -0
- package/packages/vendor/erc-3643/registry/interface/IIdentityRegistryStorage.sol +191 -0
- package/packages/vendor/erc-3643/registry/interface/ITrustedIssuersRegistry.sol +161 -0
- package/packages/vendor/erc-3643/token/IToken.sol +457 -0
- package/packages/vendor/onchain-id/interface/IClaimIssuer.sol +53 -0
- package/packages/vendor/onchain-id/interface/IERC734.sol +110 -0
- package/packages/vendor/onchain-id/interface/IERC735.sol +105 -0
- package/packages/vendor/onchain-id/interface/IIdentity.sol +26 -0
- package/packages/vendor/onchain-id/interface/IImplementationAuthority.sol +21 -0
- package/remappings.txt +6 -0
- package/script/DeployComplianceTokenERC20.s.sol +191 -0
- package/script/DeployComplianceTokenERC3643.s.sol +208 -0
- package/script/DeploySimpleComplianceToken.s.sol +38 -0
- package/script/getting_started/DeployGettingStarted.s.sol +74 -0
- package/script/getting_started/advanced/DeployAdvancedGettingStarted.s.sol +332 -0
- package/script/getting_started/advanced/DeploySanctionsList.s.sol +26 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity 0.8.26;
|
|
3
|
+
|
|
4
|
+
import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
|
|
5
|
+
import {Policy} from "@chainlink/policy-management/core/Policy.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title IntervalPolicy
|
|
9
|
+
* @notice A policy that enforces execution within specific time intervals, based on configurable time slots.
|
|
10
|
+
* @dev Implements Chainlink's `Policy` interface and OpenZeppelin's `Ownable` for access control.
|
|
11
|
+
* The policy checks whether the current time slot falls within a configured start slot and end slot
|
|
12
|
+
* in a repeating cycle.
|
|
13
|
+
*
|
|
14
|
+
* ## Core Parameters
|
|
15
|
+
*
|
|
16
|
+
* - `s_slotDuration`: The duration (in seconds) of each individual slot. For instance, 3600 for a 1-hour slot.
|
|
17
|
+
* - `s_cycleSize`: The total number of slots in each repeating cycle (e.g., 24 slots for a daily cycle).
|
|
18
|
+
* - `s_cycleOffset`: An offset (in “slots”) added to the cycle when computing the current slot.
|
|
19
|
+
* - `s_startSlot`: The lowest (inclusive) slot index within the cycle for which execution is allowed.
|
|
20
|
+
* - `s_endSlot`: The highest (exclusive) slot index within the cycle for which execution is allowed.
|
|
21
|
+
*
|
|
22
|
+
* Each cycle is effectively indexed from `0` to `s_cycleSize - 1`. The policy “resets” back to slot 0
|
|
23
|
+
* after `s_cycleSize` slots, repeating indefinitely.
|
|
24
|
+
*
|
|
25
|
+
* ## Example Usages
|
|
26
|
+
*
|
|
27
|
+
* ### 1. Hour-Based Execution (Daily Cycle)
|
|
28
|
+
* ```
|
|
29
|
+
* IntervalPolicy(11, 17, 3600, 24, 0)
|
|
30
|
+
* ```
|
|
31
|
+
* - `s_cycleSize = 24`, corresponding to the 24 hours in a day.
|
|
32
|
+
* - Execution is allowed from slot `11` (which corresponds to ~ 11:00 UTC) to slot `17` (~17:00 UTC).
|
|
33
|
+
*
|
|
34
|
+
* ### 2. Day-Based Execution (Weekly Cycle)
|
|
35
|
+
* ```
|
|
36
|
+
* IntervalPolicy(1, 6, 86400, 7, 4)
|
|
37
|
+
* ```
|
|
38
|
+
* - `s_cycleSize = 7`, a weekly cycle (one slot per day).
|
|
39
|
+
* - Execution is allowed from slot `1` (Monday) to slot `6` (Saturday),
|
|
40
|
+
* with a 4-slot offset, effectively shifting the cycle start.
|
|
41
|
+
*/
|
|
42
|
+
contract IntervalPolicy is Policy {
|
|
43
|
+
/**
|
|
44
|
+
* @notice Emitted when the start slot is updated.
|
|
45
|
+
* @param startSlot The new start slot (inclusive).
|
|
46
|
+
*/
|
|
47
|
+
event StartSlotSet(uint256 startSlot);
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @notice Emitted when the end slot is updated.
|
|
51
|
+
* @param endSlot The new end slot (exclusive).
|
|
52
|
+
*/
|
|
53
|
+
event EndSlotSet(uint256 endSlot);
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @notice Emitted when cycle parameters are updated.
|
|
57
|
+
* @param slotDuration The duration (in seconds) of each slot.
|
|
58
|
+
* @param cycleSize The total number of slots in each repeating cycle.
|
|
59
|
+
* @param cycleOffset The offset (in slots) applied when computing the current slot index.
|
|
60
|
+
*/
|
|
61
|
+
event CycleParametersSet(uint256 slotDuration, uint256 cycleSize, uint256 cycleOffset);
|
|
62
|
+
|
|
63
|
+
/// @custom:storage-location erc7201:policy-management.IntervalPolicy
|
|
64
|
+
struct IntervalPolicyStorage {
|
|
65
|
+
/// @notice Duration (in seconds) of each slot (e.g., 3600 for 1 hour, 86400 for 1 day).
|
|
66
|
+
uint256 slotDuration;
|
|
67
|
+
/// @notice Total count of slots in each repeating cycle (e.g., 24 for daily hours, 7 for days in a week).
|
|
68
|
+
uint256 cycleSize;
|
|
69
|
+
/// @notice An offset (in slots) added to the computed slot index before taking modulo `s_cycleSize`.
|
|
70
|
+
uint256 cycleOffset;
|
|
71
|
+
/// @notice Starting slot index (inclusive) within the cycle where execution is allowed.
|
|
72
|
+
uint256 startSlot;
|
|
73
|
+
/// @notice Ending slot index (exclusive) within the cycle where execution is allowed.
|
|
74
|
+
uint256 endSlot;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// keccak256(abi.encode(uint256(keccak256("policy-management.IntervalPolicy")) - 1)) & ~bytes32(uint256(0xff))
|
|
78
|
+
bytes32 private constant IntervalPolicyStorageLocation =
|
|
79
|
+
0x240ccc3ae077efd7406ec291c47a6b567b6d85c851c6ee4f4a2a0a955805cd00;
|
|
80
|
+
|
|
81
|
+
function _getIntervalPolicyStorage() private pure returns (IntervalPolicyStorage storage $) {
|
|
82
|
+
assembly {
|
|
83
|
+
$.slot := IntervalPolicyStorageLocation
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @notice Configures the policy with the specified parameters.
|
|
89
|
+
* @dev The `parameters` input must be the ABI encoding of the following:
|
|
90
|
+
* - startSlot (uint256)
|
|
91
|
+
* - endSlot (uint256)
|
|
92
|
+
* - slotDuration (uint256)
|
|
93
|
+
* - cycleSize (uint256)
|
|
94
|
+
* - cycleOffset (uint256)
|
|
95
|
+
*
|
|
96
|
+
* @param parameters ABI-encoded bytes containing the configuration parameters.
|
|
97
|
+
*/
|
|
98
|
+
function configure(bytes calldata parameters) internal override onlyInitializing {
|
|
99
|
+
IntervalPolicyStorage storage $ = _getIntervalPolicyStorage();
|
|
100
|
+
($.startSlot, $.endSlot, $.slotDuration, $.cycleSize, $.cycleOffset) =
|
|
101
|
+
abi.decode(parameters, (uint256, uint256, uint256, uint256, uint256));
|
|
102
|
+
|
|
103
|
+
require($.startSlot < $.endSlot, "End slot must be greater than start slot");
|
|
104
|
+
require($.cycleSize > 0, "Cycle size must be > 0");
|
|
105
|
+
require($.endSlot <= $.cycleSize, "Cycle size must be >= end slot");
|
|
106
|
+
require($.slotDuration > 0, "Slot duration must be > 0");
|
|
107
|
+
require($.cycleOffset < $.cycleSize, "Cycle offset must be < cycle size");
|
|
108
|
+
|
|
109
|
+
emit StartSlotSet($.startSlot);
|
|
110
|
+
emit EndSlotSet($.endSlot);
|
|
111
|
+
emit CycleParametersSet($.slotDuration, $.cycleSize, $.cycleOffset);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* @notice Updates the start slot within the cycle.
|
|
116
|
+
* @dev Must be less than the current end slot. Only callable by the owner.
|
|
117
|
+
* @param _startSlot The new start slot (inclusive).
|
|
118
|
+
*/
|
|
119
|
+
function setStartSlot(uint256 _startSlot) public onlyOwner {
|
|
120
|
+
IntervalPolicyStorage storage $ = _getIntervalPolicyStorage();
|
|
121
|
+
require(_startSlot < $.endSlot, "New start slot must be < end slot");
|
|
122
|
+
$.startSlot = _startSlot;
|
|
123
|
+
emit StartSlotSet(_startSlot);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @notice Updates the end slot within the cycle.
|
|
128
|
+
* @dev Must be greater than the current start slot and less than the cycle size. Only callable by the owner.
|
|
129
|
+
* @param _endSlot The new end slot (exclusive).
|
|
130
|
+
*/
|
|
131
|
+
function setEndSlot(uint256 _endSlot) public onlyOwner {
|
|
132
|
+
IntervalPolicyStorage storage $ = _getIntervalPolicyStorage();
|
|
133
|
+
require(_endSlot > $.startSlot, "End slot must be greater than start slot");
|
|
134
|
+
require(_endSlot <= $.cycleSize, "End slot must be <= cycle size");
|
|
135
|
+
$.endSlot = _endSlot;
|
|
136
|
+
emit EndSlotSet(_endSlot);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @notice Updates the slot duration, cycle size, and cycle offset parameters.
|
|
141
|
+
* @dev Ensures the current `s_endSlot` remains valid under the new cycle size. Only callable by owner.
|
|
142
|
+
* @param _slotDuration The duration of each slot in seconds. Must be > 0.
|
|
143
|
+
* @param _cycleSize The total number of slots in each cycle. Must be > current `s_endSlot`.
|
|
144
|
+
* @param _cycleOffset The offset (in slots) applied to the computed time slot. Must be < `_cycleSize`.
|
|
145
|
+
*/
|
|
146
|
+
function setCycleParameters(uint256 _slotDuration, uint256 _cycleSize, uint256 _cycleOffset) public onlyOwner {
|
|
147
|
+
IntervalPolicyStorage storage $ = _getIntervalPolicyStorage();
|
|
148
|
+
require(_slotDuration > 0, "Slot duration must be > 0");
|
|
149
|
+
require(_cycleSize >= $.endSlot, "New cycle size must be >= end slot");
|
|
150
|
+
require(_cycleOffset < _cycleSize, "Cycle offset must be < cycle size");
|
|
151
|
+
|
|
152
|
+
$.slotDuration = _slotDuration;
|
|
153
|
+
$.cycleSize = _cycleSize;
|
|
154
|
+
$.cycleOffset = _cycleOffset;
|
|
155
|
+
emit CycleParametersSet(_slotDuration, _cycleSize, _cycleOffset);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* @notice Retrieves the current start slot within the cycle.
|
|
160
|
+
* @return The start slot index (inclusive).
|
|
161
|
+
*/
|
|
162
|
+
function getStartSlot() public view returns (uint256) {
|
|
163
|
+
IntervalPolicyStorage storage $ = _getIntervalPolicyStorage();
|
|
164
|
+
return $.startSlot;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @notice Retrieves the current end slot within the cycle.
|
|
169
|
+
* @return The end slot index (exclusive).
|
|
170
|
+
*/
|
|
171
|
+
function getEndSlot() public view returns (uint256) {
|
|
172
|
+
IntervalPolicyStorage storage $ = _getIntervalPolicyStorage();
|
|
173
|
+
return $.endSlot;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* @notice Retrieves the cycle parameters.
|
|
178
|
+
* @return slotDuration The duration (in seconds) of each slot.
|
|
179
|
+
* @return cycleSize The total number of slots in each repeating cycle.
|
|
180
|
+
* @return cycleOffset The offset (in slots) applied when computing the current slot index.
|
|
181
|
+
*/
|
|
182
|
+
function getCycleParameters() public view returns (uint256 slotDuration, uint256 cycleSize, uint256 cycleOffset) {
|
|
183
|
+
IntervalPolicyStorage storage $ = _getIntervalPolicyStorage();
|
|
184
|
+
return ($.slotDuration, $.cycleSize, $.cycleOffset);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* @notice Determines whether execution is allowed based on the current slot and configured start/end slots.
|
|
189
|
+
* @param caller The account attempting to run the policy (unused).
|
|
190
|
+
* @param subject The protected contract of the policy call (unused).
|
|
191
|
+
* @param parameters Additional parameters (unused).
|
|
192
|
+
* @param context Additional context (unused).
|
|
193
|
+
*
|
|
194
|
+
* @return A PolicyResult enum indicating `Continue` if the current slot is within [startSlot, endSlot),
|
|
195
|
+
* or `Rejected` otherwise.
|
|
196
|
+
*/
|
|
197
|
+
function run(
|
|
198
|
+
address caller,
|
|
199
|
+
address subject,
|
|
200
|
+
bytes4, /*selector*/
|
|
201
|
+
bytes[] calldata parameters,
|
|
202
|
+
bytes calldata context
|
|
203
|
+
)
|
|
204
|
+
public
|
|
205
|
+
view
|
|
206
|
+
override
|
|
207
|
+
returns (IPolicyEngine.PolicyResult)
|
|
208
|
+
{
|
|
209
|
+
// Unused in this specific policy
|
|
210
|
+
caller;
|
|
211
|
+
subject;
|
|
212
|
+
parameters;
|
|
213
|
+
context;
|
|
214
|
+
|
|
215
|
+
// Gas optimization: load storage reference once
|
|
216
|
+
IntervalPolicyStorage storage $ = _getIntervalPolicyStorage();
|
|
217
|
+
uint256 currentSlot = ((block.timestamp / $.slotDuration) + $.cycleOffset) % $.cycleSize;
|
|
218
|
+
if (currentSlot >= $.startSlot && currentSlot < $.endSlot) {
|
|
219
|
+
return IPolicyEngine.PolicyResult.Continue;
|
|
220
|
+
}
|
|
221
|
+
revert IPolicyEngine.PolicyRejected("execution outside allowed time interval");
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity 0.8.26;
|
|
3
|
+
|
|
4
|
+
import {IPolicyEngine} from "../interfaces/IPolicyEngine.sol";
|
|
5
|
+
import {Policy} from "../core/Policy.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title MaxPolicy
|
|
9
|
+
* @notice A policy that rejects requests if the maximum amount is exceeded (amount does not accumulate between calls).
|
|
10
|
+
*/
|
|
11
|
+
contract MaxPolicy is Policy {
|
|
12
|
+
/// @custom:storage-location erc7201:policy-management.MaxPolicy
|
|
13
|
+
struct MaxPolicyStorage {
|
|
14
|
+
uint256 max;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// keccak256(abi.encode(uint256(keccak256("policy-management.MaxPolicy")) - 1)) & ~bytes32(uint256(0xff))
|
|
18
|
+
bytes32 private constant MaxPolicyStorageLocation = 0x0c09e934710ad0d4b287c3ebc989bdabd3ce7d8fae49ce825c7ca38c52419400;
|
|
19
|
+
|
|
20
|
+
function _getMaxPolicyStorage() private pure returns (MaxPolicyStorage storage $) {
|
|
21
|
+
assembly {
|
|
22
|
+
$.slot := MaxPolicyStorageLocation
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @notice Configures the policy with a maximum threshold.
|
|
28
|
+
* @dev The `parameters` input must be the ABI encoding of a single unsigned integer (`uint256`).
|
|
29
|
+
*
|
|
30
|
+
* @param parameters ABI-encoded bytes containing a single `uint256` representing the maximum value.
|
|
31
|
+
*/
|
|
32
|
+
function configure(bytes calldata parameters) internal override onlyInitializing {
|
|
33
|
+
MaxPolicyStorage storage $ = _getMaxPolicyStorage();
|
|
34
|
+
uint256 max = abi.decode(parameters, (uint256));
|
|
35
|
+
$.max = max;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function setMax(uint256 max) public onlyOwner {
|
|
39
|
+
MaxPolicyStorage storage $ = _getMaxPolicyStorage();
|
|
40
|
+
$.max = max;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getMax() public view returns (uint256) {
|
|
44
|
+
MaxPolicyStorage storage $ = _getMaxPolicyStorage();
|
|
45
|
+
return $.max;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function run(
|
|
49
|
+
address, /*caller*/
|
|
50
|
+
address, /*subject*/
|
|
51
|
+
bytes4, /*selector*/
|
|
52
|
+
bytes[] calldata parameters,
|
|
53
|
+
bytes calldata /*context*/
|
|
54
|
+
)
|
|
55
|
+
public
|
|
56
|
+
view
|
|
57
|
+
override
|
|
58
|
+
returns (IPolicyEngine.PolicyResult)
|
|
59
|
+
{
|
|
60
|
+
// expected parameters: [size(uint256)]
|
|
61
|
+
// solhint-disable-next-line gas-custom-errors
|
|
62
|
+
if (parameters.length != 1) {
|
|
63
|
+
revert IPolicyEngine.InvalidConfiguration("expected 1 parameter");
|
|
64
|
+
}
|
|
65
|
+
uint256 size = abi.decode(parameters[0], (uint256));
|
|
66
|
+
|
|
67
|
+
MaxPolicyStorage storage $ = _getMaxPolicyStorage();
|
|
68
|
+
if (size > $.max) {
|
|
69
|
+
revert IPolicyEngine.PolicyRejected("amount exceeds maximum limit");
|
|
70
|
+
}
|
|
71
|
+
return IPolicyEngine.PolicyResult.Continue;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity 0.8.26;
|
|
3
|
+
|
|
4
|
+
import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
|
|
5
|
+
import {Policy} from "@chainlink/policy-management/core/Policy.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title OnlyAuthorizedSenderPolicy
|
|
9
|
+
* @notice A policy that rejects method calls if the sender is not on the authorized list.
|
|
10
|
+
*/
|
|
11
|
+
contract OnlyAuthorizedSenderPolicy is Policy {
|
|
12
|
+
/// @custom:storage-location erc7201:policy-management.OnlyAuthorizedSenderPolicy
|
|
13
|
+
struct OnlyAuthorizedSenderPolicyStorage {
|
|
14
|
+
/// @notice If the sender is not on this list, method calls will be rejected.
|
|
15
|
+
mapping(address account => bool isAuthorized) authorizedList;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// keccak256(abi.encode(uint256(keccak256("policy-management.OnlyAuthorizedSenderPolicy")) - 1)) &
|
|
19
|
+
// ~bytes32(uint256(0xff))
|
|
20
|
+
bytes32 private constant OnlyAuthorizedSenderPolicyStorageLocation =
|
|
21
|
+
0x55dec33488a1029cdcf3599ee8cd33d98db3bd4dac88355b9ed7e751c3fe6a00;
|
|
22
|
+
|
|
23
|
+
function _getOnlyAuthorizedSenderPolicyStorage() private pure returns (OnlyAuthorizedSenderPolicyStorage storage $) {
|
|
24
|
+
assembly {
|
|
25
|
+
$.slot := OnlyAuthorizedSenderPolicyStorageLocation
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @notice Adds the account to the authorized list.
|
|
31
|
+
* @dev Throws if the account is already in the authorized list.
|
|
32
|
+
* @param account The address to add to the authorized list.
|
|
33
|
+
*/
|
|
34
|
+
function authorizeSender(address account) public onlyOwner {
|
|
35
|
+
OnlyAuthorizedSenderPolicyStorage storage $ = _getOnlyAuthorizedSenderPolicyStorage();
|
|
36
|
+
require(!$.authorizedList[account], "Account already in authorized list");
|
|
37
|
+
$.authorizedList[account] = true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @notice Removes the account from the authorized list.
|
|
42
|
+
* @dev Throws if the account is not in the authorized list.
|
|
43
|
+
* @param account The address to remove from the authorized list.
|
|
44
|
+
*/
|
|
45
|
+
function unauthorizeSender(address account) public onlyOwner {
|
|
46
|
+
OnlyAuthorizedSenderPolicyStorage storage $ = _getOnlyAuthorizedSenderPolicyStorage();
|
|
47
|
+
require($.authorizedList[account], "Account not in authorized list");
|
|
48
|
+
$.authorizedList[account] = false;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @notice Checks if the account is on the authorized list.
|
|
53
|
+
* @param account The address to check.
|
|
54
|
+
* @return senderAuthorized if the account is on the authorized list, false otherwise.
|
|
55
|
+
*/
|
|
56
|
+
function senderAuthorized(address account) public view returns (bool) {
|
|
57
|
+
OnlyAuthorizedSenderPolicyStorage storage $ = _getOnlyAuthorizedSenderPolicyStorage();
|
|
58
|
+
return $.authorizedList[account];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @notice Function to be called by the policy engine to check if execution is allowed.
|
|
63
|
+
* @param caller The address of the sender.
|
|
64
|
+
* @return result The result of the policy check.
|
|
65
|
+
*/
|
|
66
|
+
function run(
|
|
67
|
+
address caller, /*caller*/
|
|
68
|
+
address, /*subject*/
|
|
69
|
+
bytes4, /*selector*/
|
|
70
|
+
bytes[] calldata, /*parameters*/
|
|
71
|
+
bytes calldata /*context*/
|
|
72
|
+
)
|
|
73
|
+
public
|
|
74
|
+
view
|
|
75
|
+
override
|
|
76
|
+
returns (IPolicyEngine.PolicyResult)
|
|
77
|
+
{
|
|
78
|
+
OnlyAuthorizedSenderPolicyStorage storage $ = _getOnlyAuthorizedSenderPolicyStorage();
|
|
79
|
+
if (!$.authorizedList[caller]) {
|
|
80
|
+
revert IPolicyEngine.PolicyRejected("sender is not authorized");
|
|
81
|
+
}
|
|
82
|
+
return IPolicyEngine.PolicyResult.Continue;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity 0.8.26;
|
|
3
|
+
|
|
4
|
+
import {IPolicyEngine} from "../interfaces/IPolicyEngine.sol";
|
|
5
|
+
import {Policy} from "../core/Policy.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title OnlyOwnerPolicy
|
|
9
|
+
* @notice A policy that only allows the policy owner to call the method, similar to `Ownable` from OpenZeppelin.
|
|
10
|
+
*/
|
|
11
|
+
contract OnlyOwnerPolicy is Policy {
|
|
12
|
+
function run(
|
|
13
|
+
address caller,
|
|
14
|
+
address, /*subject*/
|
|
15
|
+
bytes4, /*selector*/
|
|
16
|
+
bytes[] calldata parameters,
|
|
17
|
+
bytes calldata /*context*/
|
|
18
|
+
)
|
|
19
|
+
public
|
|
20
|
+
view
|
|
21
|
+
override
|
|
22
|
+
returns (IPolicyEngine.PolicyResult)
|
|
23
|
+
{
|
|
24
|
+
// expected parameters: none
|
|
25
|
+
// solhint-disable-next-line gas-custom-errors
|
|
26
|
+
if (parameters.length != 0) {
|
|
27
|
+
revert IPolicyEngine.InvalidConfiguration("expected 0 parameters");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (caller != owner()) {
|
|
31
|
+
revert IPolicyEngine.PolicyRejected("caller is not the policy owner");
|
|
32
|
+
}
|
|
33
|
+
return IPolicyEngine.PolicyResult.Continue;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// SPDX-License-Identifier: BUSL-1.1
|
|
2
|
+
pragma solidity 0.8.26;
|
|
3
|
+
|
|
4
|
+
import {IPolicyEngine} from "@chainlink/policy-management/interfaces/IPolicyEngine.sol";
|
|
5
|
+
import {Policy} from "@chainlink/policy-management/core/Policy.sol";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @title PausePolicy
|
|
9
|
+
* @notice A policy that can be toggled to pause or unpause execution.
|
|
10
|
+
*/
|
|
11
|
+
contract PausePolicy is Policy {
|
|
12
|
+
/// @custom:storage-location erc7201:policy-management.PausePolicy
|
|
13
|
+
struct PausePolicyStorage {
|
|
14
|
+
/// @notice Indicates whether the policy is currently paused.
|
|
15
|
+
bool paused;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// keccak256(abi.encode(uint256(keccak256("policy-management.PausePolicy")) - 1)) & ~bytes32(uint256(0xff))
|
|
19
|
+
bytes32 private constant PausePolicyStorageLocation =
|
|
20
|
+
0xaefcbf6c17ae27ba80ec8ef292ac0e1afc8fd1fc954a25eef0882c51e609eb00;
|
|
21
|
+
|
|
22
|
+
function _getPausePolicyStorage() private pure returns (PausePolicyStorage storage $) {
|
|
23
|
+
assembly {
|
|
24
|
+
$.slot := PausePolicyStorageLocation
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// @notice Returns whether the policy is currently paused.
|
|
29
|
+
function s_paused() public view returns (bool) {
|
|
30
|
+
PausePolicyStorage storage $ = _getPausePolicyStorage();
|
|
31
|
+
return $.paused;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @notice Configures the policy with a paused state.
|
|
36
|
+
* @dev This function follows OZ's initializable pattern and should be called only once.
|
|
37
|
+
* param _paused(bool) The initial paused state of the policy.
|
|
38
|
+
*/
|
|
39
|
+
function configure(bytes calldata parameters) internal override onlyInitializing {
|
|
40
|
+
PausePolicyStorage storage $ = _getPausePolicyStorage();
|
|
41
|
+
$.paused = abi.decode(parameters, (bool));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// @notice Sets the paused state of the policy.
|
|
45
|
+
function pause() public onlyOwner {
|
|
46
|
+
PausePolicyStorage storage $ = _getPausePolicyStorage();
|
|
47
|
+
require(!$.paused, "already paused");
|
|
48
|
+
$.paused = true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// @notice Sets the paused state of the policy to false.
|
|
52
|
+
function unpause() public onlyOwner {
|
|
53
|
+
PausePolicyStorage storage $ = _getPausePolicyStorage();
|
|
54
|
+
require($.paused, "already unpaused");
|
|
55
|
+
$.paused = false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @notice Function to be called by the policy engine to check if execution is allowed.
|
|
60
|
+
* @return result The result of the policy check.
|
|
61
|
+
*/
|
|
62
|
+
function run(
|
|
63
|
+
address, /*caller*/
|
|
64
|
+
address, /*subject*/
|
|
65
|
+
bytes4, /*selector*/
|
|
66
|
+
bytes[] calldata, /*parameters*/
|
|
67
|
+
bytes calldata /*context*/
|
|
68
|
+
)
|
|
69
|
+
public
|
|
70
|
+
view
|
|
71
|
+
override
|
|
72
|
+
returns (IPolicyEngine.PolicyResult)
|
|
73
|
+
{
|
|
74
|
+
// Gas optimization: load storage reference once
|
|
75
|
+
PausePolicyStorage storage $ = _getPausePolicyStorage();
|
|
76
|
+
if ($.paused) {
|
|
77
|
+
revert IPolicyEngine.PolicyRejected("contract is paused");
|
|
78
|
+
} else {
|
|
79
|
+
return IPolicyEngine.PolicyResult.Continue;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|