@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,632 @@
|
|
|
1
|
+
# Common Policies
|
|
2
|
+
|
|
3
|
+
- [AllowPolicy](#allowpolicy)
|
|
4
|
+
- [BypassPolicy](#bypasspolicy)
|
|
5
|
+
- [IntervalPolicy](#intervalpolicy)
|
|
6
|
+
- [MaxPolicy](#maxpolicy)
|
|
7
|
+
- [OnlyAuthorizedSenderPolicy](#onlyauthorizedsenderpolicy)
|
|
8
|
+
- [OnlyOwnerPolicy](#onlyownerpolicy)
|
|
9
|
+
- [PausePolicy](#pausepolicy)
|
|
10
|
+
- [RejectPolicy](#rejectpolicy)
|
|
11
|
+
- [RoleBasedAccessControlPolicy](#rolebasedaccesscontrolpolicy)
|
|
12
|
+
- [SecureMintPolicy](#securemintpolicy)
|
|
13
|
+
- [VolumePolicy](#volumepolicy)
|
|
14
|
+
- [VolumeRatePolicy](#volumeratepolicy)
|
|
15
|
+
|
|
16
|
+
## Common Initialization Pattern
|
|
17
|
+
|
|
18
|
+
All policies in this repository follow a standard initialization pattern to ensure consistent configuration and deployment.
|
|
19
|
+
|
|
20
|
+
When a policy contract is deployed, it must be properly initialized using the following two-step process:
|
|
21
|
+
|
|
22
|
+
1. initialize(address policyEngine, address initialOwner, bytes configParams)
|
|
23
|
+
|
|
24
|
+
- This function is part of the abstract Policy contract and must be called first.
|
|
25
|
+
- It initializes the core components:
|
|
26
|
+
- Sets the Policy Engine reference
|
|
27
|
+
- Assigns ownership (OwnableUpgradeable)
|
|
28
|
+
- Sets up any common inherited modules (ERC165Upgradeable, etc.)
|
|
29
|
+
|
|
30
|
+
2. configure(bytes configParams). Immediately after core initialization, the initialize function automatically calls configure(configParams).
|
|
31
|
+
- Each policy implementation defines its own logic inside configure(bytes) to handle policy-specific parameters.
|
|
32
|
+
- The configParams are expected to be ABI-encoded parameters.
|
|
33
|
+
- For example, a policy that requires a maximum transfer quota might decode a single uint256 value from configParams.
|
|
34
|
+
- Validation and state assignment happen inside configure().
|
|
35
|
+
|
|
36
|
+
Important: configure(bytes) is designed to be called only once during initialization.
|
|
37
|
+
|
|
38
|
+
## AllowPolicy
|
|
39
|
+
|
|
40
|
+
### Overview
|
|
41
|
+
|
|
42
|
+
The `AllowPolicy` implements access control through an allowlist. The policy immediately rejects the transaction if the `sender` is not on the list, halting any subsequent policy checks.
|
|
43
|
+
|
|
44
|
+
### Specific Configuration
|
|
45
|
+
|
|
46
|
+
1. **Allowlist Management**
|
|
47
|
+
|
|
48
|
+
The contract [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) can:
|
|
49
|
+
|
|
50
|
+
- **`allowSender(address account)`**: Adds `account` to the allowlist.
|
|
51
|
+
- **`disallowSender(address account)`**: Removes `account` from the allowlist.
|
|
52
|
+
|
|
53
|
+
2. **View Functions**
|
|
54
|
+
- **`senderAllowed(address account) -> bool`**: Returns `true` if `account` is on the allowlist.
|
|
55
|
+
|
|
56
|
+
### Policy Parameters and Context
|
|
57
|
+
|
|
58
|
+
This policy expects a variable number of parameters, which are the addresses to check against the allowlist. Each parameter
|
|
59
|
+
MUST be an address. If ANY of the addresses provided are NOT present in the allowlist, the transaction will be rejected.
|
|
60
|
+
|
|
61
|
+
### Policy Behavior
|
|
62
|
+
|
|
63
|
+
- **`run(...)`**
|
|
64
|
+
|
|
65
|
+
- Reverts if any of the parameters is not present on the allowlist.
|
|
66
|
+
- Returns `PolicyResult.Continue` otherwise
|
|
67
|
+
|
|
68
|
+
- **`postRun(...)`**
|
|
69
|
+
- Not implemented (no state changes required)
|
|
70
|
+
|
|
71
|
+
### Example Use Cases
|
|
72
|
+
|
|
73
|
+
- **Regulated Access**: Provide access only to a select group of addresses.
|
|
74
|
+
- **Gradual Access**: Start with a restrictive allowlist, gradually adding trusted addresses.
|
|
75
|
+
|
|
76
|
+
## BypassPolicy
|
|
77
|
+
|
|
78
|
+
### Overview
|
|
79
|
+
|
|
80
|
+
The `BypassPolicy` implements access control through an allowlist. The policy immediately allows the transaction if the `sender` is on the list, bypassing any subsequent policy checks.
|
|
81
|
+
|
|
82
|
+
### Specific Configuration
|
|
83
|
+
|
|
84
|
+
1. **Allowlist Management**
|
|
85
|
+
|
|
86
|
+
The contract [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) can:
|
|
87
|
+
|
|
88
|
+
- **`allowSender(address account)`**: Adds `account` to the allowlist.
|
|
89
|
+
- **`disallowSender(address account)`**: Removes `account` from the allowlist.
|
|
90
|
+
|
|
91
|
+
2. **View Functions**
|
|
92
|
+
- **`senderAllowed(address account) -> bool`**: Returns `true` if `account` is on the allowlist.
|
|
93
|
+
|
|
94
|
+
### Policy Parameters and Context
|
|
95
|
+
|
|
96
|
+
This policy expects a variable number of parameters, which are the addresses to check against the allowlist. Each parameter
|
|
97
|
+
MUST be an address. If ALL addresses provided are present in the allowlist, the transaction will be allowed, bypassing
|
|
98
|
+
all subsequent policies.
|
|
99
|
+
|
|
100
|
+
### Policy Behavior
|
|
101
|
+
|
|
102
|
+
- **`run(...)`**
|
|
103
|
+
|
|
104
|
+
- Returns `PolicyResult.Allowed` if all parameters are present on the allowlist
|
|
105
|
+
- Returns `PolicyResult.Continue` otherwise
|
|
106
|
+
|
|
107
|
+
- **`postRun(...)`**
|
|
108
|
+
- Not implemented (no state changes required)
|
|
109
|
+
|
|
110
|
+
### Example Use Cases
|
|
111
|
+
|
|
112
|
+
- **Privileged Access**: Allow specific addresses to bypass other policy checks.
|
|
113
|
+
- **Layered Permissions**: Combine with other policies—e.g., the transaction proceeds as normal unless the caller is on the allowlist.
|
|
114
|
+
|
|
115
|
+
## IntervalPolicy
|
|
116
|
+
|
|
117
|
+
### Overview
|
|
118
|
+
|
|
119
|
+
The `IntervalPolicy` limits transaction execution to specific **time slots** within a **repeating cycle**. The policy accepts or rejects transactions based on whether the **current slot** (derived from block time) falls within a configured **start slot** and **end slot**.
|
|
120
|
+
|
|
121
|
+
### Specific Configuration
|
|
122
|
+
|
|
123
|
+
- **Slot Duration (`s_slotDuration`)**
|
|
124
|
+
The length of each slot in seconds (e.g., `3600` for 1 hour, `86400` for 1 day).
|
|
125
|
+
|
|
126
|
+
- **Cycle Size (`s_cycleSize`)**
|
|
127
|
+
The total number of slots in each repeating cycle (e.g., `24` slots for 24 hours in a day, `7` slots for days in a week).
|
|
128
|
+
|
|
129
|
+
- **Cycle Offset (`s_cycleOffset`)**
|
|
130
|
+
An offset (in slots) added after computing the raw current slot. This shifts where slot `0` is effectively located in each cycle.
|
|
131
|
+
|
|
132
|
+
- **Start Slot (`s_startSlot`)** and **End Slot (`s_endSlot`)**
|
|
133
|
+
The inclusive and exclusive slot indices (within `[0, s_cycleSize)`) that define when transactions are permitted. A transaction is allowed only if the computed current slot is in `[s_startSlot, s_endSlot)`.
|
|
134
|
+
|
|
135
|
+
These values can be set in the constructor or changed by the contract [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) via:
|
|
136
|
+
|
|
137
|
+
- `setStartSlot(uint256 _startSlot)`
|
|
138
|
+
- `setEndSlot(uint256 _endSlot)`
|
|
139
|
+
- `setCycleParameters(uint256 _slotDuration, uint256 _cycleSize, uint256 _cycleOffset)`
|
|
140
|
+
|
|
141
|
+
### Policy Parameters
|
|
142
|
+
|
|
143
|
+
| Parameter Name | Type | Description |
|
|
144
|
+
| --------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
145
|
+
| _No parameters_ | _N/A_ | The policy does not decode or use any parameters from the Extractor/Mapper. It relies solely on `block.timestamp` and its configured slot cycle to make decisions. |
|
|
146
|
+
|
|
147
|
+
Because `IntervalPolicy` ignores the `parameters` array passed into `run(...)`, it only uses the current block timestamp, combined with `s_slotDuration`, `s_cycleSize`, `s_cycleOffset`, etc., to determine if the transaction falls within the allowed slot range.
|
|
148
|
+
|
|
149
|
+
### Policy Behavior
|
|
150
|
+
|
|
151
|
+
- **`run(...)`**
|
|
152
|
+
|
|
153
|
+
1. Computes the current slot as:
|
|
154
|
+
```solidity
|
|
155
|
+
uint256 currentSlot =
|
|
156
|
+
((block.timestamp / s_slotDuration) % s_cycleSize + s_cycleOffset) % s_cycleSize;
|
|
157
|
+
```
|
|
158
|
+
2. Returns `PolicyResult.Continue` if `currentSlot` is within `[s_startSlot, s_endSlot)`, otherwise reverts.
|
|
159
|
+
|
|
160
|
+
- **`postRun(...)`**
|
|
161
|
+
- Not used in this policy (no state changes needed after `run`).
|
|
162
|
+
|
|
163
|
+
### Configuration Examples
|
|
164
|
+
|
|
165
|
+
1. **Daily Business Hours (9 AM - 5 PM UTC)**
|
|
166
|
+
|
|
167
|
+
```solidity
|
|
168
|
+
new IntervalPolicy(
|
|
169
|
+
9, // startSlot = 9
|
|
170
|
+
17, // endSlot = 17
|
|
171
|
+
3600, // 1-hour slot duration
|
|
172
|
+
24, // 24 slots in each daily cycle
|
|
173
|
+
0 // no cycle offset
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
2. **Weekday Operations (Monday-Friday)**
|
|
179
|
+
```solidity
|
|
180
|
+
new IntervalPolicy(
|
|
181
|
+
1, // startSlot = 1 (Monday)
|
|
182
|
+
6, // endSlot = 6 (Saturday, but exclusive -> stops before Saturday)
|
|
183
|
+
86400, // 1-day slot duration
|
|
184
|
+
7, // 7 slots in each weekly cycle
|
|
185
|
+
0 // no cycle offset
|
|
186
|
+
);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Example Use Cases
|
|
190
|
+
|
|
191
|
+
- **Hourly or Daily Windows**: Permit specific hours in the day (e.g., 9 AM to 5 PM).
|
|
192
|
+
- **Weekly or Monthly Cycles**: Restrict transactions to certain days of the week or specific days in a month.
|
|
193
|
+
- **Maintenance Windows**: Automatically disallow transactions outside scheduled operating hours.
|
|
194
|
+
|
|
195
|
+
## MaxPolicy
|
|
196
|
+
|
|
197
|
+
### Overview
|
|
198
|
+
|
|
199
|
+
The `MaxPolicy` enforces a maximum value constraint. The policy compares a provided usage value against a configured maximum and rejects transactions that would exceed this limit.
|
|
200
|
+
|
|
201
|
+
For example, to enforce a maximum transfer amount of 1000 tokens:
|
|
202
|
+
|
|
203
|
+
```solidity
|
|
204
|
+
// Create policy that caps transfers at 1000 tokens
|
|
205
|
+
MaxPolicy transferCapPolicy = new MaxPolicy();
|
|
206
|
+
policy.initialize(address(policyEngine), owner, abi.encode(1000));
|
|
207
|
+
|
|
208
|
+
// Usage:
|
|
209
|
+
// used <= 1000: PolicyResult.Continue
|
|
210
|
+
// used > 1000: revert
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Specific Configuration
|
|
214
|
+
|
|
215
|
+
1. **Deployment Parameter**
|
|
216
|
+
|
|
217
|
+
- **`uint256 max`**: The initial maximum. If a transaction's `amount` (`uint256`) value exceeds this value, the policy rejects the transaction.
|
|
218
|
+
|
|
219
|
+
2. **Owner Controls**
|
|
220
|
+
|
|
221
|
+
- **`setMax(uint256 max)`**: Updates the maximum.
|
|
222
|
+
- **`getMax()`**: Returns the current maximum.
|
|
223
|
+
|
|
224
|
+
The contract [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) manages these functions.
|
|
225
|
+
|
|
226
|
+
### Policy Parameters
|
|
227
|
+
|
|
228
|
+
| Parameter Name | Type | Description |
|
|
229
|
+
| -------------- | --------- | ----------------------------------------------- |
|
|
230
|
+
| `amount` | `uint256` | A usage value that must not exceed the maximum. |
|
|
231
|
+
|
|
232
|
+
No additional `context` is required.
|
|
233
|
+
|
|
234
|
+
### Policy Behavior
|
|
235
|
+
|
|
236
|
+
- **`run(...)`**
|
|
237
|
+
|
|
238
|
+
- Expects exactly one parameter, `amount` (`uint256`).
|
|
239
|
+
- Compares `amount` to the current `s_max`.
|
|
240
|
+
- Reverts if `amount > s_max`.
|
|
241
|
+
- Returns `PolicyResult.Continue` otherwise.
|
|
242
|
+
|
|
243
|
+
- **`postRun(...)`**
|
|
244
|
+
- Not implemented (no state changes required).
|
|
245
|
+
|
|
246
|
+
### Example Use Cases
|
|
247
|
+
|
|
248
|
+
- **API Call Limits**: Restrict the number of calls or resource usage per transaction.
|
|
249
|
+
- **Token Spending Caps**: Enforce that a user does not exceed a certain token allowance in a single operation.
|
|
250
|
+
- **Resource Quotas**: Limit the maximum usage of onchain functionality in a one-off or per-transaction basis.
|
|
251
|
+
|
|
252
|
+
## OnlyAuthorizedSenderPolicy
|
|
253
|
+
|
|
254
|
+
### Overview
|
|
255
|
+
|
|
256
|
+
The `OnlyAuthorizedSenderPolicy` implements access control through an authorized list. The policy rejects the transaction if the `sender` is **NOT** on the list.
|
|
257
|
+
|
|
258
|
+
### Specific Configuration
|
|
259
|
+
|
|
260
|
+
1. **Authorized List Management**
|
|
261
|
+
|
|
262
|
+
The contract [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) can:
|
|
263
|
+
|
|
264
|
+
- **`authorizeSender(address account)`**: Adds `account` to the authorized list.
|
|
265
|
+
- **`unauthorizeSender(address account)`**: Removes `account` from the authorized list.
|
|
266
|
+
|
|
267
|
+
2. **View Functions**
|
|
268
|
+
- **`senderAuthorized(address account) -> bool`**: Returns `true` if `account` is on the authorized list.
|
|
269
|
+
|
|
270
|
+
### Policy Parameters and Context
|
|
271
|
+
|
|
272
|
+
| Parameter Name | Type | Description |
|
|
273
|
+
| --------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
274
|
+
| _No parameters_ | _N/A_ | This policy does **not** require any parameters from the Policy Engine's configured Extractor and Mapper. It checks `sender` directly. |
|
|
275
|
+
|
|
276
|
+
### Policy Behavior
|
|
277
|
+
|
|
278
|
+
- **`run(...)`**
|
|
279
|
+
|
|
280
|
+
- Returns `PolicyResult.Continue` if `sender` is on the authorized list
|
|
281
|
+
- Reverts otherwise
|
|
282
|
+
|
|
283
|
+
- **`postRun(...)`**
|
|
284
|
+
- Not implemented (no state changes required)
|
|
285
|
+
|
|
286
|
+
### Example Use Cases
|
|
287
|
+
|
|
288
|
+
- **Restricted Access**: Only allow specific addresses operate the contract methods.
|
|
289
|
+
|
|
290
|
+
## OnlyOwnerPolicy
|
|
291
|
+
|
|
292
|
+
### Overview
|
|
293
|
+
|
|
294
|
+
The `OnlyOwnerPolicy` that only allows the policy owner to call the method, similar to `Ownable` from OpenZeppelin.
|
|
295
|
+
|
|
296
|
+
### Policy Parameters and Context
|
|
297
|
+
|
|
298
|
+
| Parameter Name | Type | Description |
|
|
299
|
+
| --------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
300
|
+
| _No parameters_ | _N/A_ | This policy does **not** require any parameters from the Policy Engine's configured Extractor and Mapper. It checks `sender` directly. |
|
|
301
|
+
|
|
302
|
+
### Policy Behavior
|
|
303
|
+
|
|
304
|
+
- **`run(...)`**
|
|
305
|
+
|
|
306
|
+
- Returns `PolicyResult.Continue` if `sender` is the owner of the policy
|
|
307
|
+
- Reverts otherwise
|
|
308
|
+
|
|
309
|
+
- **`postRun(...)`**
|
|
310
|
+
- Not implemented (no state changes required)
|
|
311
|
+
|
|
312
|
+
### Example Use Cases
|
|
313
|
+
|
|
314
|
+
- **Restricted Access**: Only allow contract deployer to operate the contract methods.
|
|
315
|
+
|
|
316
|
+
## PausePolicy
|
|
317
|
+
|
|
318
|
+
### Overview
|
|
319
|
+
|
|
320
|
+
The `PausePolicy` allows an [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) to enable or disable ("pause") all transactions. When the policy is paused, all incoming transactions will be rejected. When unpaused, the policy defers the decision (returns `PolicyResult.Continue`) so that other policies or the default policy engine logic can take effect.
|
|
321
|
+
|
|
322
|
+
### Specific Configuration
|
|
323
|
+
|
|
324
|
+
1. **Deployment Parameter**
|
|
325
|
+
|
|
326
|
+
- **`bool _paused`**: The initial pause state. If set to `true`, the policy starts off rejecting all transactions. If `false`, it starts in a "normal" state allowing transactions to continue.
|
|
327
|
+
|
|
328
|
+
2. **Owner Controls**
|
|
329
|
+
|
|
330
|
+
- **`pause()`**: Sets the policy to a paused state (`s_paused = true`), rejecting all subsequent transactions.
|
|
331
|
+
- **`unpause()`**: Resets the policy to an unpaused state (`s_paused = false`), allowing transactions to continue.
|
|
332
|
+
|
|
333
|
+
### Policy Parameters
|
|
334
|
+
|
|
335
|
+
| Parameter Name | Type | Description |
|
|
336
|
+
| --------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
337
|
+
| _No parameters_ | _N/A_ | The policy does not inspect or decode parameters from the Extractor/Mapper. It relies solely on its internal pause flag (`s_paused`) to decide whether to reject or continue a transaction. |
|
|
338
|
+
|
|
339
|
+
Since `PausePolicy` ignores the `parameters` array passed into `run(...)`, it uses the `s_paused` boolean to immediately reverts when paused, or defer (`PolicyResult.Continue`) when unpaused.
|
|
340
|
+
|
|
341
|
+
### Policy Behavior
|
|
342
|
+
|
|
343
|
+
- **`run(...)`**
|
|
344
|
+
- Reverts if `s_paused == true`.
|
|
345
|
+
- Returns `PolicyResult.Continue` if `s_paused == false`.
|
|
346
|
+
|
|
347
|
+
### Example Use Cases
|
|
348
|
+
|
|
349
|
+
- **Emergency Stop**: Quickly block all sensitive functions in a contract during an emergency or maintenance window.
|
|
350
|
+
- **Maintenance Mode**: Temporarily pause interactions for upgrades or migrations.
|
|
351
|
+
- **Gradual Rollout**: Deploy paused, then activate when ready.
|
|
352
|
+
|
|
353
|
+
## RejectPolicy
|
|
354
|
+
|
|
355
|
+
### Overview
|
|
356
|
+
|
|
357
|
+
The `RejectPolicy` implements access control through a denylist. The policy immediately rejects the transaction if one of the supplied addresses is on the denylist, halting any subsequent policy checks.
|
|
358
|
+
|
|
359
|
+
### Specific Configuration
|
|
360
|
+
|
|
361
|
+
1. **Denylist Management**
|
|
362
|
+
|
|
363
|
+
The contract [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) can:
|
|
364
|
+
|
|
365
|
+
- **`rejectAddress(address account)`**: Adds `account` to the denylist.
|
|
366
|
+
- **`unrejectAddress(address account)`**: Removes `account` from the denylist.
|
|
367
|
+
|
|
368
|
+
2. **View Functions**
|
|
369
|
+
- **`addressRejected(address account) -> bool`**: Returns `true` if `account` is on the denylist.
|
|
370
|
+
|
|
371
|
+
### Policy Parameters and Context
|
|
372
|
+
|
|
373
|
+
This policy expects a variable number of parameters, which are the addresses to check against the denylist. Each parameter
|
|
374
|
+
MUST be an address. If ANY of the addresses provided are present in the denylist, the transaction will be rejected.
|
|
375
|
+
|
|
376
|
+
### Policy Behavior
|
|
377
|
+
|
|
378
|
+
- **`run(...)`**
|
|
379
|
+
|
|
380
|
+
- Reverts if any of the parameters is present on the denylist.
|
|
381
|
+
- Returns `PolicyResult.Continue` otherwise
|
|
382
|
+
|
|
383
|
+
- **`postRun(...)`**
|
|
384
|
+
- Not implemented (no state changes required)
|
|
385
|
+
|
|
386
|
+
### Example Use Cases
|
|
387
|
+
|
|
388
|
+
- **Account Blocking**: Block malicious addresses, such as known hackers or compromised accounts.
|
|
389
|
+
|
|
390
|
+
## RoleBasedAccessControlPolicy
|
|
391
|
+
|
|
392
|
+
### Overview
|
|
393
|
+
|
|
394
|
+
The `RoleBasedAccessControlPolicy` utilize [OpenZeppelin's `AccessControlUpgradeable`](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/access/AccessControlUpgradeable.sol) to implement a flexible role-based access control system.
|
|
395
|
+
|
|
396
|
+
For example, to manage a transfer operation:
|
|
397
|
+
|
|
398
|
+
```solidity
|
|
399
|
+
bytes4 TRANSFER_SELECTOR = bytes4(keccak256("transfer(address,uint256)"));
|
|
400
|
+
bytes32 ADMIN_ROLE = keccak256("ADMIN_ROLE");
|
|
401
|
+
|
|
402
|
+
RoleBasedAccessControlPolicy policy = new RoleBasedAccessControlPolicy();
|
|
403
|
+
|
|
404
|
+
policy.grantRole(ADMIN_ROLE, bob);
|
|
405
|
+
policy.grantOperationAllowanceToRole(TRANSFER_SELECTOR, ADMIN_ROLE);
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
A transaction proceeds only if the sender holds a role that has been granted permission for the operation.
|
|
409
|
+
|
|
410
|
+
### Specific Configuration
|
|
411
|
+
|
|
412
|
+
1. **Role-Based Operation Allowance**
|
|
413
|
+
|
|
414
|
+
- **`grantOperationAllowanceToRole(bytes4 operation, bytes32 role)`**: Adds a role to the list of roles that can perform the operation.
|
|
415
|
+
- **`removeOperationAllowanceFromRole(bytes4 operation, bytes32 role)`**: Removes a role from that list.
|
|
416
|
+
|
|
417
|
+
2. **Account Role Management**
|
|
418
|
+
|
|
419
|
+
- **`grantRole(bytes32 role, address account)`**: Assigns a role to a specific account.
|
|
420
|
+
- **`revokeRole(bytes32 role, address account)`**: Revokes a role from an account.
|
|
421
|
+
|
|
422
|
+
3. **View Functions**
|
|
423
|
+
- **`hasAllowedRole(bytes4 operation, address account) -> bool`**: Checks if the account has any of the roles that are allowed to perform the operation.
|
|
424
|
+
- **`supportsInterface(bytes4 interfaceId) -> bool`**: Implements ERC165-style interface detection (inherited from `AccessControl` and `Policy`).
|
|
425
|
+
|
|
426
|
+
### Policy Parameters
|
|
427
|
+
|
|
428
|
+
| Parameter Name | Type | Description |
|
|
429
|
+
| --------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
|
430
|
+
| _No parameters_ | _N/A_ | This policy does **not** require any parameters from the Policy Engine's configured Extractor and Mapper. It checks `sender` directly. |
|
|
431
|
+
|
|
432
|
+
No additional `context` is used or expected.
|
|
433
|
+
|
|
434
|
+
### Policy Behavior
|
|
435
|
+
|
|
436
|
+
- **`run(...)`**
|
|
437
|
+
|
|
438
|
+
- Extracts the `operation (bytes4)` from the single parameter.
|
|
439
|
+
- Checks whether the `sender` holds one of the roles with allowance for the `operation`.
|
|
440
|
+
- If `hasAllowedRole` is `false`, reverts; otherwise, returns `PolicyResult.Continue`.
|
|
441
|
+
|
|
442
|
+
- **`postRun(...)`**
|
|
443
|
+
- Not implemented in this policy (no state changes after `run`).
|
|
444
|
+
|
|
445
|
+
### Example Use Cases
|
|
446
|
+
|
|
447
|
+
- **Granular Function Permissions**: Each `operation` corresponds to a function selector. Certain roles can call only specific functions.
|
|
448
|
+
- **Decentralized Team Management**: Owner can quickly grant or revoke privileges to multiple operations across multiple roles.
|
|
449
|
+
|
|
450
|
+
## SecureMintPolicy
|
|
451
|
+
|
|
452
|
+
### Overview
|
|
453
|
+
|
|
454
|
+
The `SecureMintPolicy` ensures the total supply of a token does not exceed the actual reserves of the underlying asset. It retrieves reserves data from a Chainlink Proof of Reserve contract (or any contract compatible with the Data Feed interface) and compares it against the total supply of the token.
|
|
455
|
+
|
|
456
|
+
### Specific Configuration
|
|
457
|
+
|
|
458
|
+
1. **Reserves Feed**
|
|
459
|
+
|
|
460
|
+
- **`setReservesFeed(address reservesFeed)`**: Updates the Chainlink data feed used for reserve validation.
|
|
461
|
+
|
|
462
|
+
2. **Reserve Margin**
|
|
463
|
+
|
|
464
|
+
- **`enum ReserveMarginMode`**
|
|
465
|
+
- `None`: No reserve margin. Policy will compare total supply against reserves directly.
|
|
466
|
+
- `PositivePercentage`: Reserve margin is a positive percentage of the reserves, meaning total supply must be less than the reserves by a certain amount. e.g. If reserves = 1000 and margin = 10%, then total supply must be less than 900.
|
|
467
|
+
- `PositiveAbsolute`: Reserve margin is a positive absolute value. e.g. If reserves = 1000 and margin = 50, then total supply must be less than 950.
|
|
468
|
+
- `NegativePercentage`: Reserve margin is a negative percentage of the reserves, meaning total supply limit is greater than the reserves by a certain amount. e.g. If reserves = 1000 and margin = -10%, then total supply limit will be 1100.
|
|
469
|
+
- `NegativeAbsolute`: Reserve margin is a negative absolute value. e.g. If reserves = 1000 and margin = -50, then total supply limit will be 1050.
|
|
470
|
+
- **`setReserveMargin(ReserveMarginMode mode, uint256 amount)`**: Sets the reserve margin mode and amount. If the reserveMarginMode is percentage-based, amount will be interpreted as hundredths of a percent (e.g. 12.34% = 1234).
|
|
471
|
+
|
|
472
|
+
3. **Reserve Staleness**
|
|
473
|
+
|
|
474
|
+
- **`setMaxStalenessSeconds(uint256 value)`**: Set the maximum staleness of the reserves data. Set to 0 to accept infinite staleness. If the data is older than this value, the policy will reject the transaction.
|
|
475
|
+
|
|
476
|
+
4. **View Functions**
|
|
477
|
+
|
|
478
|
+
- **`reservesFeed() -> address`**: Returns the current reserves feed address.
|
|
479
|
+
- **`maxStalenessSeconds() -> uint256`**: Returns the current maximum staleness value.
|
|
480
|
+
- **`reserveMarginMode() -> ReserveMarginMode`**: Returns the current reserve margin mode.
|
|
481
|
+
- **`reserveMarginAmount() -> uint256`**: Returns the current reserve margin amount.
|
|
482
|
+
|
|
483
|
+
### Policy Parameters
|
|
484
|
+
|
|
485
|
+
| Parameter Name | Type | Description |
|
|
486
|
+
| --- | --- | --- |
|
|
487
|
+
| `reservesFeed` | `address` | The address of the Chainlink Data Feed contract. |
|
|
488
|
+
| `reserveMarginMode` | `ReserveMarginMode` | The reserve margin mode. |
|
|
489
|
+
| `reserveMarginAmount` | `uint256` | The reserve margin amount. Interpreted as hundredths of a percent if `reserveMarginMode` is percentage-based. |
|
|
490
|
+
| `maxStalenessSeconds` | `uint256` | The maximum staleness of the reserves data. |
|
|
491
|
+
|
|
492
|
+
### Policy Behavior
|
|
493
|
+
|
|
494
|
+
- **`run(...)`**
|
|
495
|
+
|
|
496
|
+
- Extracts the `amount (uint256)` from parameters.
|
|
497
|
+
- Get latest reserves data from the reserves feed.
|
|
498
|
+
- If `maxStalenessSeconds` is not 0 and the data is older than this value, revert.
|
|
499
|
+
- Calculates the total backed supply of the token using the reserves value, `reserveMarginMode` and `reserveMarginAmount`.
|
|
500
|
+
- If the total supply of the token is greater than the backed supply, revert.
|
|
501
|
+
- If the total supply of the token is less than or equal to the backed supply, returns `PolicyResult.Continue`.
|
|
502
|
+
|
|
503
|
+
- **`postRun(...)`**
|
|
504
|
+
- Not implemented in this policy (no state changes after `run`).
|
|
505
|
+
|
|
506
|
+
### Example Use Cases
|
|
507
|
+
- **Collateralized Token Minting**: Ensure that the total supply of a token does not exceed the actual reserves of the underlying asset.
|
|
508
|
+
|
|
509
|
+
## VolumePolicy
|
|
510
|
+
|
|
511
|
+
#### Overview
|
|
512
|
+
|
|
513
|
+
The `VolumePolicy` enforces minimum and maximum value constraints. The policy compares a provided amount against configured bounds and rejects transactions that fall outside these limits.
|
|
514
|
+
|
|
515
|
+
For example, to limit transfers between 100 and 1000 tokens:
|
|
516
|
+
|
|
517
|
+
```solidity
|
|
518
|
+
VolumePolicy volumePolicy = new VolumePolicy();
|
|
519
|
+
volumePolicy.setMin(100); // Minimum amount allowed
|
|
520
|
+
volumePolicy.setMax(1000); // Maximum amount allowed (0 means no upper limit)
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Specific Configuration
|
|
524
|
+
|
|
525
|
+
1. **Minimum / Maximum Amount**
|
|
526
|
+
|
|
527
|
+
- **`s_minAmount`**: The minimum allowed amount.
|
|
528
|
+
- **`s_maxAmount`**: The maximum allowed amount (0 indicates no maximum limit).
|
|
529
|
+
|
|
530
|
+
2. **Owner Controls**
|
|
531
|
+
|
|
532
|
+
The contract [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) can:
|
|
533
|
+
|
|
534
|
+
- **`setMin(uint256 minAmount)`**: Updates the minimum allowed amount. Must be strictly less than the current max (unless max is 0).
|
|
535
|
+
- **`setMax(uint256 maxAmount)`**: Updates the maximum allowed amount. Must be strictly greater than the current min (unless min is 0).
|
|
536
|
+
|
|
537
|
+
3. **View Functions**
|
|
538
|
+
- **`getMax() -> uint256`**: Returns the current maximum amount.
|
|
539
|
+
- **`getMin() -> uint256`**: Returns the current minimum amount.
|
|
540
|
+
|
|
541
|
+
### Policy Parameters
|
|
542
|
+
|
|
543
|
+
The **VolumePolicy** expects **one** parameter in the `parameters` array:
|
|
544
|
+
|
|
545
|
+
| Parameter Name | Type | Description |
|
|
546
|
+
| -------------- | --------- | ------------------------------------------------------------------- |
|
|
547
|
+
| `amount` | `uint256` | The numeric value to check against `s_minAmount` and `s_maxAmount`. |
|
|
548
|
+
|
|
549
|
+
The policy expects no additional context.
|
|
550
|
+
|
|
551
|
+
### Policy Behavior
|
|
552
|
+
|
|
553
|
+
- **`run(...)`**
|
|
554
|
+
|
|
555
|
+
- Validates parameter count equals 1
|
|
556
|
+
- Decodes the parameter: `amount (uint256)`.
|
|
557
|
+
- If `amount < s_minAmount` **or** `amount > s_maxAmount` (when `s_maxAmount != 0`), reverts.
|
|
558
|
+
- Otherwise, returns `PolicyResult.Continue`.
|
|
559
|
+
|
|
560
|
+
- **`postRun(...)`**
|
|
561
|
+
- Not used in this policy (no state changes after `run`).
|
|
562
|
+
|
|
563
|
+
### Example Use Cases
|
|
564
|
+
|
|
565
|
+
- **Purchase Limits**: Restrict transaction amounts to a certain range.
|
|
566
|
+
- **Rate Controls**: Ensure that any single transaction doesn’t fall below a minimum or exceed a maximum allowed value.
|
|
567
|
+
- **Resource/Token-Transfer Rules**: Protect a system from extremely small or large transfers that could be disruptive.
|
|
568
|
+
|
|
569
|
+
## VolumeRatePolicy
|
|
570
|
+
|
|
571
|
+
### Overview
|
|
572
|
+
|
|
573
|
+
The `VolumeRatePolicy` enforces per-account volume limits within configurable time periods. The policy tracks cumulative amounts and rejects transactions that would exceed the maximum allowed volume in the current period.
|
|
574
|
+
|
|
575
|
+
For example, to limit transfers to 1000 tokens per hour:
|
|
576
|
+
|
|
577
|
+
```solidity
|
|
578
|
+
// Create policy with 1-hour period and 1000 token limit
|
|
579
|
+
VolumeRatePolicy policy = new VolumeRatePolicy(
|
|
580
|
+
3600, // Time period (1 hour in seconds)
|
|
581
|
+
1000 // Max amount per period
|
|
582
|
+
);
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### Specific Configuration
|
|
586
|
+
|
|
587
|
+
1. **Time Period (`s_timePeriod`)**
|
|
588
|
+
|
|
589
|
+
- The duration (in seconds) of a repeating window (e.g., 3600 for hourly).
|
|
590
|
+
|
|
591
|
+
2. **Max Amount (`s_maxAmount`)**
|
|
592
|
+
|
|
593
|
+
- The upper bound on total volume permitted per account in each time period.
|
|
594
|
+
- If a transaction plus the existing volume in the current time period exceeds this limit, the policy rejects the transaction.
|
|
595
|
+
|
|
596
|
+
3. **Owner Controls**
|
|
597
|
+
The contract [owner](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) can:
|
|
598
|
+
|
|
599
|
+
- **`setMaxAmount(uint256 _maxAmount)`**: Updates the maximum volume limit.
|
|
600
|
+
- **`setTimePeriod(uint256 _timePeriod)`**: Updates the time period length in seconds.
|
|
601
|
+
- **`getMaxAmount()`** / **`getTimePeriod()`**: View functions for the current configuration.
|
|
602
|
+
|
|
603
|
+
### Policy Parameters
|
|
604
|
+
|
|
605
|
+
The **VolumeRatePolicy** expects exactly **two** parameters in the `parameters` array, in this order:
|
|
606
|
+
|
|
607
|
+
| Parameter Name | Type | Description |
|
|
608
|
+
| -------------- | --------- | -------------------------------------------- |
|
|
609
|
+
| `amount` | `uint256` | The amount being transferred. |
|
|
610
|
+
| `account` | `address` | The address for which the volume is tracked. |
|
|
611
|
+
|
|
612
|
+
No additional `context` is used.
|
|
613
|
+
|
|
614
|
+
### Policy Behavior
|
|
615
|
+
|
|
616
|
+
1. **`run(...)`**
|
|
617
|
+
|
|
618
|
+
- Validates parameter count equals 2.
|
|
619
|
+
- Derives the current time period (`currentPeriod = block.timestamp / s_timePeriod`).
|
|
620
|
+
- Compares the stored `timePeriod` and `amount` for `account` against the `currentPeriod` and the incoming `amount`.
|
|
621
|
+
- If the current period matches, checks whether `existingVolume + newAmount` exceeds `s_maxAmount`. If so, reverts; else, `PolicyResult.Continue`.
|
|
622
|
+
- If the period is new for this account and `newAmount` exceeds `s_maxAmount`, reverts; otherwise, `PolicyResult.Continue`.
|
|
623
|
+
|
|
624
|
+
2. **`postRun(...)`**
|
|
625
|
+
- If the transaction wasn’t rejected, updates the stored record for that account in the current time period by adding `amount`.
|
|
626
|
+
- If this is a new period, the policy resets the stored amount to `amount`.
|
|
627
|
+
|
|
628
|
+
### Example Use Cases
|
|
629
|
+
|
|
630
|
+
- **Rate Limiting**: Enforce maximum transfer amounts per hour/day
|
|
631
|
+
- **Usage Quotas**: Prevent resource exhaustion by single accounts
|
|
632
|
+
- **Compliance**: Implement regulatory transfer limits per time window
|